From e1599b0ce6f4f545e4363863ff4f592271300b3c Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Wed, 27 Nov 2019 12:13:46 +0000 Subject: [PATCH] New upstream version 1.39.0+dfsg1 --- Cargo.lock | 4275 ++++++------ Cargo.toml | 1 + README.md | 18 +- RELEASES.md | 136 +- config.toml.example | 11 +- git-commit-hash | 2 +- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/bin/main.rs | 3 - src/bootstrap/bin/rustc.rs | 199 +- src/bootstrap/bin/rustdoc.rs | 8 +- src/bootstrap/bootstrap.py | 49 +- src/bootstrap/builder.rs | 392 +- src/bootstrap/builder/tests.rs | 153 +- src/bootstrap/cc_detect.rs | 2 +- src/bootstrap/channel.rs | 2 +- src/bootstrap/check.rs | 82 +- src/bootstrap/compile.rs | 235 +- src/bootstrap/config.rs | 8 +- src/bootstrap/dist.rs | 103 +- src/bootstrap/doc.rs | 141 +- src/bootstrap/flags.rs | 6 +- src/bootstrap/install.rs | 3 +- src/bootstrap/lib.rs | 23 +- src/bootstrap/mk/Makefile.in | 9 + src/bootstrap/native.rs | 27 +- src/bootstrap/sanity.rs | 4 - src/bootstrap/test.rs | 108 +- src/bootstrap/tool.rs | 55 +- src/build_helper/lib.rs | 5 +- src/ci/azure-pipelines/auto.yml | 19 +- .../steps/install-windows-build-deps.yml | 77 +- src/ci/azure-pipelines/steps/run.yml | 9 +- src/ci/docker/README.md | 9 +- src/ci/docker/dist-armv7-linux/Dockerfile | 8 +- .../armv7-linux-gnueabihf.config | 799 ++- .../docker/dist-armv7-linux/crosstool-ng.sh | 12 + .../001-arm-libgcc_s_resume-used.patch | 48 - .../dist-i586-gnu-i586-i686-musl/Dockerfile | 1 - src/ci/docker/dist-various-1/Dockerfile | 6 +- src/ci/docker/dist-x86_64-linux/build-curl.sh | 6 +- src/ci/docker/i686-gnu-nopt/Dockerfile | 3 + src/ci/docker/i686-gnu/Dockerfile | 3 + src/ci/docker/scripts/cross-apt-packages.sh | 1 + src/ci/docker/scripts/musl-toolchain.sh | 26 - src/ci/docker/scripts/musl.sh | 26 +- src/ci/run.sh | 15 + src/doc/book/.travis.yml | 2 +- src/doc/book/README.md | 2 +- src/doc/book/src/appendix-01-keywords.md | 1 + .../src/ch02-00-guessing-game-tutorial.md | 2 +- .../src/ch03-01-variables-and-mutability.md | 2 +- src/doc/book/src/ch03-05-control-flow.md | 4 +- src/doc/book/src/ch04-01-what-is-ownership.md | 6 +- .../src/ch04-02-references-and-borrowing.md | 2 +- src/doc/book/src/ch05-02-example-structs.md | 4 +- ...g-paths-into-scope-with-the-use-keyword.md | 14 +- .../ch09-02-recoverable-errors-with-result.md | 4 +- src/doc/book/src/ch10-01-syntax.md | 4 +- src/doc/book/src/ch11-03-test-organization.md | 2 +- src/doc/book/src/ch13-01-closures.md | 2 +- src/doc/book/src/ch14-01-release-profiles.md | 2 +- src/doc/book/src/ch15-02-deref.md | 2 +- src/doc/book/src/ch16-02-message-passing.md | 3 +- src/doc/book/src/ch16-03-shared-state.md | 2 +- .../book/src/ch17-03-oo-design-patterns.md | 2 +- src/doc/book/src/ch18-03-pattern-syntax.md | 20 +- src/doc/book/src/ch19-01-unsafe-rust.md | 1 + src/doc/book/src/ch20-02-multithreaded.md | 2 +- src/doc/book/src/title-page.md | 2 +- src/doc/book/tools/src/bin/lfp.rs | 2 +- src/doc/embedded-book/ci/install.sh | 5 +- .../embedded-book/src/start/semihosting.md | 13 + src/doc/nomicon/src/exotic-sizes.md | 11 +- src/doc/nomicon/src/subtyping.md | 2 +- src/doc/nomicon/src/transmutes.md | 2 +- src/doc/nomicon/src/unchecked-uninit.md | 178 +- src/doc/nomicon/src/vec.md | 2 +- src/doc/nomicon/src/what-unsafe-does.md | 45 +- src/doc/reference/src/SUMMARY.md | 1 + src/doc/reference/src/abi.md | 2 +- src/doc/reference/src/attributes.md | 2 +- .../src/behavior-considered-undefined.md | 66 +- .../reference/src/conditional-compilation.md | 4 +- src/doc/reference/src/const_eval.md | 7 +- .../reference/src/crates-and-source-files.md | 2 +- .../reference/src/dynamically-sized-types.md | 2 +- src/doc/reference/src/expressions.md | 6 +- .../reference/src/expressions/await-expr.md | 68 + .../reference/src/expressions/block-expr.md | 70 +- .../reference/src/expressions/loop-expr.md | 12 +- .../src/expressions/operator-expr.md | 30 +- src/doc/reference/src/influences.md | 2 +- src/doc/reference/src/introduction.md | 2 +- .../reference/src/items/associated-items.md | 2 +- .../reference/src/items/external-blocks.md | 21 +- src/doc/reference/src/items/functions.md | 178 +- src/doc/reference/src/items/generics.md | 6 +- src/doc/reference/src/items/unions.md | 2 +- .../reference/src/items/use-declarations.md | 4 +- src/doc/reference/src/lifetime-elision.md | 2 +- src/doc/reference/src/macros-by-example.md | 2 +- .../src/memory-allocation-and-lifetime.md | 2 +- .../reference/src/special-types-and-traits.md | 12 +- src/doc/reference/src/statements.md | 14 +- src/doc/reference/src/subtyping.md | 2 +- src/doc/reference/src/tokens.md | 19 +- src/doc/reference/src/type-layout.md | 6 +- src/doc/reference/src/types.md | 4 +- .../reference/src/types/function-pointer.md | 2 +- src/doc/reference/src/types/trait-object.md | 9 - src/doc/reference/stable-check/Cargo.toml | 3 +- src/doc/reference/stable-check/src/main.rs | 2 +- src/doc/rust-by-example/README.md | 4 +- src/doc/rust-by-example/src/SUMMARY.md | 6 + .../src/conversion/try_from_try_into.md | 45 + .../rust-by-example/src/custom_types/enum.md | 47 +- .../src/error/option_unwrap/question_mark.md | 58 + .../src/error/result/enter_question_mark.md | 2 +- .../rust-by-example/src/flow_control/for.md | 2 +- .../src/flow_control/if_let.md | 5 + .../src/flow_control/match/binding.md | 24 +- .../src/fn/closures/output_parameters.md | 24 +- src/doc/rust-by-example/src/hello/print.md | 2 +- .../rust-by-example/src/hello/print/fmt.md | 2 +- .../src/hello/print/print_debug.md | 2 +- .../src/hello/print/print_display.md | 2 +- .../print/print_display/testcase_list.md | 2 +- src/doc/rust-by-example/src/macros.md | 2 +- src/doc/rust-by-example/src/std/rc.md | 2 +- src/doc/rust-by-example/src/std_misc/path.md | 2 +- .../src/testing/unit_testing.md | 30 + src/doc/rust-by-example/src/trait/dyn.md | 47 + .../rust-by-example/src/trait/impl_trait.md | 59 + src/doc/rust-by-example/src/trait/iter.md | 2 +- .../src/traits/disambiguating.md | 62 + .../rust-by-example/src/traits/supertraits.md | 43 + src/doc/rustc-guide/.travis.yml | 2 + src/doc/rustc-guide/book.toml | 4 + .../rustc-guide/ci/build-ignore-timeouts.sh | 7 +- src/doc/rustc-guide/ci/install.sh | 2 +- src/doc/rustc-guide/src/SUMMARY.md | 3 +- .../rustc-guide/src/appendix/bibliography.md | 4 +- .../rustc-guide/src/appendix/code-index.md | 2 +- src/doc/rustc-guide/src/borrow_check.md | 2 +- src/doc/rustc-guide/src/compiler-team.md | 8 +- src/doc/rustc-guide/src/existential-types.md | 48 - .../rustc-guide/src/how-to-build-and-run.md | 43 +- .../src/opaque-types-type-alias-impl-trait.md | 62 + src/doc/rustc-guide/src/profiling.md | 19 +- src/doc/rustc-guide/src/query.md | 6 +- src/doc/rustc-guide/src/stability.md | 52 + .../rustc-guide/src/traits/bibliography.md | 4 +- .../rustc-guide/src/traits/lowering-rules.md | 2 +- src/doc/rustc-ux-guidelines.md | 2 +- src/doc/rustc/src/command-line-arguments.md | 7 + .../src/lints/listing/allowed-by-default.md | 2 +- .../rustc/src/profile-guided-optimization.md | 11 + src/doc/rustdoc/src/unstable-features.md | 63 +- .../src/language-features/or-patterns.md | 36 + .../src/language-features/param-attrs.md | 27 - .../src/language-features/plugin.md | 16 +- src/etc/generate-deriving-span-tests.py | 2 + src/etc/installer/exe/rust.iss | 6 +- src/etc/installer/msi/rust.wxs | 2 +- src/etc/lldb_batchmode.py | 5 +- src/etc/wasm32-shim.js | 108 +- src/liballoc/alloc.rs | 2 +- src/liballoc/boxed.rs | 135 + src/liballoc/collections/binary_heap.rs | 3 + src/liballoc/collections/btree/node.rs | 6 +- src/liballoc/collections/btree/set.rs | 44 +- src/liballoc/collections/linked_list.rs | 2 +- src/liballoc/collections/linked_list/tests.rs | 4 +- src/liballoc/collections/mod.rs | 31 +- src/liballoc/collections/vec_deque.rs | 106 +- src/liballoc/lib.rs | 15 +- src/liballoc/macros.rs | 2 +- src/liballoc/raw_vec.rs | 209 +- src/liballoc/raw_vec/tests.rs | 6 +- src/liballoc/rc.rs | 197 +- src/liballoc/string.rs | 16 +- src/liballoc/sync.rs | 202 +- src/liballoc/tests/btree/set.rs | 11 + src/liballoc/tests/string.rs | 14 +- src/liballoc/tests/vec.rs | 18 +- src/liballoc/tests/vec_deque.rs | 14 +- src/liballoc/vec.rs | 49 +- src/libcore/any.rs | 11 +- src/libcore/ascii.rs | 9 + src/libcore/bool.rs | 45 + src/libcore/char/methods.rs | 33 - src/libcore/clone.rs | 3 +- src/libcore/cmp.rs | 128 +- src/libcore/convert.rs | 41 +- src/libcore/default.rs | 3 +- src/libcore/fmt/builders.rs | 13 +- src/libcore/fmt/mod.rs | 7 +- src/libcore/hash/mod.rs | 6 +- src/libcore/hint.rs | 38 +- src/libcore/intrinsics.rs | 50 +- src/libcore/iter/adapters/chain.rs | 45 +- src/libcore/iter/adapters/flatten.rs | 86 +- src/libcore/iter/adapters/mod.rs | 621 +- src/libcore/iter/adapters/zip.rs | 8 +- src/libcore/iter/sources.rs | 10 +- src/libcore/iter/traits/accum.rs | 8 +- src/libcore/iter/traits/double_ended.rs | 27 +- src/libcore/iter/traits/iterator.rs | 448 +- src/libcore/lib.rs | 13 +- src/libcore/macros.rs | 82 +- src/libcore/marker.rs | 7 +- src/libcore/mem/maybe_uninit.rs | 14 +- src/libcore/mem/mod.rs | 4 +- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- src/libcore/num/mod.rs | 108 +- src/libcore/num/wrapping.rs | 8 + src/libcore/ops/function.rs | 8 - src/libcore/option.rs | 35 +- src/libcore/panicking.rs | 2 +- src/libcore/pin.rs | 47 +- src/libcore/prelude/v1.rs | 5 - src/libcore/ptr/mod.rs | 4 +- src/libcore/ptr/non_null.rs | 2 +- src/libcore/ptr/unique.rs | 8 + src/libcore/result.rs | 81 + src/libcore/slice/mod.rs | 25 +- src/libcore/str/mod.rs | 17 +- src/libcore/sync/atomic.rs | 33 +- src/libcore/task/poll.rs | 28 + src/libcore/tests/bool.rs | 7 + src/libcore/tests/cmp.rs | 24 +- src/libcore/tests/iter.rs | 173 + src/libcore/tests/lib.rs | 4 + src/libcore/tests/slice.rs | 19 + src/libcore/unicode/mod.rs | 5 - src/libcore/unicode/printable.py | 2 +- src/libcore/unicode/tables.rs | 375 - src/libcore/unicode/unicode.py | 9 +- src/libfmt_macros/Cargo.toml | 2 +- src/libfmt_macros/lib.rs | 9 +- src/libproc_macro/Cargo.toml | 3 + src/libproc_macro/bridge/client.rs | 8 + src/libproc_macro/lib.rs | 10 +- src/libproc_macro/quote.rs | 4 +- src/librustc/Cargo.toml | 7 +- src/librustc/arena.rs | 16 +- src/librustc/dep_graph/graph.rs | 4 +- src/librustc/error_codes.rs | 64 +- src/librustc/hir/check_attr.rs | 9 +- src/librustc/hir/def.rs | 22 +- src/librustc/hir/def_id.rs | 33 +- src/librustc/hir/intravisit.rs | 54 +- src/librustc/hir/itemlikevisit.rs | 21 +- src/librustc/hir/lowering.rs | 484 +- src/librustc/hir/lowering/expr.rs | 151 +- src/librustc/hir/lowering/item.rs | 185 +- src/librustc/hir/map/collector.rs | 22 +- src/librustc/hir/map/def_collector.rs | 91 +- src/librustc/hir/map/definitions.rs | 98 +- src/librustc/hir/map/mod.rs | 112 +- src/librustc/hir/mod.rs | 137 +- src/librustc/hir/print.rs | 60 +- src/librustc/ich/hcx.rs | 58 +- src/librustc/ich/impls_hir.rs | 28 +- src/librustc/ich/impls_syntax.rs | 37 +- src/librustc/ich/impls_ty.rs | 26 +- src/librustc/infer/combine.rs | 7 + src/librustc/infer/equate.rs | 42 +- src/librustc/infer/error_reporting/mod.rs | 51 +- .../infer/error_reporting/need_type_info.rs | 257 +- .../nice_region_error/different_lifetimes.rs | 22 +- .../nice_region_error/named_anon_conflict.rs | 30 +- .../nice_region_error/placeholder_error.rs | 67 +- .../error_reporting/nice_region_error/util.rs | 44 +- src/librustc/infer/error_reporting/note.rs | 4 +- src/librustc/infer/glb.rs | 7 +- src/librustc/infer/lub.rs | 7 +- src/librustc/infer/mod.rs | 60 +- src/librustc/infer/opaque_types/mod.rs | 6 +- src/librustc/infer/sub.rs | 44 +- src/librustc/lib.rs | 10 +- src/librustc/lint/builtin.rs | 4 +- src/librustc/lint/context.rs | 81 +- src/librustc/lint/internal.rs | 53 +- src/librustc/lint/levels.rs | 2 +- src/librustc/lint/mod.rs | 119 +- src/librustc/middle/cstore.rs | 3 +- src/librustc/middle/dead.rs | 48 +- src/librustc/middle/diagnostic_items.rs | 123 + src/librustc/middle/entry.rs | 84 +- src/librustc/middle/expr_use_visitor.rs | 20 +- src/librustc/middle/lang_items.rs | 29 +- src/librustc/middle/liveness.rs | 26 +- src/librustc/middle/mem_categorization.rs | 14 +- src/librustc/middle/reachable.rs | 8 + src/librustc/middle/region.rs | 90 +- src/librustc/middle/resolve_lifetime.rs | 99 +- src/librustc/middle/stability.rs | 8 +- src/librustc/middle/weak_lang_items.rs | 6 +- src/librustc/mir/cache.rs | 2 +- src/librustc/mir/interpret/allocation.rs | 337 +- src/librustc/mir/interpret/error.rs | 52 +- src/librustc/mir/interpret/mod.rs | 109 +- src/librustc/mir/interpret/pointer.rs | 14 +- src/librustc/mir/interpret/value.rs | 16 +- src/librustc/mir/mod.rs | 594 +- src/librustc/mir/tcx.rs | 17 +- src/librustc/mir/visit.rs | 79 +- src/librustc/query/mod.rs | 51 +- src/librustc/session/config.rs | 190 +- src/librustc/session/config/tests.rs | 6 +- src/librustc/session/mod.rs | 87 +- src/librustc/traits/chalk_fulfill.rs | 3 + src/librustc/traits/error_reporting.rs | 394 +- src/librustc/traits/fulfill.rs | 42 +- src/librustc/traits/mod.rs | 62 +- src/librustc/traits/object_safety.rs | 200 +- src/librustc/traits/on_unimplemented.rs | 19 +- src/librustc/traits/project.rs | 38 +- .../traits/query/evaluate_obligation.rs | 5 +- src/librustc/traits/query/method_autoderef.rs | 10 +- src/librustc/traits/query/normalize.rs | 38 +- src/librustc/traits/select.rs | 4 +- src/librustc/traits/structural_impls.rs | 21 +- src/librustc/traits/util.rs | 33 +- src/librustc/ty/codec.rs | 25 +- src/librustc/ty/context.rs | 302 +- src/librustc/ty/error.rs | 142 +- src/librustc/ty/flags.rs | 21 +- src/librustc/ty/fold.rs | 7 +- .../ty/inhabitedness/def_id_forest.rs | 18 +- src/librustc/ty/inhabitedness/mod.rs | 35 +- src/librustc/ty/instance.rs | 7 +- src/librustc/ty/layout.rs | 63 +- src/librustc/ty/mod.rs | 121 +- src/librustc/ty/print/mod.rs | 7 +- src/librustc/ty/print/pretty.rs | 38 +- src/librustc/ty/query/on_disk_cache.rs | 310 +- src/librustc/ty/query/plumbing.rs | 113 +- src/librustc/ty/relate.rs | 24 +- src/librustc/ty/structural_impls.rs | 2 + src/librustc/ty/sty.rs | 55 +- src/librustc/ty/util.rs | 51 +- src/librustc/ty/wf.rs | 2 +- src/librustc/util/common.rs | 37 - src/librustc_apfloat/ieee.rs | 16 +- src/librustc_apfloat/lib.rs | 36 +- src/librustc_apfloat/ppc.rs | 6 +- src/librustc_asan/build.rs | 4 + src/librustc_ast_borrowck/borrowck/mod.rs | 2 +- .../borrowck/move_data.rs | 2 +- .../cfg/construct.rs | 161 +- .../cfg/graphviz.rs | 22 +- .../cfg/mod.rs | 31 +- src/librustc_ast_borrowck/dataflow.rs | 9 +- src/librustc_ast_borrowck/graphviz.rs | 7 +- src/librustc_ast_borrowck/lib.rs | 1 + src/librustc_codegen_llvm/Cargo.toml | 4 - src/librustc_codegen_llvm/abi.rs | 2 +- src/librustc_codegen_llvm/asm.rs | 7 +- src/librustc_codegen_llvm/attributes.rs | 52 +- src/librustc_codegen_llvm/back/archive.rs | 3 +- src/librustc_codegen_llvm/back/lto.rs | 86 +- src/librustc_codegen_llvm/builder.rs | 31 +- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/common.rs | 39 +- src/librustc_codegen_llvm/consts.rs | 74 +- src/librustc_codegen_llvm/context.rs | 4 +- .../debuginfo/metadata.rs | 2 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 37 +- src/librustc_codegen_llvm/error_codes.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 48 +- src/librustc_codegen_llvm/lib.rs | 18 +- src/librustc_codegen_llvm/llvm/ffi.rs | 2 + src/librustc_codegen_ssa/Cargo.toml | 4 +- src/librustc_codegen_ssa/back/archive.rs | 5 +- src/librustc_codegen_ssa/back/command.rs | 22 + src/librustc_codegen_ssa/back/link.rs | 59 +- src/librustc_codegen_ssa/back/linker.rs | 90 +- .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 27 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_codegen_ssa/error_codes.rs | 2 +- src/librustc_codegen_ssa/lib.rs | 6 +- src/librustc_codegen_ssa/mir/analyze.rs | 25 +- src/librustc_codegen_ssa/mir/block.rs | 54 +- src/librustc_codegen_ssa/mir/mod.rs | 53 +- src/librustc_codegen_ssa/mir/operand.rs | 73 +- src/librustc_codegen_ssa/mir/place.rs | 72 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_codegen_ssa/mir/statement.rs | 35 +- src/librustc_codegen_ssa/mono_item.rs | 2 +- src/librustc_codegen_ssa/traits/asm.rs | 2 + src/librustc_codegen_ssa/traits/builder.rs | 5 +- src/librustc_codegen_ssa/traits/debuginfo.rs | 2 +- src/librustc_codegen_ssa/traits/intrinsic.rs | 4 +- src/librustc_codegen_ssa/traits/statics.rs | 6 +- src/librustc_codegen_utils/Cargo.toml | 2 +- src/librustc_codegen_utils/lib.rs | 1 - src/librustc_codegen_utils/symbol_names/v0.rs | 12 +- .../symbol_names_test.rs | 2 +- src/librustc_data_structures/Cargo.toml | 2 +- src/librustc_data_structures/indexed_vec.rs | 2 +- src/librustc_data_structures/lib.rs | 2 +- .../obligation_forest/graphviz.rs | 4 +- .../obligation_forest/mod.rs | 346 +- .../obligation_forest/node_index.rs | 20 - src/librustc_data_structures/tiny_list.rs | 56 +- .../tiny_list/tests.rs | 35 +- src/librustc_driver/Cargo.toml | 5 +- src/librustc_driver/args.rs | 53 + src/librustc_driver/lib.rs | 198 +- src/librustc_driver/pretty.rs | 12 +- src/librustc_errors/Cargo.toml | 1 + .../annotate_snippet_emitter_writer.rs | 26 +- src/librustc_errors/diagnostic.rs | 7 +- src/librustc_errors/diagnostic_builder.rs | 82 +- src/librustc_errors/emitter.rs | 784 ++- src/librustc_errors/lib.rs | 410 +- src/librustc_incremental/Cargo.toml | 2 +- .../assert_module_sources.rs | 12 +- .../persist/dirty_clean.rs | 27 +- src/librustc_interface/Cargo.toml | 3 +- src/librustc_interface/build.rs | 4 + src/librustc_interface/passes.rs | 82 +- src/librustc_interface/util.rs | 202 +- src/librustc_lexer/Cargo.toml | 12 +- src/librustc_lexer/src/lib.rs | 318 +- src/librustc_lint/builtin.rs | 209 +- src/librustc_lint/error_codes.rs | 5 +- src/librustc_lint/lib.rs | 6 +- src/librustc_lint/nonstandard_style.rs | 7 +- src/librustc_lint/redundant_semicolon.rs | 52 + src/librustc_lint/types.rs | 119 +- src/librustc_lint/unused.rs | 124 +- src/librustc_llvm/build.rs | 17 +- src/librustc_lsan/build.rs | 4 + src/librustc_macros/src/lib.rs | 2 +- src/librustc_metadata/creader.rs | 89 +- src/librustc_metadata/cstore.rs | 24 +- src/librustc_metadata/cstore_impl.rs | 41 +- src/librustc_metadata/decoder.rs | 299 +- src/librustc_metadata/encoder.rs | 522 +- src/librustc_metadata/error_codes.rs | 12 +- src/librustc_metadata/index.rs | 10 +- src/librustc_metadata/lib.rs | 5 +- src/librustc_metadata/locator.rs | 4 +- src/librustc_metadata/native_libs.rs | 8 +- src/librustc_metadata/schema.rs | 159 +- src/librustc_mir/Cargo.toml | 5 +- src/librustc_mir/borrow_check/borrow_set.rs | 2 +- .../borrow_check/conflict_errors.rs | 81 +- .../borrow_check/error_reporting.rs | 83 +- src/librustc_mir/borrow_check/flows.rs | 5 +- src/librustc_mir/borrow_check/mod.rs | 116 +- src/librustc_mir/borrow_check/move_errors.rs | 120 +- .../borrow_check/mutability_errors.rs | 116 +- .../borrow_check/nll/constraint_generation.rs | 14 +- .../borrow_check/nll/explain_borrow/mod.rs | 28 +- src/librustc_mir/borrow_check/nll/facts.rs | 17 +- .../borrow_check/nll/invalidation.rs | 2 +- src/librustc_mir/borrow_check/nll/mod.rs | 93 +- .../nll/region_infer/error_reporting/mod.rs | 243 +- .../error_reporting/region_name.rs | 207 +- .../borrow_check/nll/region_infer/mod.rs | 65 +- src/librustc_mir/borrow_check/nll/renumber.rs | 22 +- .../nll/type_check/liveness/local_use_map.rs | 22 +- .../nll/type_check/liveness/mod.rs | 4 +- .../nll/type_check/liveness/polonius.rs | 67 +- .../nll/type_check/liveness/trace.rs | 100 +- .../borrow_check/nll/type_check/mod.rs | 259 +- src/librustc_mir/borrow_check/path_utils.rs | 23 +- src/librustc_mir/borrow_check/place_ext.rs | 87 +- .../borrow_check/places_conflict.rs | 326 +- src/librustc_mir/borrow_check/prefixes.rs | 201 +- src/librustc_mir/borrow_check/used_muts.rs | 4 +- src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/expr/as_constant.rs | 2 +- src/librustc_mir/build/expr/as_place.rs | 17 +- src/librustc_mir/build/expr/as_rvalue.rs | 30 +- src/librustc_mir/build/expr/into.rs | 7 +- src/librustc_mir/build/matches/mod.rs | 71 +- src/librustc_mir/build/matches/simplify.rs | 8 +- src/librustc_mir/build/matches/test.rs | 30 +- src/librustc_mir/build/misc.rs | 5 +- src/librustc_mir/build/mod.rs | 11 +- src/librustc_mir/build/scope.rs | 141 +- src/librustc_mir/const_eval.rs | 70 +- .../dataflow/drop_flag_effects.rs | 14 +- src/librustc_mir/dataflow/generic.rs | 512 ++ .../dataflow/impls/borrowed_locals.rs | 17 +- src/librustc_mir/dataflow/impls/borrows.rs | 14 +- .../dataflow/impls/storage_liveness.rs | 4 +- src/librustc_mir/dataflow/mod.rs | 47 +- .../dataflow/move_paths/abs_domain.rs | 40 +- .../dataflow/move_paths/builder.rs | 293 +- src/librustc_mir/dataflow/move_paths/mod.rs | 75 +- src/librustc_mir/error_codes.rs | 102 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_mir/hair/pattern/_match.rs | 30 +- src/librustc_mir/hair/pattern/check_match.rs | 318 +- src/librustc_mir/hair/pattern/mod.rs | 73 +- src/librustc_mir/interpret/cast.rs | 20 +- src/librustc_mir/interpret/eval_context.rs | 132 +- src/librustc_mir/interpret/intern.rs | 269 +- src/librustc_mir/interpret/intrinsics.rs | 128 +- .../interpret/intrinsics/type_name.rs | 21 +- src/librustc_mir/interpret/machine.rs | 4 +- src/librustc_mir/interpret/memory.rs | 123 +- src/librustc_mir/interpret/mod.rs | 4 +- src/librustc_mir/interpret/operand.rs | 144 +- src/librustc_mir/interpret/operator.rs | 123 +- src/librustc_mir/interpret/place.rs | 138 +- src/librustc_mir/interpret/snapshot.rs | 21 +- src/librustc_mir/interpret/step.rs | 15 +- src/librustc_mir/interpret/terminator.rs | 11 +- src/librustc_mir/interpret/traits.rs | 21 +- src/librustc_mir/interpret/validity.rs | 95 +- src/librustc_mir/lib.rs | 9 +- src/librustc_mir/monomorphize/collector.rs | 47 +- src/librustc_mir/monomorphize/partitioning.rs | 2 +- src/librustc_mir/shim.rs | 85 +- src/librustc_mir/transform/add_call_guards.rs | 4 +- .../transform/add_moves_for_packed_drops.rs | 4 +- src/librustc_mir/transform/add_retag.rs | 55 +- src/librustc_mir/transform/check_unsafety.rs | 227 +- .../transform/cleanup_post_borrowck.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 178 +- src/librustc_mir/transform/copy_prop.rs | 58 +- src/librustc_mir/transform/deaggregator.rs | 10 +- src/librustc_mir/transform/dump_mir.rs | 4 +- src/librustc_mir/transform/elaborate_drops.rs | 50 +- src/librustc_mir/transform/erase_regions.rs | 4 +- src/librustc_mir/transform/generator.rs | 91 +- src/librustc_mir/transform/inline.rs | 64 +- src/librustc_mir/transform/instcombine.rs | 40 +- src/librustc_mir/transform/mod.rs | 136 +- src/librustc_mir/transform/no_landing_pads.rs | 4 +- src/librustc_mir/transform/promote_consts.rs | 80 +- src/librustc_mir/transform/qualify_consts.rs | 548 +- .../transform/qualify_min_const_fn.rs | 117 +- .../transform/remove_noop_landing_pads.rs | 10 +- src/librustc_mir/transform/rustc_peek.rs | 14 +- src/librustc_mir/transform/simplify.rs | 8 +- .../transform/simplify_branches.rs | 4 +- .../transform/uniform_array_move_out.rs | 197 +- src/librustc_mir/util/aggregate.rs | 6 +- src/librustc_mir/util/alignment.rs | 10 +- src/librustc_mir/util/borrowck_errors.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 13 +- src/librustc_mir/util/patch.rs | 2 +- src/librustc_mir/util/pretty.rs | 7 +- src/librustc_msan/build.rs | 4 + src/librustc_passes/ast_validation.rs | 7 +- src/librustc_passes/error_codes.rs | 12 +- src/librustc_passes/hir_stats.rs | 13 +- src/librustc_passes/lib.rs | 7 +- src/librustc_passes/loops.rs | 36 +- src/librustc_plugin/Cargo.toml | 4 +- src/librustc_plugin/deprecated/Cargo.toml | 14 + src/librustc_plugin/deprecated/lib.rs | 8 + src/librustc_plugin/error_codes.rs | 11 +- src/librustc_plugin/lib.rs | 8 +- src/librustc_privacy/error_codes.rs | 5 +- src/librustc_privacy/lib.rs | 43 +- src/librustc_resolve/build_reduced_graph.rs | 353 +- src/librustc_resolve/check_unused.rs | 4 +- src/librustc_resolve/diagnostics.rs | 71 +- src/librustc_resolve/error_codes.rs | 25 +- src/librustc_resolve/late.rs | 895 +-- src/librustc_resolve/late/diagnostics.rs | 29 +- src/librustc_resolve/lib.rs | 265 +- src/librustc_resolve/macros.rs | 285 +- src/librustc_resolve/resolve_imports.rs | 159 +- src/librustc_save_analysis/dump_visitor.rs | 318 +- src/librustc_save_analysis/lib.rs | 23 +- src/librustc_save_analysis/sig.rs | 4 +- src/librustc_target/abi/mod.rs | 19 +- .../spec/aarch64_uwp_windows_msvc.rs | 24 + .../spec/aarch64_wrs_vxworks.rs | 5 +- src/librustc_target/spec/apple_base.rs | 16 + src/librustc_target/spec/apple_ios_base.rs | 33 +- .../spec/arm_wrs_vxworks_sf.rs | 25 - src/librustc_target/spec/armv7_wrs_vxworks.rs | 31 - ...vxworks.rs => armv7_wrs_vxworks_eabihf.rs} | 8 +- src/librustc_target/spec/i586_wrs_vxworks.rs | 8 - src/librustc_target/spec/i686_apple_darwin.rs | 1 + src/librustc_target/spec/i686_unknown_uefi.rs | 98 + .../spec/i686_uwp_windows_msvc.rs | 22 + src/librustc_target/spec/i686_wrs_vxworks.rs | 2 +- .../spec/i686_wrs_vxworks_gnu.rs | 23 - src/librustc_target/spec/linux_kernel_base.rs | 26 + ...f.rs => mips64_unknown_linux_muslabi64.rs} | 19 +- .../spec/mips64el_unknown_linux_muslabi64.rs | 25 + src/librustc_target/spec/mod.rs | 24 +- .../spec/powerpc64_wrs_vxworks.rs | 3 +- .../spec/powerpc_wrs_vxworks.rs | 1 - .../spec/powerpc_wrs_vxworks_gnusf.rs | 26 - .../spec/powerpc_wrs_vxworks_gnuspesf.rs | 27 - .../spec/powerpc_wrs_vxworks_spe.rs | 1 - .../spec/sparc64_unknown_openbsd.rs | 22 + src/librustc_target/spec/vxworks_base.rs | 27 +- src/librustc_target/spec/wasm32_wasi.rs | 4 + .../spec/windows_uwp_msvc_base.rs | 33 + .../spec/x86_64_apple_darwin.rs | 1 + .../spec/x86_64_apple_ios_macabi.rs | 23 + .../spec/x86_64_linux_kernel.rs | 31 + .../spec/x86_64_uwp_windows_msvc.rs | 22 + .../spec/x86_64_wrs_vxworks.rs | 1 + src/librustc_tsan/build.rs | 4 + src/librustc_typeck/astconv.rs | 18 +- src/librustc_typeck/check/_match.rs | 1032 +-- src/librustc_typeck/check/callee.rs | 12 +- src/librustc_typeck/check/cast.rs | 6 +- src/librustc_typeck/check/closure.rs | 10 +- src/librustc_typeck/check/coercion.rs | 29 +- src/librustc_typeck/check/compare_method.rs | 13 +- src/librustc_typeck/check/demand.rs | 51 +- src/librustc_typeck/check/expr.rs | 385 +- .../check/generator_interior.rs | 56 +- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/method/confirm.rs | 20 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 + src/librustc_typeck/check/method/suggest.rs | 38 +- src/librustc_typeck/check/mod.rs | 718 +- src/librustc_typeck/check/op.rs | 29 +- src/librustc_typeck/check/pat.rs | 1214 ++++ src/librustc_typeck/check/regionck.rs | 20 +- src/librustc_typeck/check/wfcheck.rs | 92 +- src/librustc_typeck/check/writeback.rs | 20 +- .../coherence/inherent_impls.rs | 8 + src/librustc_typeck/collect.rs | 81 +- .../constrained_generic_params.rs | 18 +- src/librustc_typeck/error_codes.rs | 124 +- src/librustc_typeck/impl_wf_check.rs | 11 +- src/librustc_typeck/lib.rs | 7 +- .../outlives/implicit_infer.rs | 30 +- src/librustc_typeck/structured_errors.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_typeck/variance/terms.rs | 4 +- src/librustdoc/clean/auto_trait.rs | 8 +- src/librustdoc/clean/cfg.rs | 8 +- src/librustdoc/clean/cfg/tests.rs | 4 +- src/librustdoc/clean/inline.rs | 31 +- src/librustdoc/clean/mod.rs | 373 +- src/librustdoc/clean/simplify.rs | 100 +- src/librustdoc/config.rs | 62 +- src/librustdoc/core.rs | 45 +- src/librustdoc/html/format.rs | 256 +- src/librustdoc/html/layout.rs | 35 +- src/librustdoc/html/markdown.rs | 68 +- src/librustdoc/html/markdown/tests.rs | 44 +- src/librustdoc/html/render.rs | 1990 +++--- src/librustdoc/html/sources.rs | 175 + src/librustdoc/html/static/main.js | 99 +- src/librustdoc/html/static/rustdoc.css | 15 + src/librustdoc/html/static/storage.js | 19 +- src/librustdoc/lib.rs | 36 +- src/librustdoc/markdown.rs | 14 +- .../passes/check_code_block_syntax.rs | 37 +- .../passes/collect_intra_doc_links.rs | 4 +- src/librustdoc/passes/collect_trait_impls.rs | 1 + src/librustdoc/passes/mod.rs | 2 +- src/librustdoc/test.rs | 280 +- src/librustdoc/visit_ast.rs | 16 +- src/librustdoc/visit_lib.rs | 24 +- src/libserialize/lib.rs | 1 + src/libserialize/tests/json.rs | 2 + src/libserialize/tests/opaque.rs | 2 + src/libstd/Cargo.toml | 37 +- src/libstd/backtrace.rs | 353 + src/libstd/collections/hash/map.rs | 17 +- src/libstd/collections/hash/set.rs | 4 +- src/libstd/collections/mod.rs | 2 +- src/libstd/env.rs | 2 +- src/libstd/error.rs | 49 +- src/libstd/f32.rs | 43 +- src/libstd/f64.rs | 66 +- src/libstd/ffi/c_str.rs | 40 +- src/libstd/ffi/os_str.rs | 4 +- src/libstd/fs.rs | 5 +- src/libstd/future.rs | 1 + src/libstd/io/buffered.rs | 46 +- src/libstd/io/mod.rs | 86 +- src/libstd/io/stdio.rs | 8 +- src/libstd/keyword_docs.rs | 9 +- src/libstd/lib.rs | 10 +- src/libstd/macros.rs | 20 +- src/libstd/net/tcp.rs | 3 +- src/libstd/net/udp.rs | 3 +- src/libstd/os/raw/mod.rs | 48 +- src/libstd/panicking.rs | 16 +- src/libstd/prelude/v1.rs | 19 - src/libstd/primitive_docs.rs | 2 +- src/libstd/process.rs | 8 +- src/libstd/sync/condvar.rs | 4 +- src/libstd/sync/mod.rs | 1 - src/libstd/sys/cloudabi/abi/cloudabi.rs | 1 + src/libstd/sys/cloudabi/mod.rs | 2 - src/libstd/sys/cloudabi/mutex.rs | 7 +- src/libstd/sys/cloudabi/rwlock.rs | 15 +- src/libstd/sys/cloudabi/shims/process.rs | 8 +- src/libstd/sys/cloudabi/thread.rs | 7 +- src/libstd/sys/sgx/condvar.rs | 3 +- src/libstd/sys/sgx/mutex.rs | 4 +- src/libstd/sys/sgx/process.rs | 8 +- src/libstd/sys/sgx/rwlock.rs | 34 +- src/libstd/sys/sgx/waitqueue.rs | 11 +- src/libstd/sys/unix/process/mod.rs | 1 + src/libstd/sys/unix/process/process_common.rs | 90 +- .../sys/unix/process/process_fuchsia.rs | 63 +- src/libstd/sys/unix/process/process_unix.rs | 38 +- src/libstd/sys/unix/process/zircon.rs | 12 +- src/libstd/sys/unix/time.rs | 1 + src/libstd/sys/vxworks/backtrace/mod.rs | 110 - .../sys/vxworks/backtrace/printing/dladdr.rs | 35 - .../sys/vxworks/backtrace/printing/mod.rs | 33 - .../vxworks/backtrace/tracing/backtrace_fn.rs | 39 - .../sys/vxworks/backtrace/tracing/gcc_s.rs | 99 - .../sys/vxworks/backtrace/tracing/mod.rs | 8 - src/libstd/sys/vxworks/fast_thread_local.rs | 25 - src/libstd/sys/vxworks/fs.rs | 2 +- src/libstd/sys/vxworks/os.rs | 23 +- src/libstd/sys/vxworks/process/mod.rs | 2 +- .../sys/vxworks/process/process_common.rs | 10 +- .../sys/vxworks/process/process_vxworks.rs | 13 +- src/libstd/sys/vxworks/process/rtp.rs | 298 - src/libstd/sys/vxworks/rand.rs | 21 +- src/libstd/sys/vxworks/thread.rs | 4 +- src/libstd/sys/wasi/args.rs | 41 +- src/libstd/sys/wasi/ext/fs.rs | 10 +- src/libstd/sys/wasi/ext/io.rs | 8 +- src/libstd/sys/wasi/fd.rs | 280 +- src/libstd/sys/wasi/fs.rs | 186 +- src/libstd/sys/wasi/io.rs | 11 +- src/libstd/sys/wasi/mod.rs | 79 +- src/libstd/sys/wasi/os.rs | 33 +- src/libstd/sys/wasi/process.rs | 8 +- src/libstd/sys/wasi/stdio.rs | 11 +- src/libstd/sys/wasi/thread.rs | 54 +- src/libstd/sys/wasi/time.rs | 30 +- src/libstd/sys/wasm/args.rs | 4 +- src/libstd/sys/wasm/mod.rs | 222 +- src/libstd/sys/wasm/os.rs | 18 +- src/libstd/sys/wasm/process.rs | 8 +- src/libstd/sys/wasm/stdio.rs | 15 +- src/libstd/sys/wasm/time.rs | 5 +- src/libstd/sys/windows/c.rs | 2 +- src/libstd/sys/windows/fs.rs | 2 +- src/libstd/sys/windows/process.rs | 24 +- src/libstd/sys_common/backtrace.rs | 283 +- src/libstd/sys_common/mod.rs | 1 - src/libstd/sys_common/process.rs | 51 +- src/libstd/tests/env.rs | 2 +- src/libstd/time.rs | 54 +- src/libsyntax/ast.rs | 149 +- src/libsyntax/attr/mod.rs | 144 +- src/libsyntax/config.rs | 2 +- src/libsyntax/diagnostics/macros.rs | 55 +- src/libsyntax/diagnostics/metadata.rs | 93 - src/libsyntax/diagnostics/plugin.rs | 211 - src/libsyntax/error_codes.rs | 20 +- src/libsyntax/ext/base.rs | 394 +- src/libsyntax/ext/build.rs | 375 +- src/libsyntax/ext/expand.rs | 453 +- src/libsyntax/ext/placeholders.rs | 157 +- src/libsyntax/ext/proc_macro.rs | 14 +- src/libsyntax/ext/proc_macro_server.rs | 23 +- src/libsyntax/ext/tt/macro_rules.rs | 132 +- src/libsyntax/ext/tt/transcribe.rs | 54 +- src/libsyntax/feature_gate.rs | 2525 ------- src/libsyntax/feature_gate/accepted.rs | 252 + src/libsyntax/feature_gate/active.rs | 539 ++ src/libsyntax/feature_gate/builtin_attrs.rs | 574 ++ src/libsyntax/feature_gate/check.rs | 873 +++ src/libsyntax/feature_gate/mod.rs | 65 + src/libsyntax/feature_gate/removed.rs | 110 + src/libsyntax/json.rs | 26 +- src/libsyntax/lib.rs | 13 +- src/libsyntax/mut_visit.rs | 174 +- src/libsyntax/mut_visit/tests.rs | 10 +- src/libsyntax/parse/attr.rs | 52 +- src/libsyntax/parse/diagnostics.rs | 147 +- src/libsyntax/parse/lexer/mod.rs | 29 +- src/libsyntax/parse/lexer/tests.rs | 158 +- src/libsyntax/parse/lexer/tokentrees.rs | 40 +- src/libsyntax/parse/lexer/unicode_chars.rs | 7 +- src/libsyntax/parse/literal.rs | 4 +- src/libsyntax/parse/mod.rs | 91 +- src/libsyntax/parse/parser.rs | 225 +- src/libsyntax/parse/parser/expr.rs | 263 +- src/libsyntax/parse/parser/generics.rs | 106 +- src/libsyntax/parse/parser/item.rs | 182 +- src/libsyntax/parse/parser/module.rs | 8 +- src/libsyntax/parse/parser/pat.rs | 826 ++- src/libsyntax/parse/parser/path.rs | 20 +- src/libsyntax/parse/parser/stmt.rs | 91 +- src/libsyntax/parse/parser/ty.rs | 17 +- src/libsyntax/parse/tests.rs | 18 +- src/libsyntax/parse/token.rs | 45 +- src/libsyntax/print/pprust.rs | 194 +- src/libsyntax/print/pprust/tests.rs | 11 +- src/libsyntax/source_map.rs | 163 +- src/libsyntax/source_map/tests.rs | 98 +- src/libsyntax/tests.rs | 50 +- src/libsyntax/tokenstream.rs | 20 +- src/libsyntax/tokenstream/tests.rs | 4 +- src/libsyntax/util/node_count.rs | 7 +- src/libsyntax/util/parser.rs | 4 +- src/libsyntax/visit.rs | 119 +- src/libsyntax_ext/Cargo.toml | 1 + src/libsyntax_ext/asm.rs | 31 +- src/libsyntax_ext/assert.rs | 21 +- src/libsyntax_ext/cfg.rs | 10 +- src/libsyntax_ext/cmdline_attrs.rs | 30 + src/libsyntax_ext/compile_error.rs | 4 +- src/libsyntax_ext/concat.rs | 16 +- src/libsyntax_ext/concat_idents.rs | 18 +- src/libsyntax_ext/deriving/clone.rs | 14 +- src/libsyntax_ext/deriving/cmp/eq.rs | 14 +- src/libsyntax_ext/deriving/cmp/ord.rs | 57 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 19 +- src/libsyntax_ext/deriving/debug.rs | 18 +- src/libsyntax_ext/deriving/decodable.rs | 30 +- src/libsyntax_ext/deriving/encodable.rs | 41 +- src/libsyntax_ext/deriving/generic/mod.rs | 74 +- src/libsyntax_ext/deriving/generic/ty.rs | 40 +- src/libsyntax_ext/deriving/hash.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 32 +- src/libsyntax_ext/env.rs | 28 +- src/libsyntax_ext/error_codes.rs | 9 +- src/libsyntax_ext/format.rs | 82 +- src/libsyntax_ext/global_allocator.rs | 27 +- src/libsyntax_ext/global_asm.rs | 13 +- src/libsyntax_ext/lib.rs | 19 +- src/libsyntax_ext/log_syntax.rs | 6 +- src/libsyntax_ext/plugin_macro_defs.rs | 8 +- src/libsyntax_ext/proc_macro_harness.rs | 182 +- src/libsyntax_ext/source_util.rs | 63 +- src/libsyntax_ext/standard_library_imports.rs | 110 +- src/libsyntax_ext/test.rs | 31 +- src/libsyntax_ext/test_harness.rs | 253 +- src/libsyntax_ext/trace_macros.rs | 27 +- src/libsyntax_pos/edition.rs | 5 - src/libsyntax_pos/hygiene.rs | 291 +- src/libsyntax_pos/lib.rs | 133 +- src/libsyntax_pos/symbol.rs | 178 +- src/libterm/Cargo.toml | 6 +- src/libtest/Cargo.toml | 16 +- src/libtest/formatters/json.rs | 71 +- src/libtest/formatters/mod.rs | 1 + src/libtest/formatters/pretty.rs | 8 +- src/libtest/formatters/terse.rs | 8 +- src/libtest/lib.rs | 31 +- src/libtest/tests.rs | 11 + src/libunwind/Cargo.toml | 4 +- src/libunwind/build.rs | 26 +- src/libunwind/libunwind.rs | 10 +- src/stage0.txt | 6 +- src/stdarch/.appveyor.yml | 30 - src/stdarch/.cirrus.yml | 13 + src/stdarch/README.md | 8 +- .../{azure-pipelines.yml => ci/azure.yml} | 74 +- src/stdarch/crates/core_arch/Cargo.toml | 3 +- src/stdarch/crates/core_arch/README.md | 8 +- .../crates/core_arch/src/aarch64/crc.rs | 1 - .../crates/core_arch/src/aarch64/neon.rs | 1 - src/stdarch/crates/core_arch/src/acle/dsp.rs | 1 - src/stdarch/crates/core_arch/src/mips/msa.rs | 2631 +++---- src/stdarch/crates/core_arch/src/mod.rs | 6 +- .../crates/core_arch/src/powerpc/altivec.rs | 1 - src/stdarch/crates/core_arch/src/simd_llvm.rs | 1 - src/stdarch/crates/core_arch/src/x86/avx.rs | 6 +- src/stdarch/crates/core_arch/src/x86/avx2.rs | 11 +- src/stdarch/crates/core_arch/src/x86/sse.rs | 36 +- src/stdarch/crates/core_arch/src/x86/sse2.rs | 22 +- .../crates/core_arch/src/x86_64/sse.rs | 2 +- src/stdarch/crates/std_detect/Cargo.toml | 3 +- src/stdarch/crates/std_detect/README.md | 8 +- .../crates/std_detect/src/detect/mod.rs | 10 +- src/stdarch/crates/stdarch-verify/src/lib.rs | 36 +- .../crates/stdarch-verify/tests/arm.rs | 150 + .../crates/stdarch-verify/tests/mips.rs | 29 + .../crates/stdarch-verify/tests/x86-intel.rs | 151 + src/test/codegen/README.md | 2 + src/test/codegen/adjustments.rs | 2 +- src/test/codegen/c-variadic.rs | 23 +- src/test/codegen/fastcall-inreg.rs | 12 +- src/test/codegen/function-arguments.rs | 28 +- src/test/codegen/integer-cmp.rs | 28 + src/test/codegen/issue-45222.rs | 3 - .../codegen/iter-fold-closure-no-dupes.rs | 14 + .../codegen/iter-fold-closure-no-iterator.rs | 10 + src/test/codegen/personality_lifetimes.rs | 9 +- src/test/codegen/refs.rs | 2 +- src/test/codegen/repeat-trusted-len.rs | 2 +- src/test/codegen/repr-transparent.rs | 34 +- src/test/codegen/scalar-pair-bool.rs | 12 +- src/test/codegen/union-abi.rs | 16 +- src/test/codegen/var-names.rs | 15 + .../issues => compile-fail}/issue-44415.rs | 0 src/test/debuginfo/boxed-struct.rs | 16 +- .../debuginfo/function-arg-initialization.rs | 4 +- src/test/debuginfo/issue-22656.rs | 2 +- .../incremental/hashes/call_expressions.rs | 18 +- .../incremental/hashes/closure_expressions.rs | 12 +- src/test/incremental/hashes/consts.rs | 12 +- src/test/incremental/hashes/for_loops.rs | 2 +- .../incremental/hashes/function_interfaces.rs | 12 - src/test/incremental/hashes/if_expressions.rs | 16 +- .../hashes/indexing_expressions.rs | 14 +- src/test/incremental/hashes/inherent_impls.rs | 12 +- src/test/incremental/hashes/inline_asm.rs | 12 +- .../incremental/hashes/loop_expressions.rs | 16 +- src/test/incremental/hashes/panic_exprs.rs | 18 +- src/test/incremental/hashes/statics.rs | 20 +- .../incremental/hashes/struct_constructors.rs | 18 +- src/test/incremental/hashes/trait_defs.rs | 124 +- .../incremental/hashes/while_let_loops.rs | 18 +- src/test/incremental/hashes/while_loops.rs | 18 +- src/test/mir-opt/box_expr.rs | 15 +- .../mir-opt/generator-storage-dead-unwind.rs | 26 +- src/test/mir-opt/match-arm-scopes.rs | 2 - .../mir-opt/no-spurious-drop-after-call.rs | 24 + src/test/mir-opt/retag.rs | 38 +- src/test/pretty/macro.rs | 2 +- src/test/pretty/stmt_expr_attributes.rs | 2 - .../run-make-fulldeps/libtest-json/Makefile | 12 +- src/test/run-make-fulldeps/libtest-json/f.rs | 3 +- .../{output.json => output-default.json} | 2 +- .../libtest-json/output-stdout-success.json | 10 + src/test/run-make-fulldeps/lto-empty/Makefile | 12 + src/test/run-make-fulldeps/lto-empty/lib.rs | 1 + .../reproducible-build-2/Makefile | 12 +- src/test/run-make-fulldeps/tools.mk | 2 +- .../run-pass-valgrind/cast-enum-with-dtor.rs | 2 - .../cleanup-auto-borrow-obj.rs | 2 - src/test/run-pass-valgrind/cleanup-stdin.rs | 2 - .../down-with-thread-dtors.rs | 1 - src/test/run-pass-valgrind/dst-dtor-1.rs | 2 - src/test/run-pass-valgrind/dst-dtor-2.rs | 2 - src/test/run-pass-valgrind/dst-dtor-3.rs | 2 - src/test/run-pass-valgrind/dst-dtor-4.rs | 2 - src/test/run-pass-valgrind/exit-flushes.rs | 1 - src/test/run-pass-valgrind/osx-frameworks.rs | 1 - src/test/rustdoc-js-std/vec-new.js | 1 + src/test/rustdoc-js/exact-match.js | 9 + src/test/rustdoc-js/exact-match.rs | 68 + src/test/rustdoc-js/module-substring.js | 9 + src/test/rustdoc-js/module-substring.rs | 68 + src/test/rustdoc-js/search-short-types.js | 2 + src/test/rustdoc-js/search-short-types.rs | 6 + src/test/rustdoc-ui/failed-doctest-output.rs | 1 + .../rustdoc-ui/failed-doctest-output.stdout | 14 +- src/test/rustdoc-ui/invalid-syntax.rs | 18 + src/test/rustdoc-ui/invalid-syntax.stderr | 40 + src/test/rustdoc/assoc-consts.rs | 2 +- src/test/rustdoc/async-fn.rs | 2 - src/test/rustdoc/async-move-doctest.rs | 6 +- src/test/rustdoc/edition-flag.rs | 3 - src/test/rustdoc/inline_cross/assoc-items.rs | 6 +- .../inline_cross/auxiliary/impl_trait_aux.rs | 28 + .../inline_cross/auxiliary/proc_macro.rs | 7 + .../inline_cross/impl-inline-without-trait.rs | 2 +- src/test/rustdoc/inline_cross/impl_trait.rs | 40 + src/test/rustdoc/inline_cross/proc_macro.rs | 32 +- src/test/rustdoc/manual_impl.rs | 8 +- src/test/rustdoc/proc-macro.rs | 3 +- src/test/rustdoc/rustc-macro-crate.rs | 1 + .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 3 +- .../auxiliary/issue-40001-plugin.rs | 3 +- .../auxiliary/lint-for-crate-rpass.rs | 3 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 3 +- .../auxiliary/lint-group-plugin-test.rs | 3 +- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 3 +- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 3 +- .../ui-fulldeps/auxiliary/llvm-pass-plugin.rs | 3 +- .../auxiliary/lto-syntax-extension-plugin.rs | 3 +- .../ui-fulldeps/auxiliary/macro-crate-test.rs | 1 - .../auxiliary/outlive-expansion-phase.rs | 3 +- src/test/ui-fulldeps/auxiliary/plugin-args.rs | 3 +- .../ui-fulldeps/auxiliary/rlib-crate-test.rs | 3 +- .../ui-fulldeps/auxiliary/roman-numerals.rs | 9 +- src/test/ui-fulldeps/compiler-calls.rs | 2 +- .../ui-fulldeps/hash-stable-is-unstable.rs | 2 + .../hash-stable-is-unstable.stderr | 9 +- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 53 +- .../ui/{ => abi}/abi-sysv64-arg-passing.rs | 0 .../ui/{ => abi}/abi-sysv64-register-usage.rs | 0 src/test/ui/{ => abi}/abort-on-c-abi.rs | 0 src/test/ui/{ => abi}/anon-extern-mod.rs | 0 .../anon-extern-mod-cross-crate-1.rs | 0 .../ui/{ => abi}/auxiliary/foreign_lib.rs | 0 src/test/ui/{ => abi}/c-stack-as-value.rs | 0 src/test/ui/{ => abi}/cabi-int-widening.rs | 0 .../anon-extern-mod-cross-crate-1.rs | 0 .../anon-extern-mod-cross-crate-2.rs | 0 .../anon-extern-mod-cross-crate-1.rs | 0 .../ui/{ => abi}/duplicated-external-mods.rs | 0 .../auxiliary/extern-crosscrate-source.rs | 0 .../ui/{ => abi}/extern/extern-call-deep.rs | 0 .../ui/{ => abi}/extern/extern-call-deep2.rs | 0 .../ui/{ => abi}/extern/extern-call-direct.rs | 0 .../{ => abi}/extern/extern-call-indirect.rs | 0 .../ui/{ => abi}/extern/extern-call-scrub.rs | 0 .../ui/{ => abi}/extern/extern-crosscrate.rs | 0 .../{ => abi}/extern/extern-pass-TwoU16s.rs | 0 .../{ => abi}/extern/extern-pass-TwoU32s.rs | 0 .../{ => abi}/extern/extern-pass-TwoU64s.rs | 0 .../ui/{ => abi}/extern/extern-pass-TwoU8s.rs | 0 .../ui/{ => abi}/extern/extern-pass-char.rs | 0 .../ui/{ => abi}/extern/extern-pass-double.rs | 0 .../ui/{ => abi}/extern/extern-pass-empty.rs | 0 .../ui/{ => abi}/extern/extern-pass-u32.rs | 0 .../ui/{ => abi}/extern/extern-pass-u64.rs | 0 .../{ => abi}/extern/extern-return-TwoU16s.rs | 0 .../{ => abi}/extern/extern-return-TwoU32s.rs | 0 .../{ => abi}/extern/extern-return-TwoU64s.rs | 0 .../{ => abi}/extern/extern-return-TwoU8s.rs | 0 .../foreign/auxiliary/foreign_lib.rs | 0 .../foreign/foreign-call-no-runtime.rs | 0 src/test/ui/{ => abi}/foreign/foreign-dupe.rs | 0 .../foreign/foreign-fn-with-byval.rs | 0 .../ui/{ => abi}/foreign/foreign-no-abi.rs | 0 .../ui/{ => abi}/invoke-external-foreign.rs | 0 src/test/ui/{ => abi}/lib-defaults.rs | 0 .../ui/{ => abi}/macros/macros-in-extern.rs | 0 .../{ => abi}/macros/macros-in-extern.stderr | 0 .../mir/mir_codegen_calls_variadic.rs | 0 .../{ => abi}/numbers-arithmetic/i128-ffi.rs | 0 .../abi/proc-macro/auxiliary/test-macros.rs | 112 + .../{ => abi}/proc-macro/macros-in-extern.rs | 0 .../proc-macro/macros-in-extern.stderr | 0 .../ui/{ => abi}/segfault-no-out-of-stack.rs | 0 src/test/ui/{ => abi}/stack-probes-lto.rs | 0 src/test/ui/{ => abi}/stack-probes.rs | 0 .../{ => abi}/statics/static-mut-foreign.rs | 0 .../struct-enums}/struct-return.rs | 0 .../ui/{ => abi}/union/union-c-interop.rs | 0 src/test/ui/{ => abi}/variadic-ffi.rs | 0 src/test/ui/allocator/hygiene.rs | 31 + src/test/ui/anon-params-denied-2018.rs | 2 +- src/test/ui/anon-params-denied-2018.stderr | 16 +- .../anonymous-higher-ranked-lifetime.stderr | 154 +- src/test/ui/array-break-length.rs | 4 +- src/test/ui/array-break-length.stderr | 8 +- src/test/ui/asm/asm-out-read-uninit.rs | 2 +- src/test/ui/asm/asm-out-read-uninit.stderr | 4 +- .../associated-const-array-len.stderr | 9 +- ...ssociated-const-generic-obligations.stderr | 2 + .../associated-const-in-trait.stderr | 5 +- ...iated-const-type-parameter-arrays-2.stderr | 8 +- ...ociated-const-type-parameter-arrays.stderr | 8 +- .../assoc-type-eq-with-dyn-atb-fail.rs | 32 + .../assoc-type-eq-with-dyn-atb-fail.stderr | 11 + .../bad-bounds-on-assoc-in-trait.stderr | 24 +- .../bounds-on-assoc-in-trait.rs | 2 +- .../ui/associated-type-bounds/duplicate.rs | 165 +- .../associated-type-bounds/duplicate.stderr | 224 +- src/test/ui/associated-type-bounds/fn-apit.rs | 1 + .../ui/associated-type-bounds/fn-dyn-apit.rs | 1 + .../ui/associated-type-bounds/fn-inline.rs | 1 + .../ui/associated-type-bounds/fn-where.rs | 1 + .../ui/associated-type-bounds/fn-wrap-apit.rs | 1 + .../ui/associated-type-bounds/inside-adt.rs | 41 +- .../associated-type-bounds/inside-adt.stderr | 61 +- .../associated-type-bounds/struct-bounds.rs | 1 + ...ociated-type-projection-from-supertrait.rs | 8 - ...ted-type-projection-from-supertrait.stderr | 8 +- ...s-binding-to-type-defined-in-supertrait.rs | 6 - ...nding-to-type-defined-in-supertrait.stderr | 20 +- .../associated-types-bound-failure.stderr | 12 +- .../associated-types-eq-3.stderr | 10 +- .../associated-types-eq-hr.stderr | 112 +- .../associated-types-issue-20346.stderr | 10 +- ...ated-types-multiple-types-one-trait.stderr | 20 +- ...associated-types-overridden-binding.stderr | 8 +- .../associated-types-path-2.stderr | 18 +- .../associated-types-ref-from-struct.rs | 4 - .../higher-ranked-projection.bad.stderr | 13 +- src/test/ui/ast-json/ast-json-ice.rs | 41 + src/test/ui/ast-json/ast-json-output.rs | 9 + src/test/ui/ast-json/ast-json-output.stdout | 1 + src/test/ui/async-await/argument-patterns.rs | 4 +- .../async-assoc-fn-anon-lifetimes.rs | 23 + src/test/ui/async-await/async-await.rs | 4 +- ...ync-block-control-flow-static-semantics.rs | 7 +- ...block-control-flow-static-semantics.stderr | 36 +- ...wck-escaping-closure-error.polonius.stderr | 16 + .../async-borrowck-escaping-closure-error.rs | 10 + ...ync-borrowck-escaping-closure-error.stderr | 21 + .../async-await/async-closure-matches-expr.rs | 2 +- src/test/ui/async-await/async-closure.rs | 2 +- src/test/ui/async-await/async-error-span.rs | 3 +- .../ui/async-await/async-error-span.stderr | 4 +- ...async-fn-elided-impl-lifetime-parameter.rs | 15 + src/test/ui/async-await/async-fn-nonsend.rs | 2 - .../ui/async-await/async-fn-nonsend.stderr | 64 +- .../ui/async-await/async-fn-path-elision.rs | 3 - .../async-await/async-fn-path-elision.stderr | 2 +- .../async-await/async-fn-send-uses-nonsend.rs | 2 - .../async-await/async-fn-size-moved-locals.rs | 2 - src/test/ui/async-await/async-fn-size.rs | 2 - src/test/ui/async-await/async-matches-expr.rs | 2 - .../async-unsafe-fn-call-in-safe.rs | 2 - .../async-unsafe-fn-call-in-safe.stderr | 8 +- src/test/ui/async-await/async-with-closure.rs | 2 - .../2015-edition-error-various-positions.rs | 1 - ...015-edition-error-various-positions.stderr | 22 +- ...018-edition-error-in-non-macro-position.rs | 15 +- ...edition-error-in-non-macro-position.stderr | 42 +- .../await-keyword/2018-edition-error.rs | 4 +- .../await-keyword/2018-edition-error.stderr | 20 +- .../incorrect-syntax-suggestions.rs | 2 - .../incorrect-syntax-suggestions.stderr | 70 +- src/test/ui/async-await/await-unsize.rs | 2 - .../ui/async-await/bound-normalization.rs | 2 - ...nditional-and-guaranteed-initialization.rs | 2 - .../async-await/dont-print-desugared-async.rs | 1 - .../dont-print-desugared-async.stderr | 2 +- .../async-await/dont-suggest-missing-await.rs | 2 - .../dont-suggest-missing-await.stderr | 2 +- ...-for-async-fn-parameters-by-ref-binding.rs | 1 - .../drop-order-for-async-fn-parameters.rs | 1 - .../drop-order-for-locals-when-cancelled.rs | 8 +- ...order-for-temporary-in-tail-return-expr.rs | 95 + .../drop-order-locals-are-hidden.rs | 3 - .../drop-order-locals-are-hidden.stderr | 8 +- .../drop-order/drop-order-when-cancelled.rs | 7 +- .../edition-deny-async-fns-2015.rs | 2 - .../edition-deny-async-fns-2015.stderr | 20 +- .../ui/async-await/generics-and-bounds.rs | 2 - src/test/ui/async-await/issue-60709.rs | 3 - src/test/ui/async-await/issue-61452.rs | 1 - src/test/ui/async-await/issue-61452.stderr | 4 +- src/test/ui/async-await/issue-61793.rs | 3 - .../issue-61949-self-return-type.rs | 27 + .../issue-61949-self-return-type.stderr | 8 + src/test/ui/async-await/issue-62658.rs | 2 - ...-63832-await-short-temporary-lifetime-1.rs | 19 + ...ue-63832-await-short-temporary-lifetime.rs | 12 + .../issue-64130-non-send-future-diags.rs | 25 + .../issue-64130-non-send-future-diags.stderr | 23 + src/test/ui/async-await/issue-64391.rs | 14 + src/test/ui/async-await/issues/issue-51719.rs | 2 - .../ui/async-await/issues/issue-51719.stderr | 2 +- src/test/ui/async-await/issues/issue-51751.rs | 2 - .../ui/async-await/issues/issue-51751.stderr | 2 +- src/test/ui/async-await/issues/issue-53249.rs | 2 +- .../issues/issue-54752-async-block.rs | 3 - .../issues/issue-54752-async-block.stderr | 8 + src/test/ui/async-await/issues/issue-54974.rs | 2 - src/test/ui/async-await/issues/issue-55324.rs | 3 - src/test/ui/async-await/issues/issue-55809.rs | 2 - src/test/ui/async-await/issues/issue-58885.rs | 2 - src/test/ui/async-await/issues/issue-59001.rs | 3 - src/test/ui/async-await/issues/issue-59972.rs | 8 +- src/test/ui/async-await/issues/issue-60518.rs | 2 - .../issues/issue-60655-latebound-regions.rs | 1 - src/test/ui/async-await/issues/issue-60674.rs | 1 - src/test/ui/async-await/issues/issue-61187.rs | 4 +- .../ui/async-await/issues/issue-61187.stderr | 2 +- src/test/ui/async-await/issues/issue-61986.rs | 2 - .../ui/async-await/issues/issue-62009-1.rs | 4 +- .../async-await/issues/issue-62009-1.stderr | 5 +- .../ui/async-await/issues/issue-62009-2.rs | 2 +- .../ui/async-await/issues/issue-62517-1.rs | 21 + .../ui/async-await/issues/issue-62517-2.rs | 16 + .../issues/issue-63388-1.nll.stderr | 24 + .../ui/async-await/issues/issue-63388-1.rs | 18 + .../async-await/issues/issue-63388-1.stderr | 12 + .../issues/issue-63388-2.nll.stderr | 11 + .../ui/async-await/issues/issue-63388-2.rs | 18 + .../async-await/issues/issue-63388-2.stderr | 29 + .../ui/async-await/issues/issue-63388-3.rs | 17 + .../ui/async-await/issues/issue-63388-4.rs | 10 + .../ui/async-await/issues/issue-64391-2.rs | 20 + src/test/ui/async-await/issues/issue-64433.rs | 30 + src/test/ui/async-await/issues/issue-64477.rs | 20 + src/test/ui/async-await/issues/issue-64964.rs | 22 + .../issues/non-async-enclosing-span.rs | 11 + .../issues/non-async-enclosing-span.stderr | 11 + .../move-part-await-return-rest-struct.rs | 2 - .../move-part-await-return-rest-tuple.rs | 2 - .../async-await/multiple-lifetimes/elided.rs | 2 - .../async-await/multiple-lifetimes/fn-ptr.rs | 2 - .../ui/async-await/multiple-lifetimes/hrtb.rs | 5 +- .../async-await/multiple-lifetimes/named.rs | 2 - .../multiple-lifetimes/partial-relation.rs | 2 - .../multiple-lifetimes/ret-impl-trait-fg.rs | 2 +- .../ret-impl-trait-no-fg.rs | 2 - .../ret-impl-trait-no-fg.stderr | 2 +- .../multiple-lifetimes/ret-impl-trait-one.rs | 2 +- .../async-await/multiple-lifetimes/ret-ref.rs | 2 - .../multiple-lifetimes/ret-ref.stderr | 6 +- .../multiple-lifetimes/variance.rs | 3 - ...utually-recursive-async-impl-trait-type.rs | 13 + ...lly-recursive-async-impl-trait-type.stderr | 19 + src/test/ui/async-await/nested-in-impl.rs | 15 + .../no-args-non-move-async-closure.rs | 8 - src/test/ui/async-await/no-async-const.rs | 2 - src/test/ui/async-await/no-async-const.stderr | 2 +- src/test/ui/async-await/no-const-async.rs | 4 +- src/test/ui/async-await/no-const-async.stderr | 8 +- .../no-move-across-await-struct.rs | 2 - .../no-move-across-await-struct.stderr | 2 +- .../async-await/no-move-across-await-tuple.rs | 2 - .../no-move-across-await-tuple.stderr | 2 +- .../no-non-guaranteed-initialization.rs | 4 +- .../no-non-guaranteed-initialization.stderr | 6 +- .../no-params-non-move-async-closure.rs | 8 + ...> no-params-non-move-async-closure.stderr} | 4 +- .../partial-initialization-across-await.rs | 8 +- ...partial-initialization-across-await.stderr | 18 +- .../recursive-async-impl-trait-type.rs | 2 - .../recursive-async-impl-trait-type.stderr | 6 +- .../suggest-missing-await-closure.fixed | 2 +- .../suggest-missing-await-closure.rs | 2 +- .../async-await/suggest-missing-await.fixed | 2 - .../ui/async-await/suggest-missing-await.rs | 2 - .../async-await/suggest-missing-await.stderr | 2 +- .../suggest-switching-edition-on-await.rs | 45 + .../suggest-switching-edition-on-await.stderr | 43 + src/test/ui/async-await/unreachable-lint-1.rs | 12 + .../ui/async-await/unreachable-lint-1.stderr | 16 + src/test/ui/async-await/unreachable-lint.rs | 13 + .../ui/async-await/unresolved_type_param.rs | 2 +- src/test/ui/attributes/item-attributes.rs | 2 - src/test/ui/attributes/obsolete-attr.rs | 6 +- src/test/ui/attributes/obsolete-attr.stderr | 4 +- src/test/ui/attributes/unknown-attr.rs | 8 +- src/test/ui/attributes/unknown-attr.stderr | 6 +- .../ui/attributes/unnamed-field-attributes.rs | 9 + src/test/ui/attrs-resolution-errors.rs | 40 + src/test/ui/attrs-resolution-errors.stderr | 32 + src/test/ui/attrs-resolution.rs | 37 + src/test/ui/auto-ref-slice-plus-ref.stderr | 6 +- src/test/ui/auxiliary/cond_plugin.rs | 1 + src/test/ui/auxiliary/proc_macro_def.rs | 1 + .../ui/bind-by-move/bind-by-move-no-guards.rs | 13 - .../bind-by-move-no-guards.stderr | 11 - src/test/ui/block-expr-precedence.stderr | 8 + .../ui/borrowck/assign_mutable_fields.stderr | 8 +- src/test/ui/borrowck/borrowck-and-init.rs | 2 +- src/test/ui/borrowck/borrowck-and-init.stderr | 4 +- src/test/ui/borrowck/borrowck-asm.rs | 2 +- src/test/ui/borrowck/borrowck-asm.stderr | 4 +- src/test/ui/borrowck/borrowck-block-unint.rs | 2 +- .../ui/borrowck/borrowck-block-unint.stderr | 4 +- .../ui/borrowck/borrowck-break-uninit-2.rs | 2 +- .../borrowck/borrowck-break-uninit-2.stderr | 4 +- src/test/ui/borrowck/borrowck-break-uninit.rs | 2 +- .../ui/borrowck/borrowck-break-uninit.stderr | 4 +- .../ui/borrowck/borrowck-field-sensitivity.rs | 6 +- .../borrowck-field-sensitivity.stderr | 12 +- src/test/ui/borrowck/borrowck-if-no-else.rs | 2 +- .../ui/borrowck/borrowck-if-no-else.stderr | 4 +- src/test/ui/borrowck/borrowck-if-with-else.rs | 2 +- .../ui/borrowck/borrowck-if-with-else.stderr | 4 +- .../borrowck-init-in-called-fn-expr.rs | 2 +- .../borrowck-init-in-called-fn-expr.stderr | 4 +- .../ui/borrowck/borrowck-init-in-fn-expr.rs | 2 +- .../borrowck/borrowck-init-in-fn-expr.stderr | 4 +- src/test/ui/borrowck/borrowck-init-in-fru.rs | 2 +- .../ui/borrowck/borrowck-init-in-fru.stderr | 4 +- .../ui/borrowck/borrowck-init-op-equal.rs | 2 +- .../ui/borrowck/borrowck-init-op-equal.stderr | 4 +- .../ui/borrowck/borrowck-init-plus-equal.rs | 2 +- .../borrowck/borrowck-init-plus-equal.stderr | 4 +- .../borrowck-migrate-to-nll.edition.stderr | 13 +- .../ui/borrowck/borrowck-migrate-to-nll.rs | 6 +- .../borrowck-migrate-to-nll.zflag.stderr | 4 +- .../ui/borrowck/borrowck-mutate-in-guard.rs | 7 +- .../borrowck/borrowck-mutate-in-guard.stderr | 27 +- src/test/ui/borrowck/borrowck-or-init.rs | 2 +- src/test/ui/borrowck/borrowck-or-init.stderr | 4 +- .../ui/borrowck/borrowck-partial-reinit-4.rs | 2 +- .../borrowck/borrowck-partial-reinit-4.stderr | 4 +- src/test/ui/borrowck/borrowck-return.rs | 2 +- src/test/ui/borrowck/borrowck-return.stderr | 4 +- .../ui/borrowck/borrowck-storage-dead.stderr | 4 +- .../ui/borrowck/borrowck-uninit-after-item.rs | 2 +- .../borrowck-uninit-after-item.stderr | 4 +- .../borrowck-uninit-field-access.stderr | 4 +- .../borrowck/borrowck-uninit-in-assignop.rs | 20 +- .../borrowck-uninit-in-assignop.stderr | 40 +- .../ui/borrowck/borrowck-uninit-ref-chain.rs | 8 +- .../borrowck/borrowck-uninit-ref-chain.stderr | 28 +- src/test/ui/borrowck/borrowck-uninit.rs | 2 +- src/test/ui/borrowck/borrowck-uninit.stderr | 4 +- .../borrowck/borrowck-union-uninitialized.rs | 4 +- .../borrowck-union-uninitialized.stderr | 8 +- .../borrowck-use-in-index-lvalue.stderr | 8 +- ...wck-use-uninitialized-in-cast-trait.stderr | 4 +- .../borrowck-use-uninitialized-in-cast.stderr | 4 +- src/test/ui/borrowck/borrowck-while-break.rs | 2 +- .../ui/borrowck/borrowck-while-break.stderr | 4 +- src/test/ui/borrowck/borrowck-while-cond.rs | 2 +- .../ui/borrowck/borrowck-while-cond.stderr | 4 +- src/test/ui/borrowck/borrowck-while.rs | 2 +- src/test/ui/borrowck/borrowck-while.stderr | 4 +- .../disallow-possibly-uninitialized.rs | 8 +- .../disallow-possibly-uninitialized.stderr | 16 +- src/test/ui/borrowck/issue-10876.rs | 2 +- ...-54499-field-mutation-marks-mut-as-used.rs | 6 +- ...99-field-mutation-marks-mut-as-used.stderr | 12 +- ...ssue-54499-field-mutation-of-never-init.rs | 6 +- ...-54499-field-mutation-of-never-init.stderr | 12 +- .../borrowck/issue-62107-match-arm-scopes.rs | 2 +- .../issue-62107-match-arm-scopes.stderr | 4 +- .../ui/borrowck/move-error-snippets-ext.rs | 7 + src/test/ui/borrowck/move-error-snippets.rs | 23 + .../ui/borrowck/move-error-snippets.stderr | 15 + .../reassignment_immutable_fields.stderr | 8 +- ...gnment_immutable_fields_overlapping.stderr | 4 +- ...reassignment_immutable_fields_twice.stderr | 4 +- ...al-binding-from-desugaring.polonius.stderr | 16 + src/test/ui/borrowck/two-phase-across-loop.rs | 2 +- .../two-phase-multiple-activations.rs | 4 +- .../two-phase-surprise-no-conflict.rs | 2 +- src/test/ui/break-outside-loop.rs | 14 +- src/test/ui/break-outside-loop.stderr | 31 +- .../ui/c-variadic/variadic-ffi-4.nll.stderr | 18 +- .../c-variadic/variadic-ffi-no-fixed-args.rs | 6 + .../variadic-ffi-no-fixed-args.stderr | 8 + src/test/ui/chalkify/type_inference.stderr | 8 +- src/test/ui/class-cast-to-trait.stderr | 2 +- .../expect-fn-supply-fn.nll.stderr | 42 +- .../expect-fn-supply-fn.stderr | 42 +- .../expect-infer-var-appearing-twice.stderr | 14 +- src/test/ui/closure-expected.stderr | 4 +- .../ui/closures/closure-array-break-length.rs | 6 +- .../closure-array-break-length.stderr | 12 +- ...ds-cant-promote-superkind-in-struct.stderr | 8 +- .../ui/closures/closure-bounds-subtype.stderr | 12 +- src/test/ui/closures/closure-move-sync.rs | 2 + src/test/ui/closures/closure-move-sync.stderr | 20 +- src/test/ui/codemap_tests/bad-format-args.rs | 2 +- .../ui/codemap_tests/bad-format-args.stderr | 4 +- .../overlapping_inherent_impls.stderr | 2 +- src/test/ui/coercion/coercion-slice.rs | 2 +- src/test/ui/coercion/coercion-slice.stderr | 2 +- ...mpl-trait-for-trait-object-safe.old.stderr | 4 +- ...impl-trait-for-trait-object-safe.re.stderr | 4 +- ...rence-overlap-upstream-inherent.old.stderr | 2 +- ...erence-overlap-upstream-inherent.re.stderr | 2 +- .../coherence-overlap-upstream.old.stderr | 2 +- .../coherence-overlap-upstream.re.stderr | 2 +- ...ence-projection-conflict-orphan.old.stderr | 2 +- ...rence-projection-conflict-orphan.re.stderr | 2 +- ...ke_err_fundamental_struct_tuple.old.stderr | 2 +- ...ike_err_fundamental_struct_tuple.re.stderr | 2 +- .../coherence_copy_like_err_struct.old.stderr | 2 +- .../coherence_copy_like_err_struct.re.stderr | 2 +- .../coherence_copy_like_err_tuple.old.stderr | 2 +- .../coherence_copy_like_err_tuple.re.stderr | 2 +- .../coherence/coherence_inherent.old.stderr | 2 +- .../ui/coherence/coherence_inherent.re.stderr | 2 +- .../coherence_inherent_cc.old.stderr | 2 +- .../coherence/coherence_inherent_cc.re.stderr | 2 +- .../ui/coherence/conflicting-impl-with-err.rs | 16 + .../conflicting-impl-with-err.stderr | 15 + src/test/ui/collections-const-new.rs | 8 +- src/test/ui/commandline-argfile-badutf8.args | 2 + src/test/ui/commandline-argfile-badutf8.rs | 13 + .../ui/commandline-argfile-badutf8.stderr | 2 + src/test/ui/commandline-argfile-missing.rs | 16 + .../ui/commandline-argfile-missing.stderr | 2 + src/test/ui/commandline-argfile.args | 2 + src/test/ui/commandline-argfile.rs | 13 + .../reordered-type-param.stderr | 2 + .../cfg-arg-invalid-6.rs | 3 + .../cfg-arg-invalid-6.stderr | 2 + .../cfg-attr-cfg-2.stderr | 5 +- .../cfg-attr-crate-2.rs | 2 +- .../cfg-attr-crate-2.stderr | 2 +- .../cfg-attr-multi-invalid-1.rs | 3 +- .../cfg-attr-multi-invalid-1.stderr | 2 +- .../cfg-attr-multi-invalid-2.rs | 3 +- .../cfg-attr-multi-invalid-2.stderr | 2 +- ...-attr-unknown-attribute-macro-expansion.rs | 2 +- ...r-unknown-attribute-macro-expansion.stderr | 2 +- .../cfg-generic-params.rs | 12 +- .../cfg-generic-params.stderr | 52 +- .../cfg-in-crate-1.stderr | 4 +- .../const-generics/apit-with-const-param.rs | 2 +- .../core-traits-no-impls-length-33.stderr | 4 +- .../array-wrapper-struct-ctor.rs | 2 + src/test/ui/const-generics/const-types.rs | 2 +- .../foreign-item-const-parameter.rs | 10 + .../foreign-item-const-parameter.stderr | 27 + .../invalid-const-arg-for-type-param.stderr | 2 +- src/test/ui/const-generics/issue-61422.rs | 4 +- src/test/ui/const-generics/issue-61432.rs | 17 + src/test/ui/const-generics/issue-61432.stderr | 8 + src/test/ui/const-generics/issue-64519.rs | 21 + src/test/ui/const-generics/issue-64519.stderr | 8 + .../ui/const-generics/unused-const-param.rs | 2 +- src/test/ui/consts/array-literal-index-oob.rs | 1 - .../ui/consts/array-literal-index-oob.stderr | 8 +- src/test/ui/consts/auxiliary/issue-63226.rs | 14 + src/test/ui/consts/const-err2.rs | 3 +- src/test/ui/consts/const-err2.stderr | 12 +- src/test/ui/consts/const-err3.rs | 30 + src/test/ui/consts/const-err3.stderr | 38 + src/test/ui/consts/const-err4.stderr | 2 +- .../const-pointer-values-in-various-types.rs | 1 + ...nst-pointer-values-in-various-types.stderr | 76 +- src/test/ui/consts/const-eval/const_fn_ptr.rs | 37 + .../ui/consts/const-eval/const_fn_ptr.stderr | 152 + .../ui/consts/const-eval/const_fn_ptr_fail.rs | 13 + .../consts/const-eval/const_fn_ptr_fail2.rs | 26 + .../const-eval/const_fn_ptr_fail2.stderr | 71 + .../ui/consts/const-eval/const_transmute.rs | 2 + src/test/ui/consts/const-eval/dangling.rs | 13 + src/test/ui/consts/const-eval/dangling.stderr | 16 + src/test/ui/consts/const-eval/double_check.rs | 1 + .../ui/consts/const-eval/double_check2.rs | 1 + .../ui/consts/const-eval/double_check2.stderr | 4 +- .../const-eval/feature-gate-const_fn_union.rs | 1 + .../feature-gate-const_fn_union.stderr | 2 +- .../ui/consts/const-eval/issue-43197.stderr | 8 +- src/test/ui/consts/const-eval/issue-49296.rs | 1 + .../ui/consts/const-eval/issue-49296.stderr | 2 +- .../const-eval/promoted_const_fn_fail.rs | 1 + .../const-eval/promoted_const_fn_fail.stderr | 2 +- .../promoted_const_fn_fail_deny_const_err.rs | 1 + ...omoted_const_fn_fail_deny_const_err.stderr | 2 +- .../ui/consts/const-eval/promoted_errors.rs | 8 +- .../consts/const-eval/promoted_errors.stderr | 30 +- .../ui/consts/const-eval/promoted_errors2.rs | 22 + .../consts/const-eval/promoted_errors2.stderr | 68 + .../ui/consts/const-eval/ref_to_int_match.rs | 1 + .../consts/const-eval/ref_to_int_match.stderr | 4 +- src/test/ui/consts/const-eval/strlen.rs | 12 +- .../consts/const-eval/transmute-const.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.rs | 3 + src/test/ui/consts/const-eval/ub-enum.stderr | 36 +- src/test/ui/consts/const-eval/ub-nonnull.rs | 10 +- .../ui/consts/const-eval/ub-nonnull.stderr | 41 +- src/test/ui/consts/const-eval/ub-ref.rs | 5 +- src/test/ui/consts/const-eval/ub-ref.stderr | 16 +- src/test/ui/consts/const-eval/ub-uninhabit.rs | 1 + .../ui/consts/const-eval/ub-uninhabit.stderr | 12 +- src/test/ui/consts/const-eval/ub-upvars.rs | 2 +- .../ui/consts/const-eval/ub-upvars.stderr | 2 +- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 159 + .../ui/consts/const-eval/ub-wide-ptr.stderr | 147 + .../const-eval/union-const-eval-field.rs | 1 + .../const-eval/union-const-eval-field.stderr | 4 +- src/test/ui/consts/const-eval/union-ice.rs | 1 + .../ui/consts/const-eval/union-ice.stderr | 12 +- .../ui/consts/const-eval/union-ub-fat-ptr.rs | 131 - .../consts/const-eval/union-ub-fat-ptr.stderr | 115 - src/test/ui/consts/const-eval/union-ub.rs | 3 + src/test/ui/consts/const-eval/union-ub.stderr | 4 +- .../ui/consts/const-eval/union_promotion.rs | 1 + .../consts/const-eval/union_promotion.stderr | 2 +- src/test/ui/consts/const-eval/valid-const.rs | 3 +- .../ui/consts/const-int-overflowing-rpass.rs | 8 + src/test/ui/consts/const-int-sign-rpass.rs | 6 + .../ui/consts/const-int-wrapping-rpass.rs | 8 + src/test/ui/consts/const-labeled-break.rs | 2 +- .../ui/consts/const-match-check.eval1.stderr | 4 +- .../ui/consts/const-match-check.eval2.stderr | 4 +- .../consts/const-match-check.matchck.stderr | 16 +- .../ui/consts/const-pattern-irrefutable.rs | 6 +- .../consts/const-pattern-irrefutable.stderr | 6 +- src/test/ui/consts/const-size_of-cycle.stderr | 15 +- src/test/ui/consts/const_let_refutable.rs | 4 +- src/test/ui/consts/const_let_refutable.stderr | 12 +- src/test/ui/consts/issue-63226.rs | 12 + src/test/ui/consts/issue-64059-2.rs | 6 + src/test/ui/consts/issue-64059.rs | 5 + src/test/ui/consts/match_ice.stderr | 3 + .../min_const_fn/min_const_fn_unsafe_bad.rs | 16 + ....stderr => min_const_fn_unsafe_bad.stderr} | 18 +- ...fn_unsafe.rs => min_const_fn_unsafe_ok.rs} | 23 +- .../miri_unleashed/enum_discriminants.rs | 110 + .../miri_unleashed/enum_discriminants.stderr | 72 + ...ure-gate-unleash_the_miri_inside_of_you.rs | 3 +- ...gate-unleash_the_miri_inside_of_you.stderr | 10 +- .../ui/consts/miri_unleashed/mutable_const.rs | 20 + .../miri_unleashed/mutable_const.stderr | 27 + .../mutable_references_ice.stderr | 2 +- src/test/ui/consts/packed_pattern.stderr | 8 + src/test/ui/consts/packed_pattern2.stderr | 8 + src/test/ui/consts/std/alloc.stderr | 2 +- src/test/ui/consts/too_generic_eval_ice.rs | 13 + .../ui/consts/too_generic_eval_ice.stderr | 43 + .../ui/consts/validate_never_arrays.stderr | 2 +- src/test/ui/consts/zst_no_llvm_alloc.rs | 19 + .../ui/continue-after-missing-main.nll.stderr | 10 +- .../ui/continue-after-missing-main.stderr | 10 +- src/test/ui/copy-a-resource.stderr | 2 +- src/test/ui/custom_attribute.rs | 6 +- src/test/ui/custom_attribute.stderr | 6 +- src/test/ui/dead-code-ret.stderr | 4 +- src/test/ui/defaulted-never-note.rs | 3 +- src/test/ui/defaulted-never-note.stderr | 10 +- .../ui/deprecation/deprecation-in-future.rs | 2 +- src/test/ui/derive-uninhabited-enum-38885.rs | 11 +- .../ui/derive-uninhabited-enum-38885.stderr | 14 +- .../derives/derive-assoc-type-not-impl.stderr | 2 +- src/test/ui/derives/derive-hygiene.rs | 121 + .../derives-span-Hash-enum-struct-variant.rs | 2 + ...rives-span-Hash-enum-struct-variant.stderr | 7 +- src/test/ui/derives/derives-span-Hash-enum.rs | 2 + .../ui/derives/derives-span-Hash-enum.stderr | 7 +- .../ui/derives/derives-span-Hash-struct.rs | 2 + .../derives/derives-span-Hash-struct.stderr | 7 +- .../derives/derives-span-Hash-tuple-struct.rs | 2 + .../derives-span-Hash-tuple-struct.stderr | 7 +- src/test/ui/derives/deriving-bounds.stderr | 24 +- src/test/ui/derives/deriving-copyclone.stderr | 36 +- .../issue-39802-show-5-trait-impls.stderr | 36 +- src/test/ui/did_you_mean/issue-40006.stderr | 5 +- src/test/ui/did_you_mean/issue-40396.rs | 11 - src/test/ui/did_you_mean/issue-40396.stderr | 80 +- ...-identifier-not-instead-of-negation.stderr | 5 +- .../ui/did_you_mean/multiple-pattern-typo.rs | 7 - .../did_you_mean/multiple-pattern-typo.stderr | 8 - .../ui/did_you_mean/recursion_limit.stderr | 8 +- src/test/ui/drop/dropck_legal_cycles.rs | 30 +- src/test/ui/drop/dynamic-drop-async.rs | 4 +- ...dropck_trait_cycle_checked.polonius.stderr | 12 +- .../dropck/dropck_trait_cycle_checked.stderr | 10 +- .../duplicate/duplicate-type-parameter.stderr | 14 +- .../edition-keywords-2015-2018-expansion.rs | 2 +- ...dition-keywords-2015-2018-expansion.stderr | 4 +- .../edition-keywords-2018-2015-parsing.rs | 4 +- .../edition-keywords-2018-2015-parsing.stderr | 8 +- .../edition-keywords-2018-2018-expansion.rs | 2 +- ...dition-keywords-2018-2018-expansion.stderr | 4 +- .../edition-keywords-2018-2018-parsing.rs | 4 +- .../edition-keywords-2018-2018-parsing.stderr | 8 +- src/test/ui/elided-test.stderr | 6 +- src/test/ui/empty/empty-macro-use.stderr | 2 +- src/test/ui/empty/empty-never-array.rs | 2 +- src/test/ui/empty/empty-never-array.stderr | 5 +- .../ui/empty/empty-struct-tuple-pat.stderr | 7 +- src/test/ui/error-codes/E0008.rs | 7 - src/test/ui/error-codes/E0008.stderr | 11 - src/test/ui/error-codes/E0023.rs | 5 +- src/test/ui/error-codes/E0023.stderr | 43 +- src/test/ui/error-codes/E0033-teach.rs | 3 +- src/test/ui/error-codes/E0033-teach.stderr | 7 +- src/test/ui/error-codes/E0033.rs | 3 +- src/test/ui/error-codes/E0033.stderr | 7 +- src/test/ui/error-codes/E0038.stderr | 5 +- src/test/ui/error-codes/E0044.rs | 2 +- src/test/ui/error-codes/E0044.stderr | 2 +- src/test/ui/error-codes/E0138.stderr | 2 +- src/test/ui/error-codes/E0194.rs | 2 +- src/test/ui/error-codes/E0194.stderr | 8 +- src/test/ui/error-codes/E0214.stderr | 10 +- src/test/ui/error-codes/E0267.stderr | 4 +- src/test/ui/error-codes/E0268.stderr | 4 +- src/test/ui/error-codes/E0271.stderr | 8 +- src/test/ui/error-codes/E0275.stderr | 8 +- src/test/ui/error-codes/E0277-2.stderr | 8 +- src/test/ui/error-codes/E0277.stderr | 13 +- src/test/ui/error-codes/E0282.stderr | 5 +- src/test/ui/error-codes/E0283.stderr | 9 +- src/test/ui/error-codes/E0301.rs | 7 - src/test/ui/error-codes/E0301.stderr | 20 - src/test/ui/error-codes/E0302.rs | 8 - src/test/ui/error-codes/E0302.stderr | 17 - src/test/ui/error-codes/E0403.stderr | 2 +- src/test/ui/error-codes/E0601.rs | 2 +- src/test/ui/error-codes/E0601.stderr | 4 +- src/test/ui/error-festival.stderr | 2 +- .../ui/error-should-say-copy-not-pod.stderr | 13 +- .../explicit-self-lifetime-mismatch.rs | 4 +- .../explicit-self-lifetime-mismatch.stderr | 4 +- src/test/ui/ext-nonexistent.stderr | 2 +- src/test/ui/extenv/issue-55897.rs | 2 +- src/test/ui/extenv/issue-55897.stderr | 8 +- .../extern/extern-types-not-sync-send.stderr | 24 +- .../ui/extern/extern-types-unsized.stderr | 36 +- .../ui/extern/extern-wrong-value-type.stderr | 12 +- ...llow-unwind-when-calling-panic-directly.rs | 65 + ...sue-64655-extern-rust-must-allow-unwind.rs | 83 + .../ui/feature-gate-optimize_attribute.rs | 10 +- .../ui/feature-gate-optimize_attribute.stderr | 10 +- .../ui/feature-gate/allow-features-empty.rs | 2 - .../feature-gate/allow-features-empty.stderr | 14 +- src/test/ui/feature-gate/allow-features.rs | 4 +- .../ui/feature-gate/allow-features.stderr | 4 +- .../feature-gate-static-nobundle-2.rs | 2 +- .../feature-gate-static-nobundle-2.stderr | 2 +- .../issue-43106-gating-of-builtin-attrs.rs | 4 +- ...issue-43106-gating-of-builtin-attrs.stderr | 14 + .../issue-43106-gating-of-derive-2.stderr | 4 +- .../issue-43106-gating-of-derive.rs | 3 - .../issue-43106-gating-of-derive.stderr | 16 +- src/test/ui/feature-gates/feature-gate-abi.rs | 10 +- .../ui/feature-gates/feature-gate-abi.stderr | 187 +- .../feature-gate-alloc-error-handler.rs | 2 +- .../feature-gate-alloc-error-handler.stderr | 2 +- .../feature-gates/feature-gate-allow_fail.rs | 2 +- .../feature-gate-allow_fail.stderr | 2 +- .../feature-gate-async-await-2015-edition.rs | 9 - ...ature-gate-async-await-2015-edition.stderr | 31 - .../feature-gates/feature-gate-async-await.rs | 18 - .../feature-gate-async-await.stderr | 45 - .../feature-gate-custom_attribute.rs | 26 +- .../feature-gate-custom_attribute.stderr | 26 +- .../feature-gate-custom_attribute2.rs | 34 +- .../feature-gate-custom_attribute2.stderr | 186 +- .../feature-gates/feature-gate-doc_alias.rs | 2 +- .../feature-gate-doc_alias.stderr | 2 +- .../ui/feature-gates/feature-gate-doc_cfg.rs | 2 +- .../feature-gates/feature-gate-doc_cfg.stderr | 2 +- .../feature-gates/feature-gate-doc_keyword.rs | 2 +- .../feature-gate-doc_keyword.stderr | 2 +- .../feature-gate-external_doc.rs | 2 +- .../feature-gate-external_doc.stderr | 2 +- .../feature-gates/feature-gate-generators.rs | 6 + .../feature-gate-generators.stderr | 20 +- .../feature-gates/feature-gate-intrinsics.rs | 1 + .../feature-gate-intrinsics.stderr | 8 +- .../feature-gates/feature-gate-is_sorted.rs | 4 +- .../ui/feature-gates/feature-gate-link_cfg.rs | 2 +- .../feature-gate-link_cfg.stderr | 2 +- .../feature-gate-marker_trait_attr.rs | 2 +- .../feature-gate-marker_trait_attr.stderr | 2 +- .../ui/feature-gates/feature-gate-no_core.rs | 2 +- .../feature-gates/feature-gate-no_core.stderr | 2 +- .../feature-gate-non_exhaustive.rs | 2 +- .../feature-gate-non_exhaustive.stderr | 2 +- .../feature-gates/feature-gate-rustc-attrs.rs | 4 +- .../feature-gate-rustc-attrs.stderr | 4 +- .../feature-gate-rustc-diagnostic-macros.rs | 13 - ...eature-gate-rustc-diagnostic-macros.stderr | 20 - .../feature-gate-static-nobundle.rs | 2 +- .../feature-gate-static-nobundle.stderr | 2 +- .../feature-gate-type_ascription.rs | 2 +- ...-gate-unboxed-closures-manual-impls.stderr | 4 +- .../feature-gate-unwind-attributes.rs | 2 +- .../feature-gate-unwind-attributes.stderr | 2 +- src/test/ui/fmt/send-sync.stderr | 16 +- src/test/ui/fn/fn-trait-formatting.stderr | 12 +- src/test/ui/for/for-c-in-str.rs | 5 +- ...oop-refutable-pattern-error-message.stderr | 4 +- ...for-loop-unconstrained-element-type.stderr | 5 +- ...erator-yielding-or-returning-itself.stderr | 13 +- .../ui/generator/auto-trait-regions.stderr | 18 +- .../issue-61442-stmt-expr-with-drop.rs | 2 +- .../ui/generator/issue-62506-two_awaits.rs | 1 - .../generator/niche-in-generator.rs | 2 + .../no-arguments-on-generators.stderr | 8 - ...tors.rs => no-parameters-on-generators.rs} | 2 +- .../no-parameters-on-generators.stderr | 8 + src/test/ui/generator/not-send-sync.stderr | 16 +- .../partial-initialization-across-yield.rs | 6 +- ...partial-initialization-across-yield.stderr | 12 +- src/test/ui/generator/static-not-unpin.stderr | 13 +- src/test/ui/generic/generic-extern.stderr | 2 +- .../hrtb-type-outlives.rs | 2 - src/test/ui/hrtb/due-to-where-clause.rs | 16 + src/test/ui/hrtb/due-to-where-clause.stderr | 14 + .../ui/hrtb/hrtb-cache-issue-54302.stderr | 9 +- src/test/ui/hrtb/hrtb-conflate-regions.rs | 1 - src/test/ui/hrtb/hrtb-conflate-regions.stderr | 17 +- ...b-exists-forall-trait-contravariant.stderr | 19 +- .../hrtb-exists-forall-trait-covariant.stderr | 19 +- .../hrtb-exists-forall-trait-invariant.stderr | 19 +- ...igher-ranker-supertraits-transitive.stderr | 17 +- .../hrtb-higher-ranker-supertraits.stderr | 39 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 34 +- src/test/ui/hrtb/issue-30786.migrate.stderr | 14 +- src/test/ui/hrtb/issue-30786.nll.stderr | 4 +- src/test/ui/hrtb/issue-30786.rs | 3 +- src/test/ui/hrtb/issue-46989.stderr | 12 +- src/test/ui/hrtb/issue-57639.rs | 2 +- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 2 + .../ui/hygiene/auxiliary/codegen-attrs.rs | 10 + src/test/ui/hygiene/auxiliary/not-libstd.rs | 1 + .../ui/hygiene/cross-crate-codegen-attrs.rs | 12 + .../ui/hygiene/no_implicit_prelude-2018.rs | 2 +- .../hygiene/no_implicit_prelude-2018.stderr | 2 +- src/test/ui/hygiene/no_implicit_prelude.rs | 2 +- .../ui/hygiene/no_implicit_prelude.stderr | 18 +- src/test/ui/hygiene/prelude-import-hygiene.rs | 29 + src/test/ui/hygiene/trait_items.stderr | 2 +- src/test/ui/hygiene/unpretty-debug.stdout | 10 + src/test/ui/if-ret.stderr | 10 + src/test/ui/if/if-without-else-as-fn-expr.rs | 6 - .../ui/if/if-without-else-as-fn-expr.stderr | 83 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 8 +- .../ui/impl-trait/auto-trait-leak2.stderr | 16 +- src/test/ui/impl-trait/bindings-opaque.stderr | 6 +- .../ui/impl-trait/bound-normalization-fail.rs | 7 +- .../bound-normalization-fail.stderr | 16 +- .../ui/impl-trait/bound-normalization-pass.rs | 5 - .../bound-normalization-pass.stderr | 2 +- .../impl-trait/closure-calling-parent-fn.rs | 2 +- .../dyn-trait-elided-two-inputs-assoc.rs | 16 + .../dyn-trait-elided-two-inputs-param.rs | 11 + .../dyn-trait-elided-two-inputs-ref-assoc.rs | 27 + .../dyn-trait-elided-two-inputs-ref-param.rs | 23 + src/test/ui/impl-trait/equality2.stderr | 2 + .../impl-generic-mismatch-ab.stderr | 2 + src/test/ui/impl-trait/issue-55872-2.rs | 3 +- src/test/ui/impl-trait/issue-55872-2.stderr | 4 +- ...e-21659-show-relevant-trait-impls-3.stderr | 2 +- src/test/ui/impl-trait/issues/issue-53457.rs | 4 +- .../method-suggestion-no-duplication.stderr | 2 +- .../multiple-lifetimes/inverse-bounds.rs | 2 +- .../impl-trait/needs_least_region_or_bound.rs | 4 +- .../no-method-suggested-traits.stderr | 56 +- ...-impl-trait-type--through-non-recursize.rs | 25 + ...l-trait-type--through-non-recursize.stderr | 35 + .../universal-mismatched-type.stderr | 2 + .../universal-two-impl-traits.stderr | 2 + src/test/ui/imports/gensymed.rs | 4 +- .../local-modularized-tricky-fail-1.stderr | 38 +- src/test/ui/imports/reexports.rs | 9 +- src/test/ui/imports/reexports.stderr | 28 +- .../ui/imports/shadow_builtin_macros.stderr | 28 +- .../ui/imports/unresolved-imports-used.rs | 14 +- .../ui/imports/unresolved-imports-used.stderr | 44 +- src/test/ui/in-band-lifetimes/nested-items.rs | 20 + src/test/ui/inaccessible-test-modules.stderr | 21 - src/test/ui/include-macros/data.bin | 2 + src/test/ui/include-macros/normalization.rs | 12 + ...infer-async-enabled-impl-trait-bindings.rs | 17 + ...r-async-enabled-impl-trait-bindings.stderr | 19 + src/test/ui/inference/cannot-infer-async.rs | 15 + .../ui/inference/cannot-infer-async.stderr | 11 + src/test/ui/inference/cannot-infer-closure.rs | 6 + .../ui/inference/cannot-infer-closure.stderr | 13 + .../ui/infinite/infinite-autoderef.stderr | 2 +- src/test/ui/inline-asm-bad-operand.stderr | 4 +- .../interior-mutability.rs | 2 + .../interior-mutability.stderr | 10 +- src/test/ui/intrinsics-always-extern.rs | 16 + src/test/ui/intrinsics-always-extern.stderr | 24 + src/test/ui/issues/issue-10291.stderr | 1 + src/test/ui/issues/issue-10465.stderr | 2 +- src/test/ui/issues/issue-11692-1.rs | 2 +- src/test/ui/issues/issue-11692-1.stderr | 2 +- src/test/ui/issues/issue-11692-2.rs | 2 +- src/test/ui/issues/issue-11692-2.stderr | 2 +- src/test/ui/issues/issue-12028.rs | 2 - src/test/ui/issues/issue-12028.stderr | 2 +- src/test/ui/issues/issue-1251.rs | 2 - src/test/ui/issues/issue-13483.stderr | 4 +- src/test/ui/issues/issue-13853.stderr | 4 +- src/test/ui/issues/issue-14309.rs | 2 +- src/test/ui/issues/issue-14309.stderr | 25 +- src/test/ui/issues/issue-15207.stderr | 2 +- src/test/ui/issues/issue-15381.rs | 4 +- src/test/ui/issues/issue-15381.stderr | 8 +- src/test/ui/issues/issue-15783.rs | 8 +- src/test/ui/issues/issue-15783.stderr | 2 +- src/test/ui/issues/issue-16250.rs | 2 +- src/test/ui/issues/issue-16250.stderr | 5 +- src/test/ui/issues/issue-16739.rs | 4 - src/test/ui/issues/issue-17651.rs | 1 + src/test/ui/issues/issue-17651.stderr | 15 +- src/test/ui/issues/issue-17740.rs | 4 +- src/test/ui/issues/issue-17740.stderr | 4 +- src/test/ui/issues/issue-17905-2.rs | 4 +- src/test/ui/issues/issue-17905-2.stderr | 4 +- src/test/ui/issues/issue-18159.stderr | 5 +- src/test/ui/issues/issue-1871.stderr | 2 +- src/test/ui/issues/issue-18959.stderr | 5 +- src/test/ui/issues/issue-1920-1.stderr | 13 +- src/test/ui/issues/issue-1920-2.stderr | 13 +- src/test/ui/issues/issue-1920-3.stderr | 13 +- src/test/ui/issues/issue-19380.stderr | 5 +- src/test/ui/issues/issue-19521.stderr | 2 +- src/test/ui/issues/issue-19538.stderr | 9 +- src/test/ui/issues/issue-19692.stderr | 2 +- src/test/ui/issues/issue-19734.rs | 2 +- src/test/ui/issues/issue-19734.stderr | 2 +- src/test/ui/issues/issue-20005.stderr | 8 +- src/test/ui/issues/issue-20225.stderr | 6 + src/test/ui/issues/issue-20413.stderr | 16 +- src/test/ui/issues/issue-21160.rs | 2 + src/test/ui/issues/issue-21160.stderr | 7 +- src/test/ui/issues/issue-2149.stderr | 2 +- src/test/ui/issues/issue-2150.stderr | 5 +- src/test/ui/issues/issue-21596.stderr | 2 +- src/test/ui/issues/issue-21763.stderr | 8 +- src/test/ui/issues/issue-21837.stderr | 8 +- src/test/ui/issues/issue-21974.stderr | 9 +- src/test/ui/issues/issue-23589.stderr | 10 +- src/test/ui/issues/issue-23966.stderr | 4 +- src/test/ui/issues/issue-24204.stderr | 9 +- src/test/ui/issues/issue-24267-flow-exit.rs | 4 +- .../ui/issues/issue-24267-flow-exit.stderr | 8 +- src/test/ui/issues/issue-24424.stderr | 9 +- ...535-allow-mutable-borrow-in-match-guard.rs | 2 - src/test/ui/issues/issue-25076.stderr | 13 +- src/test/ui/issues/issue-25385.stderr | 4 +- src/test/ui/issues/issue-26448-2.rs | 2 +- src/test/ui/issues/issue-26448-3.rs | 2 +- .../issue-27282-reborrow-ref-mut-in-guard.rs | 2 - ...sue-27282-reborrow-ref-mut-in-guard.stderr | 2 +- src/test/ui/issues/issue-27697.rs | 2 +- src/test/ui/issues/issue-28098.rs | 2 + src/test/ui/issues/issue-28098.stderr | 36 +- src/test/ui/issues/issue-28105.rs | 4 +- src/test/ui/issues/issue-28105.stderr | 8 +- src/test/ui/issues/issue-2823.stderr | 2 +- src/test/ui/issues/issue-29124.stderr | 4 +- src/test/ui/issues/issue-29147.stderr | 9 +- src/test/ui/issues/issue-29181.stderr | 2 +- src/test/ui/issues/issue-2951.stderr | 2 + src/test/ui/issues/issue-31173.stderr | 2 +- src/test/ui/issues/issue-31561.rs | 2 +- src/test/ui/issues/issue-31561.stderr | 6 +- src/test/ui/issues/issue-31776.rs | 6 +- src/test/ui/issues/issue-32004.stderr | 5 +- src/test/ui/issues/issue-32323.stderr | 2 + src/test/ui/issues/issue-32655.rs | 4 +- src/test/ui/issues/issue-32655.stderr | 4 +- src/test/ui/issues/issue-32963.stderr | 9 +- src/test/ui/issues/issue-32995-2.stderr | 12 +- src/test/ui/issues/issue-32995.stderr | 28 +- src/test/ui/issues/issue-33575.rs | 4 + src/test/ui/issues/issue-33575.stderr | 9 + src/test/ui/issues/issue-34334.stderr | 2 +- src/test/ui/issues/issue-35677.stderr | 2 +- src/test/ui/issues/issue-36617.rs | 1 + src/test/ui/issues/issue-36617.stderr | 10 +- src/test/ui/issues/issue-36836.rs | 15 + src/test/ui/issues/issue-36836.stderr | 9 + src/test/ui/issues/issue-38591.rs | 2 +- src/test/ui/issues/issue-39175.stderr | 2 +- src/test/ui/issues/issue-39687.stderr | 4 +- src/test/ui/issues/issue-39970.stderr | 8 +- src/test/ui/issues/issue-40827.stderr | 16 +- src/test/ui/issues/issue-40845.rs | 4 +- src/test/ui/issues/issue-40845.stderr | 4 +- src/test/ui/issues/issue-41880.stderr | 2 +- src/test/ui/issues/issue-43162.stderr | 8 +- src/test/ui/issues/issue-43189.stderr | 2 +- src/test/ui/issues/issue-43623.stderr | 34 +- src/test/ui/issues/issue-43806.rs | 2 +- src/test/ui/issues/issue-44415.stderr | 28 - src/test/ui/issues/issue-46101.rs | 2 + src/test/ui/issues/issue-46101.stderr | 9 +- src/test/ui/issues/issue-47706-trait.stderr | 4 +- src/test/ui/issues/issue-47706.stderr | 24 +- src/test/ui/issues/issue-48132.rs | 2 + src/test/ui/issues/issue-48179.rs | 2 +- src/test/ui/issues/issue-48728.stderr | 2 +- src/test/ui/issues/issue-49040.rs | 1 + src/test/ui/issues/issue-49040.stderr | 6 +- src/test/ui/issues/issue-49074.rs | 4 +- src/test/ui/issues/issue-49074.stderr | 14 +- src/test/ui/issues/issue-49934-errors.rs | 13 + src/test/ui/issues/issue-49934-errors.stderr | 26 + src/test/ui/issues/issue-49934.rs | 9 +- src/test/ui/issues/issue-49934.stderr | 26 +- .../option-as_deref_mut.stderr | 2 +- src/test/ui/issues/issue-50301.rs | 31 + src/test/ui/issues/issue-50415.rs | 6 +- src/test/ui/issues/issue-50576.stderr | 8 +- src/test/ui/issues/issue-50577.rs | 1 - src/test/ui/issues/issue-50577.stderr | 15 +- src/test/ui/issues/issue-50581.stderr | 4 +- src/test/ui/issues/issue-5067.rs | 4 +- src/test/ui/issues/issue-50781.stderr | 4 +- src/test/ui/issues/issue-5153.stderr | 2 +- src/test/ui/issues/issue-52060.rs | 1 - src/test/ui/issues/issue-52060.stderr | 10 +- src/test/ui/issues/issue-52533.stderr | 1 + src/test/ui/issues/issue-54062.stderr | 2 +- src/test/ui/issues/issue-54302-cases.stderr | 54 +- src/test/ui/issues/issue-54302.stderr | 9 +- src/test/ui/issues/issue-55731.stderr | 13 +- src/test/ui/issues/issue-56806.rs | 5 +- src/test/ui/issues/issue-56806.stderr | 5 +- src/test/ui/issues/issue-57362-1.stderr | 2 +- src/test/ui/issues/issue-60057.rs | 2 + src/test/ui/issues/issue-60057.stderr | 9 +- src/test/ui/issues/issue-60283.stderr | 38 +- .../issue-61711-once-caused-rustc-inf-loop.rs | 2 +- src/test/ui/issues/issue-63983.rs | 15 + src/test/ui/issues/issue-63983.stderr | 15 + src/test/ui/issues/issue-64430.rs | 14 + src/test/ui/issues/issue-64430.stderr | 12 + src/test/ui/issues/issue-64559.rs | 6 + src/test/ui/issues/issue-64559.stderr | 18 + src/test/ui/issues/issue-64593.rs | 12 + src/test/ui/issues/issue-65611.rs | 63 + src/test/ui/issues/issue-65611.stderr | 18 + src/test/ui/issues/issue-6919.rs | 1 - src/test/ui/issues/issue-7246.stderr | 4 +- src/test/ui/issues/issue-8460-const.rs | 2 + src/test/ui/issues/issue-8460-const.stderr | 82 +- src/test/ui/issues/issue-8460-const2.rs | 59 + src/test/ui/issues/issue-8460-const2.stderr | 188 + src/test/ui/iterators/bound.stderr | 7 +- .../ui/iterators/iter-count-overflow-debug.rs | 16 + .../iterators/iter-count-overflow-ndebug.rs | 11 + .../ui/iterators/iter-map-fold-type-length.rs | 38 + .../iterators/iter-position-overflow-debug.rs | 22 + .../iter-position-overflow-ndebug.rs | 13 + src/test/ui/json-multiple.polonius.stderr | 1 + src/test/ui/json-options.polonius.stderr | 1 + src/test/ui/json-short.stderr | 4 +- .../keyword-extern-as-identifier-pat.rs | 2 +- .../keyword-extern-as-identifier-pat.stderr | 8 +- src/test/ui/kindck/kindck-copy.stderr | 133 +- .../kindck/kindck-impl-type-params-2.stderr | 12 +- .../kindck/kindck-inherited-copy-bound.stderr | 12 +- .../ui/kindck/kindck-nonsendable-1.stderr | 8 +- src/test/ui/kindck/kindck-send-object.stderr | 16 +- .../ui/kindck/kindck-send-object1.nll.stderr | 16 +- src/test/ui/kindck/kindck-send-object1.stderr | 16 +- src/test/ui/kindck/kindck-send-object2.stderr | 16 +- src/test/ui/kindck/kindck-send-owned.stderr | 8 +- src/test/ui/kindck/kindck-send-unsafe.stderr | 12 +- src/test/ui/lang-item-missing-generator.rs | 19 + .../ui/lang-item-missing-generator.stderr | 8 + src/test/ui/lifetime-before-type-params.rs | 2 + .../ui/lifetime-before-type-params.stderr | 7 +- .../lifetime-elision-return-type-trait.rs | 2 +- .../lifetime-elision-return-type-trait.stderr | 10 +- .../ex3-both-anon-regions-3.nll.stderr | 6 +- src/test/ui/lint/empty-lint-attributes.rs | 2 +- .../ui/lint/issue-54538-unused-parens-lint.rs | 92 +- .../issue-54538-unused-parens-lint.stderr | 136 +- .../ui/lint/lint-attr-non-item-node.stderr | 4 +- src/test/ui/lint/lint-ctypes-enum.rs | 21 +- src/test/ui/lint/lint-ctypes-enum.stderr | 77 +- src/test/ui/lint/lint-ctypes.rs | 13 +- src/test/ui/lint/lint-ctypes.stderr | 127 +- .../ui/lint/lint-dead-code-const-and-self.rs | 35 + .../lint-dead-code-empty-unused-enum-pub.rs | 6 + .../lint/lint-dead-code-empty-unused-enum.rs | 5 + .../lint-dead-code-empty-unused-enum.stderr | 15 + .../ui/lint/lint-dead-code-unused-enum.rs | 11 + .../ui/lint/lint-dead-code-unused-enum.stderr | 27 + .../lint/lint-dead-code-unused-variant-pub.rs | 14 + .../ui/lint/lint-dead-code-unused-variant.rs | 13 + .../lint/lint-dead-code-unused-variant.stderr | 15 + src/test/ui/lint/lint-qualification.rs | 2 +- .../ui/lint/lint-stability-deprecated.stderr | 36 +- src/test/ui/lint/lint-unused-mut-variables.rs | 2 +- src/test/ui/lint/lint-unused-variables.rs | 17 +- src/test/ui/lint/lint-unused-variables.stderr | 28 +- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 16 + src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 15 + .../redundant-semi-proc-macro-def.rs | 12 + .../redundant-semi-proc-macro.rs | 19 + .../redundant-semi-proc-macro.stderr | 21 + src/test/ui/lint/uninitialized-zeroed.rs | 31 +- src/test/ui/lint/uninitialized-zeroed.stderr | 158 +- src/test/ui/lint/unreachable-async-fn.rs | 9 + src/test/ui/lint/use_suggestion_json.stderr | 2 +- src/test/ui/liveness/liveness-unused.stderr | 4 +- src/test/ui/loops/loop-proper-liveness.rs | 2 +- src/test/ui/loops/loop-proper-liveness.stderr | 4 +- src/test/ui/lto-duplicate-symbols.stderr | 2 +- src/test/ui/lub-if.stderr | 1 + src/test/ui/lub-match.stderr | 1 + .../macros/auxiliary/proc_macro_sequence.rs | 20 +- .../macro-backtrace-invalid-internals.stderr | 4 +- .../ui/macros/macro-expansion-tests.stderr | 4 +- src/test/ui/macros/macro-in-fn.rs | 8 + src/test/ui/macros/macro-name-typo.stderr | 2 +- .../ui/macros/macro-path-prelude-fail-3.rs | 2 +- .../macros/macro-path-prelude-fail-3.stderr | 2 +- src/test/ui/macros/macro-reexport-removed.rs | 2 +- .../ui/macros/macro-reexport-removed.stderr | 2 +- .../ui/macros/macro-use-wrong-name.stderr | 2 +- src/test/ui/macros/macro_undefined.stderr | 2 +- .../ui/macros/restricted-shadowing-modern.rs | 2 - .../macros/restricted-shadowing-modern.stderr | 18 +- src/test/ui/macros/same-sequence-span.stderr | 16 +- src/test/ui/macros/trace-macro.stderr | 2 +- src/test/ui/main-wrong-location.rs | 1 + src/test/ui/main-wrong-location.stderr | 16 +- .../ui/malformed/malformed-regressions.stderr | 6 +- .../overlap-marker-trait.stderr | 13 +- .../match-no-arms-unreachable-after.stderr | 4 +- .../match/match-pattern-field-mismatch.stderr | 3 + src/test/ui/match/match-ref-mut-stability.rs | 2 - .../ui/match/match-unresolved-one-arm.stderr | 5 +- src/test/ui/match/match-vec-mismatch.stderr | 2 +- .../ui/match/non-exhaustive-defined-here.rs | 72 + .../match/non-exhaustive-defined-here.stderr | 170 + .../ui/methods/method-call-err-msg.stderr | 2 +- src/test/ui/methods/method-projection.rs | 9 - src/test/ui/mismatched_types/E0631.stderr | 44 +- .../mismatched_types/closure-arg-count.stderr | 46 +- .../closure-arg-type-mismatch.stderr | 28 +- .../mismatched_types/closure-mismatch.stderr | 16 +- .../ui/mismatched_types/fn-variance-1.stderr | 26 +- .../ui/mismatched_types/issue-35030.stderr | 2 + .../ui/mismatched_types/issue-36053-2.stderr | 2 +- .../method-help-unsatisfied-bound.stderr | 2 +- .../unboxed-closures-vtable-mismatch.rs | 3 +- .../unboxed-closures-vtable-mismatch.stderr | 13 +- src/test/ui/missing/missing-macro-use.rs | 2 +- src/test/ui/missing/missing-macro-use.stderr | 2 +- src/test/ui/missing/missing-main.stderr | 4 +- .../missing/missing-semicolon-warning.stderr | 4 +- src/test/ui/moves/move-into-dead-array-1.rs | 2 +- .../ui/moves/move-into-dead-array-1.stderr | 4 +- src/test/ui/mut/mutable-enum-indirect.stderr | 8 +- src/test/ui/mutexguard-sync.stderr | 12 +- src/test/ui/namespace/namespace-mix.stderr | 572 +- src/test/ui/never-assign-dead-code.stderr | 11 +- ...ue-21232-partial-init-and-erroneous-use.rs | 8 +- ...1232-partial-init-and-erroneous-use.stderr | 16 +- .../nll/issue-21232-partial-init-and-use.rs | 24 +- .../issue-21232-partial-init-and-use.stderr | 48 +- src/test/ui/nll/issue-52742.stderr | 1 + src/test/ui/nll/issue-55288.rs | 2 +- src/test/ui/nll/issue-55401.stderr | 1 + src/test/ui/nll/issue-57960.rs | 1 - src/test/ui/nll/match-cfg-fake-edges.rs | 4 +- src/test/ui/nll/match-cfg-fake-edges.stderr | 8 +- .../ui/nll/match-guards-partially-borrow.rs | 2 - .../nll/match-guards-partially-borrow.stderr | 18 +- src/test/ui/nll/match-on-borrowed.stderr | 4 +- src/test/ui/nll/normalization-bounds.rs | 2 +- .../promotable-mutable-zst-doesnt-conflict.rs | 4 +- src/test/ui/nll/self-assign-ref-mut.rs | 20 + .../constant-in-expr-normalize.stderr | 1 + .../constant-in-expr-trait-item-1.stderr | 1 + .../constant-in-expr-trait-item-2.stderr | 1 + .../ui/nll/user-annotations/issue-55219.rs | 2 +- .../nll/user-annotations/normalize-self-ty.rs | 4 +- src/test/ui/no-send-res-ports.rs | 2 + src/test/ui/no-send-res-ports.stderr | 12 +- src/test/ui/no_send-enum.stderr | 8 +- src/test/ui/no_send-rc.stderr | 12 +- src/test/ui/no_send-struct.stderr | 12 +- src/test/ui/no_share-enum.stderr | 8 +- src/test/ui/no_share-struct.stderr | 12 +- src/test/ui/non-copyable-void.stderr | 2 +- ...terger-atomic.rs => non-integer-atomic.rs} | 0 ...tomic.stderr => non-integer-atomic.stderr} | 32 +- src/test/ui/noncopyable-class.stderr | 2 +- src/test/ui/not-panic/not-panic-safe-2.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-3.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-4.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-5.stderr | 8 +- src/test/ui/not-panic/not-panic-safe-6.stderr | 16 +- src/test/ui/not-panic/not-panic-safe.stderr | 8 +- src/test/ui/not-sync.stderr | 72 +- src/test/ui/object-does-not-impl-trait.stderr | 12 +- ...lifetime-default-dyn-binding-nonstatic1.rs | 27 + ...time-default-dyn-binding-nonstatic1.stderr | 8 + ...lifetime-default-dyn-binding-nonstatic2.rs | 30 + ...time-default-dyn-binding-nonstatic2.stderr | 8 + ...lifetime-default-dyn-binding-nonstatic3.rs | 23 + ...time-default-dyn-binding-nonstatic3.stderr | 8 + ...ect-lifetime-default-dyn-binding-static.rs | 28 + src/test/ui/object-pointer-types.stderr | 6 +- .../object-safety-associated-consts.stderr | 5 +- .../object-safety-generics.stderr | 10 +- .../object-safety-mentions-Self.stderr | 10 +- .../object-safety-no-static.stderr | 5 +- src/test/ui/obsolete-in-place/bad.rs | 2 +- src/test/ui/obsolete-in-place/bad.stderr | 8 +- .../ui/on-unimplemented/multiple-impls.stderr | 58 +- src/test/ui/on-unimplemented/on-impl.stderr | 14 +- src/test/ui/on-unimplemented/on-trait.stderr | 16 +- src/test/ui/or-patterns/already-bound-name.rs | 46 + .../ui/or-patterns/already-bound-name.stderr | 105 + .../ui/or-patterns/consistent-bindings.rs | 46 + .../ui/or-patterns/consistent-bindings.stderr | 20 + .../feature-gate-or_patterns-leading-for.rs | 8 + ...eature-gate-or_patterns-leading-for.stderr | 12 + .../feature-gate-or_patterns-leading-let.rs | 8 + ...eature-gate-or_patterns-leading-let.stderr | 12 + .../or-patterns/feature-gate-or_patterns.rs | 52 + .../feature-gate-or_patterns.stderr | 174 + .../ui/or-patterns/fn-param-wrap-parens.fixed | 14 + .../ui/or-patterns/fn-param-wrap-parens.rs | 14 + .../or-patterns/fn-param-wrap-parens.stderr | 8 + src/test/ui/or-patterns/inconsistent-modes.rs | 28 + .../ui/or-patterns/inconsistent-modes.stderr | 80 + src/test/ui/or-patterns/missing-bindings.rs | 84 + .../ui/or-patterns/missing-bindings.stderr | 250 + .../ui/or-patterns/multiple-pattern-typo.rs | 45 + .../or-patterns/multiple-pattern-typo.stderr | 52 + .../{ => or-patterns}/or-pattern-mismatch.rs | 0 .../or-pattern-mismatch.stderr | 0 .../or-patterns/or-patterns-syntactic-fail.rs | 53 + .../or-patterns-syntactic-fail.stderr | 124 + .../or-patterns/or-patterns-syntactic-pass.rs | 78 + .../or-patterns-syntactic-pass.stderr | 8 + .../ui/or-patterns/remove-leading-vert.fixed | 23 + .../ui/or-patterns/remove-leading-vert.rs | 23 + .../ui/or-patterns/remove-leading-vert.stderr | 68 + .../while-parsing-this-or-pattern.rs | 9 + .../while-parsing-this-or-pattern.stderr | 10 + src/test/ui/overlap-marker-trait.stderr | 13 +- src/test/ui/parser-recovery-1.rs | 1 + src/test/ui/parser-recovery-1.stderr | 19 +- src/test/ui/parser/assoc-type-in-type-arg.rs | 11 + .../ui/parser/assoc-type-in-type-arg.stderr | 8 + src/test/ui/parser/bad-match.rs | 2 +- src/test/ui/parser/bad-match.stderr | 4 +- src/test/ui/parser/bad-name.stderr | 4 +- src/test/ui/parser/do-catch-suggests-try.rs | 2 +- .../ui/parser/do-catch-suggests-try.stderr | 2 +- src/test/ui/parser/doc-before-semi.rs | 2 + src/test/ui/parser/doc-before-semi.stderr | 8 + src/test/ui/parser/fn-arg-doc-comment.rs | 4 - src/test/ui/parser/fn-arg-doc-comment.stderr | 33 +- src/test/ui/parser/inverted-parameters.rs | 12 +- src/test/ui/parser/inverted-parameters.stderr | 24 +- src/test/ui/parser/issue-22647.rs | 2 +- src/test/ui/parser/issue-22647.stderr | 4 +- src/test/ui/parser/issue-22712.rs | 2 +- src/test/ui/parser/issue-22712.stderr | 4 +- src/test/ui/parser/issue-2354.rs | 5 +- src/test/ui/parser/issue-2354.stderr | 20 +- src/test/ui/parser/issue-24197.rs | 2 +- src/test/ui/parser/issue-24197.stderr | 4 +- src/test/ui/parser/issue-32501.rs | 3 +- src/test/ui/parser/issue-32501.stderr | 8 +- src/test/ui/parser/issue-33413.rs | 2 +- src/test/ui/parser/issue-33413.stderr | 4 +- src/test/ui/parser/issue-63135.rs | 2 +- src/test/ui/parser/issue-63135.stderr | 12 +- .../issue-65122-mac-invoc-in-mut-patterns.rs | 26 + ...sue-65122-mac-invoc-in-mut-patterns.stderr | 45 + src/test/ui/parser/keyword-abstract.rs | 2 +- src/test/ui/parser/keyword-abstract.stderr | 8 +- .../ui/parser/keyword-as-as-identifier.rs | 2 +- .../ui/parser/keyword-as-as-identifier.stderr | 8 +- .../ui/parser/keyword-break-as-identifier.rs | 2 +- .../parser/keyword-break-as-identifier.stderr | 8 +- .../ui/parser/keyword-const-as-identifier.rs | 2 +- .../parser/keyword-const-as-identifier.stderr | 8 +- .../parser/keyword-continue-as-identifier.rs | 2 +- .../keyword-continue-as-identifier.stderr | 8 +- .../ui/parser/keyword-else-as-identifier.rs | 2 +- .../parser/keyword-else-as-identifier.stderr | 8 +- .../ui/parser/keyword-enum-as-identifier.rs | 2 +- .../parser/keyword-enum-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-final.rs | 2 +- src/test/ui/parser/keyword-final.stderr | 8 +- .../ui/parser/keyword-fn-as-identifier.rs | 2 +- .../ui/parser/keyword-fn-as-identifier.stderr | 8 +- .../ui/parser/keyword-for-as-identifier.rs | 2 +- .../parser/keyword-for-as-identifier.stderr | 8 +- .../ui/parser/keyword-if-as-identifier.rs | 2 +- .../ui/parser/keyword-if-as-identifier.stderr | 8 +- .../ui/parser/keyword-impl-as-identifier.rs | 2 +- .../parser/keyword-impl-as-identifier.stderr | 8 +- .../ui/parser/keyword-let-as-identifier.rs | 2 +- .../parser/keyword-let-as-identifier.stderr | 8 +- .../ui/parser/keyword-loop-as-identifier.rs | 2 +- .../parser/keyword-loop-as-identifier.stderr | 8 +- .../ui/parser/keyword-match-as-identifier.rs | 2 +- .../parser/keyword-match-as-identifier.stderr | 8 +- .../ui/parser/keyword-mod-as-identifier.rs | 2 +- .../parser/keyword-mod-as-identifier.stderr | 8 +- .../ui/parser/keyword-move-as-identifier.rs | 2 +- .../parser/keyword-move-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-override.rs | 2 +- src/test/ui/parser/keyword-override.stderr | 8 +- .../ui/parser/keyword-pub-as-identifier.rs | 2 +- .../parser/keyword-pub-as-identifier.stderr | 8 +- .../ui/parser/keyword-return-as-identifier.rs | 2 +- .../keyword-return-as-identifier.stderr | 8 +- .../ui/parser/keyword-static-as-identifier.rs | 2 +- .../keyword-static-as-identifier.stderr | 8 +- .../ui/parser/keyword-struct-as-identifier.rs | 2 +- .../keyword-struct-as-identifier.stderr | 8 +- .../ui/parser/keyword-trait-as-identifier.rs | 2 +- .../parser/keyword-trait-as-identifier.stderr | 8 +- .../keyword-try-as-identifier-edition2018.rs | 2 +- ...yword-try-as-identifier-edition2018.stderr | 8 +- .../ui/parser/keyword-type-as-identifier.rs | 2 +- .../parser/keyword-type-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-typeof.rs | 2 +- src/test/ui/parser/keyword-typeof.stderr | 8 +- .../ui/parser/keyword-unsafe-as-identifier.rs | 2 +- .../keyword-unsafe-as-identifier.stderr | 8 +- .../ui/parser/keyword-use-as-identifier.rs | 2 +- .../parser/keyword-use-as-identifier.stderr | 8 +- .../ui/parser/keyword-where-as-identifier.rs | 2 +- .../parser/keyword-where-as-identifier.stderr | 8 +- .../ui/parser/keyword-while-as-identifier.rs | 2 +- .../parser/keyword-while-as-identifier.stderr | 8 +- src/test/ui/parser/lex-bad-char-literals-2.rs | 2 + .../ui/parser/lex-bad-char-literals-2.stderr | 7 +- src/test/ui/parser/mut-patterns.rs | 42 +- src/test/ui/parser/mut-patterns.stderr | 101 +- src/test/ui/parser/omitted-arg-in-item-fn.rs | 2 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 4 +- src/test/ui/parser/pat-lt-bracket-2.rs | 2 +- src/test/ui/parser/pat-lt-bracket-2.stderr | 4 +- src/test/ui/parser/pat-lt-bracket-5.rs | 2 +- src/test/ui/parser/pat-lt-bracket-5.stderr | 4 +- src/test/ui/parser/pat-lt-bracket-6.rs | 5 +- src/test/ui/parser/pat-lt-bracket-6.stderr | 6 +- src/test/ui/parser/pat-lt-bracket-7.rs | 3 +- src/test/ui/parser/pat-lt-bracket-7.stderr | 6 +- src/test/ui/parser/pat-ranges-1.rs | 2 +- src/test/ui/parser/pat-ranges-1.stderr | 4 +- src/test/ui/parser/pat-ranges-2.rs | 2 +- src/test/ui/parser/pat-ranges-2.stderr | 4 +- src/test/ui/parser/pat-ranges-3.rs | 2 +- src/test/ui/parser/pat-ranges-3.stderr | 4 +- src/test/ui/parser/pat-ranges-4.rs | 2 +- src/test/ui/parser/pat-ranges-4.stderr | 4 +- .../recover-for-loop-parens-around-head.rs | 2 +- ...recover-for-loop-parens-around-head.stderr | 4 +- src/test/ui/parser/removed-syntax-mode.rs | 2 +- src/test/ui/parser/removed-syntax-mode.stderr | 4 +- .../require-parens-for-chained-comparison.rs | 3 +- ...quire-parens-for-chained-comparison.stderr | 15 +- .../ui/parser/trait-object-lifetime-parens.rs | 1 - .../trait-object-lifetime-parens.stderr | 11 +- .../type-parameters-in-field-exprs.stderr | 4 +- .../parser/unclosed-delimiter-in-dep.stderr | 2 +- src/test/ui/parser/unclosed_delim_mod.rs | 2 + src/test/ui/parser/unclosed_delim_mod.stderr | 9 +- .../ui/pattern/pat-tuple-overfield.stderr | 6 + .../ui/pattern/pattern-error-continue.stderr | 3 + src/test/ui/phantom-oibit.stderr | 24 +- src/test/ui/placement-syntax.rs | 2 +- src/test/ui/placement-syntax.stderr | 10 +- ...-to-type-err-cause-on-impl-trait-return.rs | 31 +- ...type-err-cause-on-impl-trait-return.stderr | 68 +- src/test/ui/privacy/union-field-privacy-2.rs | 2 +- .../ui/privacy/union-field-privacy-2.stderr | 2 +- .../proc-macro/attributes-on-definitions.rs | 12 + .../attributes-on-definitions.stderr | 8 + .../auxiliary/attributes-on-definitions.rs | 23 + .../proc-macro/auxiliary/gen-macro-rules.rs | 12 + .../ui/proc-macro/derive-helper-configured.rs | 18 + .../ui/proc-macro/derive-helper-shadowing.rs | 3 +- .../proc-macro/derive-helper-shadowing.stderr | 8 +- src/test/ui/proc-macro/derive-still-gated.rs | 2 +- .../ui/proc-macro/derive-still-gated.stderr | 2 +- .../dollar-crate-issue-57089.stdout | 32 +- .../dollar-crate-issue-62325.stdout | 44 +- src/test/ui/proc-macro/dollar-crate.stdout | 96 +- src/test/ui/proc-macro/gen-macro-rules.rs | 13 + src/test/ui/proc-macro/generate-mod.stderr | 10 +- .../ui/proc-macro/invalid-punct-ident-1.rs | 5 + .../proc-macro/invalid-punct-ident-1.stderr | 2 +- .../ui/proc-macro/invalid-punct-ident-2.rs | 5 + .../proc-macro/invalid-punct-ident-2.stderr | 2 +- .../ui/proc-macro/invalid-punct-ident-3.rs | 5 + .../proc-macro/invalid-punct-ident-3.stderr | 2 +- .../proc-macro/invalid-punct-ident-4.stderr | 5 +- .../ui/proc-macro/lints_in_proc_macros.stderr | 5 +- .../proc-macro/macro-namespace-reserved-2.rs | 6 +- .../macro-namespace-reserved-2.stderr | 26 +- src/test/ui/proc-macro/multispan.stderr | 133 +- .../ui/proc-macro/proc-macro-attributes.rs | 2 +- .../proc-macro/proc-macro-attributes.stderr | 2 +- src/test/ui/proc-macro/proc-macro-gates2.rs | 4 +- .../ui/proc-macro/proc-macro-gates2.stderr | 11 +- src/test/ui/proc-macro/resolve-error.rs | 8 +- src/test/ui/proc-macro/resolve-error.stderr | 76 +- src/test/ui/proc-macro/span-preservation.rs | 2 +- .../ui/proc-macro/span-preservation.stderr | 2 +- src/test/ui/proc-macro/subspan.stderr | 16 +- src/test/ui/proc-macro/three-equals.stderr | 19 +- src/test/ui/reachable/expr_add.stderr | 5 +- src/test/ui/reachable/expr_again.stderr | 4 +- src/test/ui/reachable/expr_array.stderr | 9 +- src/test/ui/reachable/expr_assign.stderr | 13 +- src/test/ui/reachable/expr_block.stderr | 8 +- src/test/ui/reachable/expr_box.stderr | 5 +- src/test/ui/reachable/expr_call.stderr | 10 +- src/test/ui/reachable/expr_cast.stderr | 5 +- src/test/ui/reachable/expr_if.stderr | 11 +- src/test/ui/reachable/expr_loop.stderr | 12 +- src/test/ui/reachable/expr_match.stderr | 8 +- src/test/ui/reachable/expr_method.stderr | 12 +- src/test/ui/reachable/expr_repeat.stderr | 5 +- src/test/ui/reachable/expr_return.stderr | 5 +- src/test/ui/reachable/expr_return_in_macro.rs | 15 + .../ui/reachable/expr_return_in_macro.stderr | 17 + src/test/ui/reachable/expr_struct.stderr | 18 +- src/test/ui/reachable/expr_tup.stderr | 9 +- src/test/ui/reachable/expr_type.stderr | 5 +- src/test/ui/reachable/expr_unary.stderr | 5 +- src/test/ui/reachable/expr_while.stderr | 12 +- .../recursion/recursive-requirements.stderr | 16 +- .../recursive-types-are-not-uninhabited.rs | 2 +- ...recursive-types-are-not-uninhabited.stderr | 4 +- src/test/ui/refutable-pattern-errors.rs | 4 +- src/test/ui/refutable-pattern-errors.stderr | 8 +- ...rait-outlives-container.migrate.nll.stderr | 2 +- ...pertrait-outlives-container.migrate.stderr | 10 +- ...n-supertrait-outlives-container.nll.stderr | 2 +- ...c-type-in-supertrait-outlives-container.rs | 4 - .../regions-close-object-into-object-5.stderr | 12 +- .../regions-early-bound-error-method.stderr | 1 + .../regions/regions-early-bound-error.stderr | 1 + .../ui/regions/regions-name-undeclared.stderr | 8 +- src/test/ui/regions/regions-nested-fns.stderr | 1 + ...ojection-container-hrtb.migrate.nll.stderr | 4 +- ...s-projection-container-hrtb.migrate.stderr | 20 +- ...lives-projection-container-hrtb.nll.stderr | 4 +- ...ions-outlives-projection-container-hrtb.rs | 7 - ...projection-container-wc.migrate.nll.stderr | 2 +- ...ves-projection-container-wc.migrate.stderr | 10 +- ...utlives-projection-container-wc.nll.stderr | 2 +- ...egions-outlives-projection-container-wc.rs | 4 - ...s-outlives-projection-container.nll.stderr | 8 +- .../regions-outlives-projection-container.rs | 4 - ...gions-outlives-projection-container.stderr | 40 +- .../regions-static-bound.migrate.stderr | 3 +- src/test/ui/reify-intrinsic.rs | 15 + src/test/ui/reify-intrinsic.stderr | 22 + .../ui/reserved/reserved-attr-on-macro.rs | 2 +- .../ui/reserved/reserved-attr-on-macro.stderr | 12 +- src/test/ui/reserved/reserved-become.rs | 2 +- src/test/ui/reserved/reserved-become.stderr | 8 +- .../ui/resolve/block-with-trait-parent.rs | 14 + src/test/ui/resolve/issue-3907-2.stderr | 2 +- .../ui/resolve/visibility-indeterminate.rs | 4 +- .../resolve/visibility-indeterminate.stderr | 9 +- .../bind-by-move-no-guards.rs | 6 +- .../feature-gate.gate_and_2015.stderr | 10 - .../feature-gate.gate_and_2018.stderr | 10 - .../feature-gate.gate_and_feature_nll.stderr | 10 - .../feature-gate.gate_and_znll.stderr | 10 - .../feature-gate.no_gate.stderr | 11 - .../feature-gate.rs | 40 - .../former-E0008-now-pass.rs | 11 + .../rfc-basic-examples.rs | 2 - .../rfc-reject-double-move-across-arms.rs | 2 - .../rfc-reject-double-move-across-arms.stderr | 2 +- .../rfc-reject-double-move-in-first-arm.rs | 2 - ...rfc-reject-double-move-in-first-arm.stderr | 2 +- .../termination-trait-test-wrong-type.rs | 2 + .../termination-trait-test-wrong-type.stderr | 8 +- .../variants_same_crate.rs | 6 +- .../dbg-macro-expected-behavior.rs | 84 +- .../dbg-macro-expected-behavior.run.stderr | 28 + .../protect-precedences.rs | 2 - .../protect-precedences.stderr | 10 + .../attr-without-param.rs | 16 + .../attr-without-param.stderr | 20 + .../auxiliary/ident-mac.rs | 11 + .../auxiliary/param-attrs.rs | 12 +- ...-64682-dropping-first-attrs-in-impl-fns.rs | 21 + .../rfc-2565-param-attrs/param-attrs-2018.rs | 4 +- .../param-attrs-2018.stderr | 6 +- .../param-attrs-allowed.rs | 1 - .../param-attrs-builtin-attrs.rs | 49 +- .../param-attrs-builtin-attrs.stderr | 261 +- .../rfc-2565-param-attrs/param-attrs-cfg.rs | 26 +- .../param-attrs-cfg.stderr | 52 +- .../param-attrs-feature-gate.rs | 16 - .../param-attrs-feature-gate.stderr | 27 - .../param-attrs-pretty.rs | 7 +- .../proc-macro-cannot-be-used.rs | 65 + .../proc-macro-cannot-be-used.stderr | 176 + .../shadowing.rs | 16 +- .../shadowing.stderr | 21 +- .../rust-2018/trait-import-suggestions.stderr | 6 +- .../ui/rust-2018/uniform-paths/deadlock.rs | 2 +- .../rust-2018/uniform-paths/deadlock.stderr | 6 +- src/test/ui/rust-unstable-column-gated.rs | 4 - src/test/ui/rust-unstable-column-gated.stderr | 11 - src/test/ui/save-analysis/issue-63663.rs | 28 + src/test/ui/save-analysis/issue-64659.rs | 10 + src/test/ui/save-analysis/issue-65411.rs | 15 + src/test/ui/save-analysis/issue-65590.rs | 21 + ...rbitrary-self-types-not-object-safe.stderr | 9 +- ...arbitrary_self_types_pin_lifetime-async.rs | 35 + ...s_pin_lifetime_impl_trait-async.nll.stderr | 14 + ...elf_types_pin_lifetime_impl_trait-async.rs | 14 + ...types_pin_lifetime_impl_trait-async.stderr | 20 + ...pes_pin_lifetime_mismatch-async.nll.stderr | 46 + ..._self_types_pin_lifetime_mismatch-async.rs | 20 + ...f_types_pin_lifetime_mismatch-async.stderr | 29 + src/test/ui/self/elision/README.md | 31 + src/test/ui/self/elision/alias-async.rs | 37 + src/test/ui/self/elision/assoc-async.rs | 41 + src/test/ui/self/elision/lt-alias-async.rs | 39 + src/test/ui/self/elision/lt-assoc-async.rs | 51 + .../self/elision/lt-ref-self-async.nll.stderr | 123 + src/test/ui/self/elision/lt-ref-self-async.rs | 40 + .../ui/self/elision/lt-ref-self-async.stderr | 56 + src/test/ui/self/elision/lt-self-async.rs | 50 + src/test/ui/self/elision/lt-struct-async.rs | 37 + .../self/elision/multiple-ref-self-async.rs | 44 + src/test/ui/self/elision/ref-alias-async.rs | 40 + src/test/ui/self/elision/ref-assoc-async.rs | 41 + .../ui/self/elision/ref-mut-alias-async.rs | 37 + .../elision/ref-mut-self-async.nll.stderr | 123 + .../ui/self/elision/ref-mut-self-async.rs | 40 + .../ui/self/elision/ref-mut-self-async.stderr | 56 + .../elision/ref-mut-struct-async.nll.stderr | 103 + .../ui/self/elision/ref-mut-struct-async.rs | 34 + .../self/elision/ref-mut-struct-async.stderr | 47 + .../ui/self/elision/ref-self-async.nll.stderr | 143 + src/test/ui/self/elision/ref-self-async.rs | 53 + .../ui/self/elision/ref-self-async.stderr | 65 + .../self/elision/ref-struct-async.nll.stderr | 103 + src/test/ui/self/elision/ref-struct-async.rs | 34 + .../ui/self/elision/ref-struct-async.stderr | 47 + src/test/ui/self/elision/self-async.rs | 37 + src/test/ui/self/elision/struct-async.rs | 33 + .../point-at-arbitrary-self-type-method.rs | 9 + ...point-at-arbitrary-self-type-method.stderr | 15 + ...int-at-arbitrary-self-type-trait-method.rs | 10 + ...at-arbitrary-self-type-trait-method.stderr | 18 + src/test/ui/self/self_lifetime-async.rs | 14 + src/test/ui/self/self_type_keyword.rs | 5 +- src/test/ui/self/self_type_keyword.stderr | 34 +- .../ui/shadowed/shadowed-trait-methods.stderr | 2 +- .../ui/shadowed/shadowed-type-parameter.rs | 6 +- .../shadowed/shadowed-type-parameter.stderr | 30 +- .../shadowing-in-the-same-pattern.stderr | 7 +- src/test/ui/span/issue-27522.rs | 2 +- src/test/ui/span/issue-27522.stderr | 5 +- src/test/ui/span/issue-29595.stderr | 9 +- src/test/ui/span/issue-34264.stderr | 12 +- .../issue-42234-unknown-receiver-type.stderr | 4 +- .../ui/span/type-annotations-needed-expr.rs | 3 + .../span/type-annotations-needed-expr.stderr | 11 + .../defaultimpl/specialization-no-default.rs | 8 - .../specialization-no-default.stderr | 10 +- ...pecialization-trait-not-implemented.stderr | 2 +- src/test/ui/specialization/issue-52050.stderr | 2 +- .../specialization/issue-63716-parse-async.rs | 14 + .../specialization-default-projection.stderr | 4 + .../specialization-default-types.stderr | 4 + .../specialization-no-default.rs | 8 - .../specialization-no-default.stderr | 10 +- src/test/ui/std-backtrace.rs | 75 + src/test/ui/str/str-idx.stderr | 8 +- src/test/ui/str/str-mut-idx.stderr | 16 +- .../structs/struct-path-alias-bounds.stderr | 9 +- .../struct-path-self-type-mismatch.stderr | 4 + src/test/ui/structs/struct-path-self.rs | 6 +- src/test/ui/structs/struct-path-self.stderr | 6 +- src/test/ui/substs-ppaux.normal.stderr | 8 +- src/test/ui/substs-ppaux.verbose.stderr | 8 +- ...as-arg-where-it-should-have-been-called.rs | 10 + ...rg-where-it-should-have-been-called.stderr | 15 + src/test/ui/suggestions/attribute-typos.rs | 6 +- .../ui/suggestions/attribute-typos.stderr | 6 +- .../dont-suggest-ref/duplicate-suggestions.rs | 2 +- .../dont-suggest-ref/move-into-closure.rs | 4 +- .../ui/suggestions/dont-suggest-ref/simple.rs | 8 +- .../dont-suggest-try_into-in-macros.rs | 3 + .../dont-suggest-try_into-in-macros.stderr | 11 + ...as-arg-where-it-should-have-been-called.rs | 18 + ...rg-where-it-should-have-been-called.stderr | 15 + .../fn-or-tuple-struct-without-args.rs | 2 + .../fn-or-tuple-struct-without-args.stderr | 16 +- ...ait-with-missing-trait-bounds-in-arg.fixed | 20 + ...-trait-with-missing-trait-bounds-in-arg.rs | 20 + ...it-with-missing-trait-bounds-in-arg.stderr | 15 + src/test/ui/suggestions/into-str.stderr | 8 +- src/test/ui/suggestions/issue-21673.stderr | 4 +- src/test/ui/suggestions/issue-62843.stderr | 4 +- .../mismatched-types-numeric-from.rs | 3 + .../mismatched-types-numeric-from.stderr | 9 + src/test/ui/suggestions/opaque-type-error.rs | 24 + .../ui/suggestions/opaque-type-error.stderr | 20 + src/test/ui/suggestions/suggest-box.fixed | 8 + src/test/ui/suggestions/suggest-box.rs | 8 + src/test/ui/suggestions/suggest-box.stderr | 24 + .../suggest-closure-return-type-1.rs | 3 + .../suggest-closure-return-type-1.stderr | 13 + .../suggest-closure-return-type-2.rs | 3 + .../suggest-closure-return-type-2.stderr | 13 + .../suggest-closure-return-type-3.rs | 3 + .../suggest-closure-return-type-3.stderr | 13 + .../ui/suggestions/suggest-methods.stderr | 2 +- src/test/ui/symbol-names/impl1.rs | 6 +- src/test/ui/symbol-names/impl1.v0.stderr | 6 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- src/test/ui/symbol-names/issue-60925.rs | 4 +- src/test/ui/syntax-extension-minor.rs | 6 +- src/test/ui/syntax-extension-minor.stderr | 9 - .../non-whitespace-trimming-2.rs | 6 + .../non-whitespace-trimming-2.stderr | 12 + .../non-whitespace-trimming-unicode.rs | 6 + .../non-whitespace-trimming-unicode.stderr | 12 + .../terminal-width/non-whitespace-trimming.rs | 6 + .../non-whitespace-trimming.stderr | 12 + .../terminal-width/whitespace-trimming-2.rs | 8 + .../whitespace-trimming-2.stderr | 14 + .../ui/terminal-width/whitespace-trimming.rs | 6 + .../terminal-width/whitespace-trimming.stderr | 12 + .../auxiliary/test_macro.rs | 0 src/test/ui/test-attrs/decl-macro-test.rs | 22 + .../inaccessible-test-modules.rs | 4 +- .../inaccessible-test-modules.stderr | 21 + .../{ => test-attrs}/test-allow-fail-attr.rs | 0 .../test-attr-non-associated-functions.rs | 0 .../test-attr-non-associated-functions.stderr | 0 .../test-cant-be-shadowed.rs | 0 ...e-verification-for-explicit-return-type.rs | 0 .../test-main-not-dead-attr.rs | 0 .../ui/{ => test-attrs}/test-main-not-dead.rs | 0 src/test/ui/{ => test-attrs}/test-on-macro.rs | 0 .../ui/{ => test-attrs}/test-on-macro.stderr | 0 .../test-runner-hides-buried-main.rs | 0 .../test-runner-hides-main.rs | 0 .../test-runner-hides-start.rs | 0 .../test-should-fail-good-message.rs | 0 .../test-should-panic-attr.rs | 0 .../test-should-panic-attr.stderr | 0 .../ui/{ => test-attrs}/test-vs-cfg-test.rs | 0 .../{ => test-attrs}/test-warns-dead-code.rs | 0 .../test-warns-dead-code.stderr | 0 .../ui/tool-attributes/diagnostic_item.rs | 3 + .../ui/tool-attributes/diagnostic_item.stderr | 12 + .../ui/tool-attributes/diagnostic_item2.rs | 6 + .../ui/tool-attributes/diagnostic_item3.rs | 7 + .../tool-attributes-misplaced-1.rs | 6 +- .../tool-attributes-misplaced-1.stderr | 4 +- .../trait-alias-cross-crate.stderr | 24 +- .../trait-alias/trait-alias-object-wf.rs | 2 +- .../traits/trait-alias/trait-alias-wf.stderr | 7 +- ...-bounds-on-structs-and-enums-in-fns.stderr | 18 +- ...ounds-on-structs-and-enums-in-impls.stderr | 9 +- ...-bounds-on-structs-and-enums-locals.stderr | 18 +- ...-bounds-on-structs-and-enums-static.stderr | 9 +- .../trait-bounds-on-structs-and-enums.stderr | 60 +- src/test/ui/traits/trait-impl-1.stderr | 2 +- src/test/ui/traits/trait-item-privacy.stderr | 24 +- src/test/ui/traits/trait-object-safety.stderr | 9 +- ...ait-static-method-generic-inference.stderr | 9 +- .../ui/traits/trait-suggest-where-clause.rs | 2 + .../traits/trait-suggest-where-clause.stderr | 42 +- src/test/ui/traits/trait-test-2.stderr | 15 +- .../ui/traits/traits-conditional-model-fn.rs | 7 - ...its-inductive-overflow-simultaneous.stderr | 8 +- ...inductive-overflow-supertrait-oibit.stderr | 12 +- ...raits-inductive-overflow-supertrait.stderr | 8 +- ...raits-inductive-overflow-two-traits.stderr | 9 +- .../ui/traits/traits-negative-impls.stderr | 80 +- .../traits-repeated-supertrait-ambig.stderr | 17 +- .../trivial-bounds/trivial-bounds-leak.stderr | 26 +- src/test/ui/try-block/try-block-opt-init.rs | 2 +- .../ui/try-block/try-block-opt-init.stderr | 4 +- src/test/ui/try-operator-on-main.rs | 2 +- src/test/ui/try-operator-on-main.stderr | 11 +- .../enum-variant-generic-args-pass.rs | 16 +- .../enum-variant-generic-args.stderr | 12 + .../ui/type-alias-impl-trait/issue-60564.rs | 2 + .../type-alias-impl-trait/issue-60564.stderr | 7 +- src/test/ui/type/ascription/issue-34255-1.rs | 1 + .../ui/type/ascription/issue-34255-1.stderr | 12 +- src/test/ui/type/ascription/issue-54516.rs | 2 +- .../ui/type/ascription/issue-54516.stderr | 4 +- src/test/ui/type/type-annotation-needed.rs | 1 + .../ui/type/type-annotation-needed.stderr | 11 +- src/test/ui/type/type-check-defaults.stderr | 73 +- .../ui/type/type-check/issue-40294.stderr | 9 +- ...ter-defaults-referencing-Self-ppaux.stderr | 5 +- src/test/ui/type/type-parameter-names.stderr | 2 + .../type/type-params-in-different-spaces-1.rs | 2 +- .../type-params-in-different-spaces-1.stderr | 4 +- .../type-params-in-different-spaces-2.stderr | 16 +- .../type-params-in-different-spaces-3.stderr | 4 +- ...ypeck-default-trait-impl-assoc-type.stderr | 8 +- ...ault-trait-impl-constituent-types-2.stderr | 8 +- ...efault-trait-impl-constituent-types.stderr | 12 +- ...ck-default-trait-impl-negation-send.stderr | 12 +- ...ck-default-trait-impl-negation-sync.stderr | 28 +- .../typeck-default-trait-impl-negation.stderr | 24 +- ...ypeck-default-trait-impl-precedence.stderr | 8 +- ...ypeck-default-trait-impl-send-param.stderr | 12 +- .../typeck/typeck-unsafe-always-share.stderr | 44 +- src/test/ui/ufcs/ufcs-explicit-self-bad.rs | 14 +- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 23 +- .../unboxed-closure-sugar-default.stderr | 9 +- .../unboxed-closure-sugar-equiv.stderr | 9 +- ...oxed-closure-sugar-used-on-struct-1.stderr | 4 +- ...oxed-closure-sugar-used-on-struct-3.stderr | 10 +- ...nboxed-closure-sugar-used-on-struct.stderr | 4 +- ...ong-number-number-type-parameters-1.stderr | 4 +- ...ong-number-number-type-parameters-3.stderr | 4 +- ...wrong-number-number-type-parameters.stderr | 8 +- .../unboxed-closure-sugar-wrong-trait.stderr | 4 +- .../unboxed-closures-fnmut-as-fn.stderr | 12 +- ...-argument-types-two-region-pointers.stderr | 1 + ...ed-closures-static-call-wrong-trait.stderr | 2 +- .../unboxed-closures-unsafe-extern-fn.stderr | 60 +- .../unboxed-closures-wrong-abi.stderr | 60 +- ...d-closures-wrong-arg-type-extern-fn.stderr | 60 +- .../auxiliary/duplicate.rs | 0 .../auxiliary/underscore-imports.rs | 0 .../basic.rs | 0 .../basic.stderr | 0 src/test/ui/underscore-imports/cycle.rs | 18 + .../duplicate.rs | 0 .../intercrate.rs | 0 src/test/ui/underscore-imports/shadow.rs | 23 + src/test/ui/underscore-imports/shadow.stderr | 13 + .../unused-2018.rs | 0 .../unused-2018.stderr | 0 .../unevaluated_fixed_size_array_len.stderr | 8 +- .../uninhabited-irrefutable.stderr | 1 + src/test/ui/union/union-derive-clone.stderr | 2 +- src/test/ui/union/union-generic.stderr | 18 +- src/test/ui/union/union-repr-c.rs | 2 +- src/test/ui/union/union-repr-c.stderr | 5 +- src/test/ui/unique-object-noncopyable.stderr | 2 +- src/test/ui/unique-pinned-nocopy.stderr | 2 +- .../ui/unreachable/unreachable-code.stderr | 5 +- .../ui/unreachable/unreachable-in-call.rs | 2 +- .../ui/unreachable/unreachable-in-call.stderr | 15 +- .../unreachable-try-pattern.stderr | 5 +- .../unwarned-match-on-never.stderr | 13 +- .../ui/unsized/unsized-bare-typaram.stderr | 11 +- src/test/ui/unsized/unsized-enum.stderr | 8 +- .../unsized-inherent-impl-self-type.stderr | 8 +- src/test/ui/unsized/unsized-struct.stderr | 16 +- .../unsized-trait-impl-self-type.stderr | 8 +- src/test/ui/unsized3.stderr | 52 +- src/test/ui/vtable-res-trait-param.stderr | 4 +- src/test/ui/wf/wf-const-type.stderr | 8 +- src/test/ui/wf/wf-enum-bound.stderr | 8 +- .../wf/wf-enum-fields-struct-variant.stderr | 8 +- src/test/ui/wf/wf-enum-fields.stderr | 8 +- src/test/ui/wf/wf-fn-where-clause.stderr | 8 +- .../wf/wf-impl-associated-type-trait.stderr | 8 +- src/test/ui/wf/wf-in-fn-arg.stderr | 8 +- src/test/ui/wf/wf-in-fn-ret.stderr | 8 +- src/test/ui/wf/wf-in-fn-type-arg.stderr | 8 +- src/test/ui/wf/wf-in-fn-type-ret.stderr | 8 +- src/test/ui/wf/wf-in-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 8 +- ...f-inherent-impl-method-where-clause.stderr | 8 +- .../wf/wf-inherent-impl-where-clause.stderr | 8 +- src/test/ui/wf/wf-object-safe.stderr | 5 +- src/test/ui/wf/wf-static-method.stderr | 3 +- src/test/ui/wf/wf-static-type.stderr | 8 +- src/test/ui/wf/wf-struct-bound.stderr | 8 +- src/test/ui/wf/wf-struct-field.stderr | 8 +- .../wf/wf-trait-associated-type-bound.stderr | 8 +- .../wf/wf-trait-associated-type-trait.stderr | 8 +- src/test/ui/wf/wf-trait-bound.stderr | 8 +- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 8 +- src/test/ui/wf/wf-trait-default-fn-ret.stderr | 8 +- .../wf-trait-default-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-trait-fn-arg.stderr | 8 +- src/test/ui/wf/wf-trait-fn-ret.stderr | 8 +- .../ui/wf/wf-trait-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-trait-superbound.stderr | 8 +- ...traints-are-local-for-inherent-impl.stderr | 12 +- ...onstraints-are-local-for-trait-impl.stderr | 12 +- .../where-clauses-method-unsatisfied.stderr | 4 +- .../where-clauses-unsatisfied.stderr | 9 +- .../ui/where-clauses/where-for-self-2.stderr | 12 +- src/test/ui/while-let.rs | 7 +- src/test/ui/while-let.stderr | 12 +- src/test/ui/wrapping-int-combinations.rs | 77 + src/tools/build-manifest/Cargo.toml | 2 +- src/tools/build-manifest/src/main.rs | 19 +- src/tools/cargotest/main.rs | 2 + src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/common.rs | 4 +- src/tools/compiletest/src/header.rs | 23 +- src/tools/compiletest/src/main.rs | 9 +- src/tools/compiletest/src/runtest.rs | 140 +- src/tools/compiletest/src/util.rs | 8 +- src/tools/error_index_generator/Cargo.toml | 4 + src/tools/error_index_generator/build.rs | 57 + src/tools/error_index_generator/main.rs | 50 +- src/tools/linkchecker/main.rs | 2 + src/tools/publish_toolstate.py | 118 +- src/tools/rustbook/src/main.rs | 88 +- .../rustc-std-workspace-alloc/Cargo.toml | 2 +- src/tools/rustc-std-workspace-core/Cargo.toml | 2 +- src/tools/rustc-std-workspace-std/Cargo.toml | 15 + src/tools/rustc-std-workspace-std/README.md | 3 + src/tools/rustc-std-workspace-std/lib.rs | 1 + src/tools/rustc-workspace-hack/Cargo.toml | 12 +- src/tools/tidy/src/deps.rs | 6 + src/tools/tidy/src/features.rs | 29 +- src/tools/tidy/src/features/tests.rs | 4 +- src/tools/tidy/src/main.rs | 2 + src/tools/tidy/src/style.rs | 26 +- src/tools/unstable-book-gen/src/main.rs | 2 + vendor/backtrace/.cargo-checksum.json | 2 +- vendor/backtrace/Cargo.lock | 392 ++ vendor/backtrace/Cargo.toml | 31 +- vendor/backtrace/README.md | 2 - vendor/backtrace/azure-pipelines.yml | 161 - vendor/backtrace/ci/azure-install-rust.yml | 25 - vendor/backtrace/ci/azure-test-all.yml | 57 - vendor/backtrace/src/capture.rs | 81 +- vendor/backtrace/src/dbghelp.rs | 150 +- vendor/backtrace/src/lib.rs | 3 + vendor/backtrace/src/print.rs | 268 + vendor/backtrace/src/print/fuchsia.rs | 432 ++ vendor/backtrace/src/symbolize/dladdr.rs | 4 +- vendor/backtrace/src/symbolize/gimli.rs | 287 +- vendor/backtrace/src/symbolize/mod.rs | 2 + vendor/backtrace/src/types.rs | 21 +- vendor/backtrace/src/windows.rs | 13 + vendor/backtrace/tests/concurrent-panics.rs | 72 + vendor/byteorder/.cargo-checksum.json | 2 +- vendor/byteorder/CHANGELOG.md | 43 + vendor/byteorder/Cargo.toml | 12 +- vendor/byteorder/README.md | 11 +- vendor/byteorder/benches/bench.rs | 68 +- vendor/byteorder/build.rs | 87 + vendor/byteorder/src/io.rs | 57 +- vendor/byteorder/src/lib.rs | 411 +- vendor/clap/.cargo-checksum.json | 2 +- vendor/clap/CHANGELOG.md | 41 + vendor/clap/Cargo.toml | 32 +- vendor/clap/README.md | 69 +- vendor/clap/SPONSORS.md | 21 +- vendor/clap/index.html | 1 - vendor/clap/justfile | 2 +- vendor/clap/src/app/mod.rs | 29 +- vendor/clap/src/app/parser.rs | 91 +- vendor/clap/src/app/settings.rs | 44 +- vendor/clap/src/app/validator.rs | 4 +- vendor/clap/src/args/arg.rs | 50 +- vendor/clap/src/args/arg_matches.rs | 9 +- vendor/clap/src/args/group.rs | 2 +- vendor/clap/src/args/settings.rs | 3 +- vendor/clap/src/completions/bash.rs | 48 +- vendor/clap/src/errors.rs | 3 +- vendor/clap/src/fmt.rs | 10 +- vendor/clap/src/lib.rs | 32 +- vendor/clap/src/macros.rs | 21 +- vendor/clap/src/suggestions.rs | 54 +- vendor/env_logger-0.5.13/.cargo-checksum.json | 1 - vendor/env_logger-0.5.13/Cargo.toml | 50 - vendor/env_logger-0.5.13/README.md | 140 - .../examples/custom_default_format.rs | 44 - .../examples/custom_format.rs | 52 - .../examples/custom_logger.rs | 60 - vendor/env_logger-0.5.13/examples/default.rs | 36 - .../examples/direct_logger.rs | 40 - vendor/env_logger-0.5.13/src/filter/mod.rs | 568 -- vendor/env_logger-0.5.13/src/filter/regex.rs | 29 - vendor/env_logger-0.5.13/src/filter/string.rs | 22 - vendor/env_logger-0.5.13/src/fmt.rs | 844 --- vendor/env_logger-0.5.13/src/lib.rs | 1125 --- vendor/env_logger-0.5.13/tests/log-in-log.rs | 38 - .../env_logger-0.5.13/tests/regexp_filter.rs | 51 - vendor/env_logger/.cargo-checksum.json | 2 +- vendor/env_logger/CHANGELOG.md | 3 + vendor/env_logger/Cargo.lock | 212 + vendor/env_logger/Cargo.toml | 4 +- vendor/env_logger/README.md | 18 +- vendor/env_logger/examples/default.rs | 3 + .../env_logger/examples/filters_from_code.rs | 19 + vendor/env_logger/src/filter/mod.rs | 14 +- vendor/env_logger/src/fmt/mod.rs | 4 +- vendor/env_logger/src/fmt/writer/mod.rs | 22 +- .../src/fmt/writer/termcolor/extern_impl.rs | 79 +- .../src/fmt/writer/termcolor/shim_impl.rs | 4 +- vendor/env_logger/src/lib.rs | 87 +- .../tests/init-twice-retains-filter.rs | 2 +- vendor/getopts/.cargo-checksum.json | 2 +- vendor/getopts/Cargo.toml | 15 +- vendor/getopts/README.md | 14 +- vendor/getopts/appveyor.yml | 17 - vendor/getopts/src/lib.rs | 30 +- vendor/getopts/src/tests/mod.rs | 18 +- vendor/getrandom/.cargo-checksum.json | 2 +- vendor/getrandom/CHANGELOG.md | 41 + vendor/getrandom/Cargo.toml | 20 +- vendor/getrandom/README.md | 23 +- vendor/getrandom/build.rs | 19 + vendor/getrandom/src/error.rs | 46 +- vendor/getrandom/src/lib.rs | 114 +- vendor/getrandom/src/use_file.rs | 61 +- vendor/getrandom/src/util_libc.rs | 22 + vendor/getrandom/src/wasi.rs | 15 +- vendor/getrandom/src/wasm32_bindgen.rs | 62 +- vendor/getrandom/src/wasm32_stdweb.rs | 10 +- vendor/getrandom/src/windows_uwp.rs | 59 + vendor/hashbrown-0.4.0/.cargo-checksum.json | 1 - vendor/hashbrown-0.4.0/CHANGELOG.md | 128 - vendor/hashbrown-0.4.0/Cargo.toml | 65 - vendor/hashbrown-0.4.0/README.md | 87 - vendor/hashbrown-0.4.0/benches/bench.rs | 150 - vendor/hashbrown-0.4.0/clippy.toml | 1 - .../src/external_trait_impls/mod.rs | 4 - .../src/external_trait_impls/rayon/helpers.rs | 26 - .../src/external_trait_impls/rayon/map.rs | 676 -- .../src/external_trait_impls/rayon/mod.rs | 5 - .../src/external_trait_impls/rayon/raw.rs | 193 - .../src/external_trait_impls/rayon/set.rs | 646 -- .../src/external_trait_impls/serde.rs | 200 - vendor/hashbrown-0.4.0/src/fx.rs | 119 - vendor/hashbrown-0.4.0/src/lib.rs | 93 - vendor/hashbrown-0.4.0/src/macros.rs | 54 - vendor/hashbrown-0.4.0/src/map.rs | 3566 ---------- vendor/hashbrown-0.4.0/src/raw/bitmask.rs | 108 - vendor/hashbrown-0.4.0/src/raw/generic.rs | 157 - vendor/hashbrown-0.4.0/src/raw/mod.rs | 1374 ---- vendor/hashbrown-0.4.0/src/raw/sse2.rs | 140 - vendor/hashbrown-0.4.0/src/rustc_entry.rs | 573 -- vendor/hashbrown-0.4.0/src/scopeguard.rs | 49 - vendor/hashbrown-0.4.0/src/set.rs | 1829 ----- vendor/hashbrown-0.4.0/tests/hasher.rs | 65 - vendor/hashbrown-0.4.0/tests/rayon.rs | 533 -- vendor/hashbrown-0.4.0/tests/serde.rs | 59 - vendor/hashbrown-0.4.0/tests/set.rs | 31 - vendor/kernel32-sys/.cargo-checksum.json | 1 + vendor/kernel32-sys/Cargo.toml | 17 + vendor/kernel32-sys/README.md | 13 + vendor/kernel32-sys/build.rs | 6 + vendor/kernel32-sys/src/lib.rs | 2754 ++++++++ vendor/libc/.cargo-checksum.json | 2 +- vendor/libc/CONTRIBUTING.md | 4 +- vendor/libc/Cargo.toml | 4 +- vendor/libc/README.md | 8 +- vendor/libc/build.rs | 16 +- vendor/libc/src/lib.rs | 6 + vendor/libc/src/unix/bsd/apple/b32.rs | 4 + vendor/libc/src/unix/bsd/apple/b64.rs | 4 + vendor/libc/src/unix/bsd/apple/mod.rs | 3 - .../bsd/freebsdlike/freebsd/freebsd11/mod.rs | 2 + .../bsd/freebsdlike/freebsd/freebsd12/mod.rs | 9 + .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 8 +- vendor/libc/src/unix/bsd/freebsdlike/mod.rs | 4 +- vendor/libc/src/unix/bsd/mod.rs | 4 +- .../src/unix/bsd/netbsdlike/openbsd/mod.rs | 3 +- .../libc/src/unix/linux_like/linux/align.rs | 4 + .../libc/src/unix/linux_like/linux/gnu/mod.rs | 63 - vendor/libc/src/unix/linux_like/linux/mod.rs | 62 + .../unix/linux_like/linux/musl/b32/hexagon.rs | 795 +++ .../src/unix/linux_like/linux/musl/b32/mod.rs | 3 + .../src/unix/linux_like/linux/musl/mod.rs | 5 +- vendor/libc/src/unix/linux_like/mod.rs | 1 + vendor/libc/src/unix/mod.rs | 86 +- vendor/libc/src/unix/redox/mod.rs | 710 +- vendor/libc/src/vxworks/aarch64.rs | 3 + vendor/libc/src/vxworks/arm.rs | 3 + vendor/libc/src/vxworks/armv7.rs | 2 + vendor/libc/src/vxworks/mod.rs | 2319 +++++++ vendor/libc/src/vxworks/powerpc.rs | 3 + vendor/libc/src/vxworks/powerpc64.rs | 3 + vendor/libc/src/vxworks/x86.rs | 3 + vendor/libc/src/vxworks/x86_64.rs | 3 + vendor/lock_api-0.1.3/.cargo-checksum.json | 1 + vendor/lock_api-0.1.3/Cargo.toml | 31 + vendor/lock_api-0.1.3/src/lib.rs | 106 + vendor/lock_api-0.1.3/src/mutex.rs | 496 ++ vendor/lock_api-0.1.3/src/remutex.rs | 564 ++ vendor/lock_api-0.1.3/src/rwlock.rs | 1345 ++++ vendor/lock_api/.cargo-checksum.json | 2 +- vendor/lock_api/Cargo.toml | 14 +- .../LICENSE-APACHE | 0 vendor/{quote => lock_api}/LICENSE-MIT | 0 vendor/lock_api/src/lib.rs | 21 +- vendor/lock_api/src/mutex.rs | 187 +- vendor/lock_api/src/remutex.rs | 247 +- vendor/lock_api/src/rwlock.rs | 463 +- vendor/log/.cargo-checksum.json | 2 +- vendor/log/CHANGELOG.md | 24 +- vendor/log/Cargo.toml | 20 +- vendor/log/README.md | 26 +- vendor/log/appveyor.yml | 19 - vendor/log/build.rs | 14 + vendor/log/src/kv/error.rs | 88 + vendor/log/src/kv/key.rs | 143 + vendor/log/src/kv/mod.rs | 23 + vendor/log/src/kv/source.rs | 396 ++ vendor/log/src/kv/value/impls.rs | 269 + vendor/log/src/kv/value/internal.rs | 264 + vendor/log/src/kv/value/mod.rs | 155 + vendor/log/src/kv/value/test.rs | 81 + vendor/log/src/lib.rs | 285 +- vendor/log/src/macros.rs | 81 +- vendor/log/src/serde.rs | 6 +- vendor/log/tests/filters.rs | 12 +- vendor/once_cell/.cargo-checksum.json | 1 + vendor/once_cell/CHANGELOG.md | 87 + vendor/once_cell/Cargo.lock | 197 + vendor/once_cell/Cargo.toml | 61 + .../LICENSE-APACHE | 0 vendor/{syn => once_cell}/LICENSE-MIT | 0 vendor/once_cell/README.md | 53 + vendor/once_cell/examples/bench.rs | 28 + .../examples/bench_vs_lazy_static.rs | 51 + vendor/once_cell/examples/lazy_static.rs | 36 + .../examples/reentrant_init_deadlocks.rs | 7 + vendor/once_cell/examples/regex.rs | 49 + vendor/once_cell/src/imp_pl.rs | 100 + vendor/once_cell/src/imp_std.rs | 333 + vendor/once_cell/src/lib.rs | 920 +++ vendor/once_cell/tests/test.rs | 521 ++ vendor/owning_ref/.cargo-checksum.json | 1 - vendor/owning_ref/Cargo.toml | 15 - vendor/owning_ref/README.md | 67 - vendor/owning_ref/src/lib.rs | 1891 ----- vendor/parking_lot/.cargo-checksum.json | 2 +- vendor/parking_lot/CHANGELOG.md | 67 +- vendor/parking_lot/Cargo.toml | 22 +- vendor/parking_lot/README.md | 9 +- vendor/parking_lot/appveyor.yml | 64 +- vendor/parking_lot/build.rs | 8 + vendor/parking_lot/src/condvar.rs | 78 +- vendor/parking_lot/src/deadlock.rs | 18 +- vendor/parking_lot/src/elision.rs | 126 +- vendor/parking_lot/src/lib.rs | 24 +- vendor/parking_lot/src/mutex.rs | 33 +- vendor/parking_lot/src/once.rs | 87 +- vendor/parking_lot/src/raw_mutex.rs | 52 +- vendor/parking_lot/src/raw_rwlock.rs | 1424 ++-- vendor/parking_lot/src/remutex.rs | 37 +- vendor/parking_lot/src/rwlock.rs | 64 +- vendor/parking_lot/src/util.rs | 9 +- vendor/parking_lot_core/.cargo-checksum.json | 2 +- vendor/parking_lot_core/Cargo.toml | 17 +- vendor/parking_lot_core/build.rs | 5 +- vendor/parking_lot_core/src/lib.rs | 59 +- vendor/parking_lot_core/src/parking_lot.rs | 508 +- vendor/parking_lot_core/src/spinwait.rs | 61 +- .../src/thread_parker/cloudabi.rs | 298 + .../src/thread_parker/generic.rs | 105 +- .../src/thread_parker/linux.rs | 136 +- .../parking_lot_core/src/thread_parker/mod.rs | 89 + .../src/thread_parker/redox.rs | 138 + .../parking_lot_core/src/thread_parker/sgx.rs | 94 + .../src/thread_parker/unix.rs | 129 +- .../src/thread_parker/wasm.rs | 53 + .../src/thread_parker/wasm_atomic.rs | 96 + .../src/thread_parker/windows/keyed_event.rs | 128 +- .../src/thread_parker/windows/mod.rs | 88 +- .../src/thread_parker/windows/waitaddress.rs | 119 +- vendor/parking_lot_core/src/util.rs | 5 +- vendor/parking_lot_core/src/word_lock.rs | 198 +- vendor/polonius-engine/.cargo-checksum.json | 2 +- vendor/polonius-engine/Cargo.toml | 2 +- vendor/polonius-engine/src/facts.rs | 39 +- .../src/output/datafrog_opt.rs | 21 +- vendor/polonius-engine/src/output/hybrid.rs | 6 +- .../src/output/initialization.rs | 145 + vendor/polonius-engine/src/output/liveness.rs | 86 +- .../src/output/location_insensitive.rs | 19 +- vendor/polonius-engine/src/output/mod.rs | 20 +- vendor/polonius-engine/src/output/naive.rs | 20 +- .../.cargo-checksum.json | 0 .../Cargo.toml | 0 .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 .../README.md | 0 .../build.rs | 0 .../src/fallback.rs | 0 .../src/lib.rs | 0 .../src/strnom.rs | 0 .../src/wrapper.rs | 0 .../tests/marker.rs | 0 .../tests/test.rs | 0 .../.cargo-checksum.json | 0 .../CONTRIBUTING.md | 0 .../Cargo.toml | 0 .../LICENSE | 0 .../README.md | 0 .../azure-pipelines.yml | 0 .../benches/html_rendering.rs | 0 .../benches/lib.rs | 0 .../build.rs | 0 .../examples/event-filter.rs | 0 .../examples/string-to-string.rs | 0 .../specs/footnotes.txt | 0 .../specs/regression.txt | 0 .../specs/table.txt | 0 .../src/entities.rs | 0 .../src/escape.rs | 0 .../src/html.rs | 0 .../src/lib.rs | 0 .../src/linklabel.rs | 0 .../src/main.rs | 0 .../src/parse.rs | 0 .../src/puncttable.rs | 0 .../src/scanners.rs | 0 .../src/simd.rs | 0 .../src/strings.rs | 0 .../src/tree.rs | 0 .../tests/errors.rs | 0 .../tests/html.rs | 0 .../tests/lib.rs | 0 .../tests/suite/footnotes.rs | 0 .../tests/suite/gfm_strikethrough.rs | 0 .../tests/suite/gfm_table.rs | 0 .../tests/suite/gfm_tasklist.rs | 0 .../tests/suite/mod.rs | 0 .../tests/suite/regression.rs | 0 .../tests/suite/spec.rs | 0 .../tests/suite/table.rs | 0 .../third_party/CommonMark/LICENSE | 0 .../third_party/CommonMark/README.google | 0 .../third_party/CommonMark/spec.txt | 0 .../third_party/GitHub/LICENSE | 0 .../third_party/GitHub/gfm_strikethrough.txt | 0 .../third_party/GitHub/gfm_table.txt | 0 .../third_party/GitHub/gfm_tasklist.txt | 0 .../third_party/GitHub/spec.txt | 0 .../third_party/xi-editor/LICENSE | 0 .../third_party/xi-editor/crdt.md | 0 .../tools/mk_entities.py | 0 .../tools/mk_puncttable.py | 0 .../.cargo-checksum.json | 0 vendor/{quote => quote-0.6.12}/Cargo.toml | 0 vendor/{quote => quote-0.6.12}/LICENSE-APACHE | 0 .../LICENSE-MIT | 2 +- vendor/{quote => quote-0.6.12}/README.md | 0 vendor/{quote => quote-0.6.12}/src/ext.rs | 0 vendor/{quote => quote-0.6.12}/src/lib.rs | 0 vendor/{quote => quote-0.6.12}/src/runtime.rs | 0 .../{quote => quote-0.6.12}/src/to_tokens.rs | 0 .../tests/conditional/integer128.rs | 0 vendor/{quote => quote-0.6.12}/tests/test.rs | 0 vendor/rustc-demangle/.cargo-checksum.json | 2 +- vendor/rustc-demangle/Cargo.toml | 2 +- vendor/rustc-demangle/src/legacy.rs | 173 +- vendor/rustc-demangle/src/lib.rs | 34 +- vendor/rustc-demangle/src/v0.rs | 35 +- vendor/serde/.cargo-checksum.json | 2 +- vendor/serde/Cargo.toml | 4 +- vendor/serde/build.rs | 25 + vendor/serde/src/de/ignored_any.rs | 11 +- vendor/serde/src/de/impls.rs | 49 +- vendor/serde/src/export.rs | 3 + vendor/serde/src/integer128.rs | 12 +- vendor/serde/src/lib.rs | 17 +- vendor/serde/src/private/de.rs | 2 + vendor/serde/src/ser/impls.rs | 46 +- vendor/strsim/.cargo-checksum.json | 2 +- vendor/strsim/CHANGELOG.md | 11 +- vendor/strsim/Cargo.toml | 6 +- vendor/strsim/README.md | 15 +- vendor/strsim/benches/benches.rs | 84 + vendor/strsim/src/lib.rs | 88 + vendor/strsim/tests/lib.rs | 14 +- .../{syn => syn-0.15.35}/.cargo-checksum.json | 0 vendor/{syn => syn-0.15.35}/Cargo.toml | 0 vendor/{syn => syn-0.15.35}/LICENSE-APACHE | 0 .../{toml-0.4.10 => syn-0.15.35}/LICENSE-MIT | 2 - vendor/{syn => syn-0.15.35}/README.md | 0 vendor/{syn => syn-0.15.35}/build.rs | 0 vendor/{syn => syn-0.15.35}/src/attr.rs | 0 vendor/{syn => syn-0.15.35}/src/buffer.rs | 0 .../src/custom_keyword.rs | 0 .../src/custom_punctuation.rs | 0 vendor/{syn => syn-0.15.35}/src/data.rs | 0 vendor/{syn => syn-0.15.35}/src/derive.rs | 0 vendor/{syn => syn-0.15.35}/src/error.rs | 0 vendor/{syn => syn-0.15.35}/src/export.rs | 0 vendor/{syn => syn-0.15.35}/src/expr.rs | 0 vendor/{syn => syn-0.15.35}/src/ext.rs | 0 vendor/{syn => syn-0.15.35}/src/file.rs | 0 vendor/{syn => syn-0.15.35}/src/gen/fold.rs | 0 vendor/{syn => syn-0.15.35}/src/gen/visit.rs | 0 .../{syn => syn-0.15.35}/src/gen/visit_mut.rs | 0 vendor/{syn => syn-0.15.35}/src/gen_helper.rs | 0 vendor/{syn => syn-0.15.35}/src/generics.rs | 0 vendor/{syn => syn-0.15.35}/src/group.rs | 0 vendor/{syn => syn-0.15.35}/src/ident.rs | 0 vendor/{syn => syn-0.15.35}/src/item.rs | 0 vendor/{syn => syn-0.15.35}/src/keyword.rs | 0 vendor/{syn => syn-0.15.35}/src/lib.rs | 0 vendor/{syn => syn-0.15.35}/src/lifetime.rs | 0 vendor/{syn => syn-0.15.35}/src/lit.rs | 0 vendor/{syn => syn-0.15.35}/src/lookahead.rs | 0 vendor/{syn => syn-0.15.35}/src/mac.rs | 0 vendor/{syn => syn-0.15.35}/src/macros.rs | 0 vendor/{syn => syn-0.15.35}/src/op.rs | 0 vendor/{syn => syn-0.15.35}/src/parse.rs | 0 .../src/parse_macro_input.rs | 0 .../{syn => syn-0.15.35}/src/parse_quote.rs | 0 vendor/{syn => syn-0.15.35}/src/path.rs | 0 vendor/{syn => syn-0.15.35}/src/print.rs | 0 vendor/{syn => syn-0.15.35}/src/punctuated.rs | 0 vendor/{syn => syn-0.15.35}/src/sealed.rs | 0 vendor/{syn => syn-0.15.35}/src/span.rs | 0 vendor/{syn => syn-0.15.35}/src/spanned.rs | 0 vendor/{syn => syn-0.15.35}/src/thread.rs | 0 vendor/{syn => syn-0.15.35}/src/token.rs | 0 vendor/{syn => syn-0.15.35}/src/tt.rs | 0 vendor/{syn => syn-0.15.35}/src/ty.rs | 0 vendor/tempfile/.cargo-checksum.json | 2 +- vendor/tempfile/Cargo.toml | 13 +- vendor/tempfile/NEWS | 111 +- vendor/tempfile/README.md | 8 +- vendor/tempfile/src/dir.rs | 10 +- vendor/tempfile/src/error.rs | 23 +- vendor/tempfile/src/file/imp/other.rs | 15 +- vendor/tempfile/src/file/imp/unix.rs | 120 +- vendor/tempfile/src/file/imp/windows.rs | 111 +- vendor/tempfile/src/file/mod.rs | 239 +- vendor/tempfile/src/lib.rs | 123 +- vendor/tempfile/src/spooled.rs | 11 +- vendor/tempfile/src/util.rs | 53 +- vendor/tempfile/tests/namedtempfile.rs | 82 +- vendor/tempfile/tests/spooled.rs | 9 +- vendor/tempfile/tests/tempdir.rs | 5 +- vendor/tempfile/tests/tempfile.rs | 7 +- vendor/term_size/.cargo-checksum.json | 1 + vendor/term_size/CHANGELOG.md | 48 + vendor/term_size/CONTRIBUTORS.md | 11 + vendor/term_size/Cargo.toml | 84 + .../{toml-0.4.10 => term_size}/LICENSE-APACHE | 0 .../LICENSE => term_size/LICENSE-MIT} | 2 +- vendor/term_size/README.md | 63 + vendor/term_size/appveyor.yml | 12 + vendor/term_size/index.html | 1 + vendor/term_size/justfile | 39 + vendor/term_size/rustfmt.toml | 4 + vendor/term_size/src/lib.rs | 237 + vendor/textwrap/.cargo-checksum.json | 2 +- vendor/textwrap/Cargo.toml | 17 +- vendor/textwrap/README.md | 62 +- vendor/textwrap/benches/linear.rs | 24 +- vendor/textwrap/examples/layout.rs | 8 +- vendor/textwrap/examples/termwidth.rs | 26 +- vendor/textwrap/src/indentation.rs | 294 + vendor/textwrap/src/lib.rs | 356 +- vendor/textwrap/src/splitting.rs | 139 + vendor/textwrap/tests/version-numbers.rs | 5 + vendor/toml-0.4.10/.cargo-checksum.json | 1 - vendor/toml-0.4.10/Cargo.toml | 33 - vendor/toml-0.4.10/README.md | 40 - vendor/toml-0.4.10/examples/decode.rs | 55 - vendor/toml-0.4.10/examples/enum_external.rs | 46 - vendor/toml-0.4.10/examples/toml2json.rs | 51 - vendor/toml-0.4.10/src/datetime.rs | 424 -- vendor/toml-0.4.10/src/de.rs | 1861 ----- vendor/toml-0.4.10/src/lib.rs | 175 - vendor/toml-0.4.10/src/macros.rs | 462 -- vendor/toml-0.4.10/src/ser.rs | 1802 ----- vendor/toml-0.4.10/src/spanned.rs | 140 - vendor/toml-0.4.10/src/tokens.rs | 690 -- vendor/toml-0.4.10/src/value.rs | 1007 --- .../tests/enum_external_deserialize.rs | 238 - vendor/toml/.cargo-checksum.json | 2 +- vendor/toml/Cargo.toml | 4 +- vendor/toml/src/de.rs | 237 +- vendor/toml/src/lib.rs | 1 - vendor/toml/src/ser.rs | 6 +- vendor/toml/src/spanned.rs | 44 +- vendor/toml/src/value.rs | 13 +- vendor/unicase/.cargo-checksum.json | 2 +- vendor/unicase/Cargo.toml | 4 +- vendor/unicase/README.md | 2 +- vendor/unicase/src/lib.rs | 2 +- vendor/unicase/src/unicode/map.rs | 3478 ++++++---- vendor/unicode-width/.cargo-checksum.json | 2 +- vendor/unicode-width/Cargo.toml | 18 +- vendor/unicode-width/README.md | 23 +- vendor/unicode-width/src/tests.rs | 10 + vendor/unicode-xid-0.1.0/.cargo-checksum.json | 1 + vendor/unicode-xid-0.1.0/COPYRIGHT | 7 + vendor/unicode-xid-0.1.0/Cargo.toml | 26 + vendor/unicode-xid-0.1.0/LICENSE-APACHE | 201 + vendor/unicode-xid-0.1.0/LICENSE-MIT | 25 + vendor/unicode-xid-0.1.0/README.md | 34 + .../scripts/unicode.py | 0 vendor/unicode-xid-0.1.0/src/lib.rs | 87 + vendor/unicode-xid-0.1.0/src/tables.rs | 426 ++ vendor/unicode-xid-0.1.0/src/tests.rs | 113 + vendor/unicode-xid/.cargo-checksum.json | 2 +- vendor/unicode-xid/Cargo.toml | 39 +- vendor/unicode-xid/README.md | 12 +- vendor/unicode-xid/src/lib.rs | 2 +- vendor/unicode-xid/src/tables.rs | 737 +- vendor/unicode-xid/src/tests.rs | 14 +- vendor/wasi/.cargo-checksum.json | 1 + vendor/wasi/0001-maybe.patch | 1178 ++++ vendor/wasi/CODE_OF_CONDUCT.md | 46 + vendor/wasi/CONTRIBUTING.md | 8 + vendor/wasi/Cargo.toml | 43 + vendor/wasi/LICENSE-APACHE | 201 + .../LICENSE-Apache-2.0_WITH_LLVM-exception | 220 + vendor/{hashbrown-0.4.0 => wasi}/LICENSE-MIT | 2 - vendor/wasi/README.md | 24 + vendor/wasi/clip.log | 20 + vendor/wasi/old-bitflags.patch | 570 ++ vendor/wasi/rusty-tags.vi | 477 ++ vendor/wasi/src/lib.rs | 20 + vendor/wasi/src/wasi_unstable/mod.rs | 824 +++ vendor/wasi/src/wasi_unstable/raw.rs | 632 ++ vendor/winapi-0.2.8/.cargo-checksum.json | 1 + vendor/winapi-0.2.8/Cargo.toml | 61 + vendor/winapi-0.2.8/LICENSE.md | 21 + vendor/winapi-0.2.8/src/activation.rs | 5 + vendor/winapi-0.2.8/src/audioclient.rs | 71 + vendor/winapi-0.2.8/src/audiosessiontypes.rs | 11 + vendor/winapi-0.2.8/src/basetsd.rs | 99 + vendor/winapi-0.2.8/src/bcrypt.rs | 356 + vendor/winapi-0.2.8/src/cfg.rs | 134 + vendor/winapi-0.2.8/src/cfgmgr32.rs | 758 ++ vendor/winapi-0.2.8/src/combaseapi.rs | 17 + vendor/winapi-0.2.8/src/commctrl.rs | 3578 ++++++++++ vendor/winapi-0.2.8/src/commdlg.rs | 583 ++ vendor/winapi-0.2.8/src/corsym.rs | 79 + vendor/winapi-0.2.8/src/d2d1.rs | 734 ++ vendor/winapi-0.2.8/src/d2dbasetypes.rs | 61 + vendor/winapi-0.2.8/src/d3d10shader.rs | 110 + vendor/winapi-0.2.8/src/d3d11.rs | 2665 ++++++++ vendor/winapi-0.2.8/src/d3d11shader.rs | 320 + vendor/winapi-0.2.8/src/d3d12.rs | 2324 +++++++ vendor/winapi-0.2.8/src/d3d12sdklayers.rs | 1063 +++ vendor/winapi-0.2.8/src/d3d12shader.rs | 320 + vendor/winapi-0.2.8/src/d3d9.rs | 713 ++ vendor/winapi-0.2.8/src/d3d9caps.rs | 349 + vendor/winapi-0.2.8/src/d3d9types.rs | 1397 ++++ vendor/winapi-0.2.8/src/d3dcommon.rs | 753 ++ vendor/winapi-0.2.8/src/d3dcompiler.rs | 74 + vendor/winapi-0.2.8/src/dbghelp.rs | 340 + vendor/winapi-0.2.8/src/dcommon.rs | 18 + vendor/winapi-0.2.8/src/devpropdef.rs | 71 + vendor/winapi-0.2.8/src/docobj.rs | 22 + vendor/winapi-0.2.8/src/dpapi.rs | 11 + vendor/winapi-0.2.8/src/dsgetdc.rs | 113 + vendor/winapi-0.2.8/src/dsound.rs | 132 + vendor/winapi-0.2.8/src/dsrole.rs | 50 + vendor/winapi-0.2.8/src/dwmapi.rs | 9 + vendor/winapi-0.2.8/src/dwrite.rs | 1038 +++ vendor/winapi-0.2.8/src/dxgi.rs | 240 + vendor/winapi-0.2.8/src/dxgi1_2.rs | 288 + vendor/winapi-0.2.8/src/dxgi1_3.rs | 131 + vendor/winapi-0.2.8/src/dxgi1_4.rs | 82 + vendor/winapi-0.2.8/src/dxgiformat.rs | 124 + vendor/winapi-0.2.8/src/dxgitype.rs | 86 + vendor/winapi-0.2.8/src/errhandlingapi.rs | 7 + vendor/winapi-0.2.8/src/excpt.rs | 14 + vendor/winapi-0.2.8/src/fileapi.rs | 152 + vendor/winapi-0.2.8/src/gl.rs | 35 + vendor/winapi-0.2.8/src/guiddef.rs | 20 + vendor/winapi-0.2.8/src/heapapi.rs | 12 + vendor/winapi-0.2.8/src/hidclass.rs | 56 + vendor/winapi-0.2.8/src/hidpi.rs | 182 + vendor/winapi-0.2.8/src/hidsdi.rs | 15 + vendor/winapi-0.2.8/src/hidusage.rs | 270 + vendor/winapi-0.2.8/src/hstring.rs | 16 + vendor/winapi-0.2.8/src/http.rs | 828 +++ vendor/winapi-0.2.8/src/imm.rs | 3 + vendor/winapi-0.2.8/src/inaddr.rs | 22 + vendor/winapi-0.2.8/src/inspectable.rs | 15 + vendor/winapi-0.2.8/src/ksmedia.rs | 18 + vendor/winapi-0.2.8/src/lib.rs | 368 + vendor/winapi-0.2.8/src/libloaderapi.rs | 23 + vendor/winapi-0.2.8/src/lmaccess.rs | 853 +++ vendor/winapi-0.2.8/src/lmcons.rs | 55 + vendor/winapi-0.2.8/src/lmdfs.rs | 311 + vendor/winapi-0.2.8/src/lmerrlog.rs | 263 + vendor/winapi-0.2.8/src/lmjoin.rs | 80 + vendor/winapi-0.2.8/src/lsalookup.rs | 69 + vendor/winapi-0.2.8/src/macros.rs | 270 + vendor/winapi-0.2.8/src/memoryapi.rs | 19 + vendor/winapi-0.2.8/src/minschannel.rs | 56 + vendor/winapi-0.2.8/src/minwinbase.rs | 253 + vendor/winapi-0.2.8/src/minwindef.rs | 89 + vendor/winapi-0.2.8/src/mmdeviceapi.rs | 63 + vendor/winapi-0.2.8/src/mmreg.rs | 304 + vendor/winapi-0.2.8/src/mmsystem.rs | 259 + vendor/winapi-0.2.8/src/mscat.rs | 28 + vendor/winapi-0.2.8/src/mssip.rs | 103 + vendor/winapi-0.2.8/src/nb30.rs | 200 + vendor/winapi-0.2.8/src/ncrypt.rs | 9 + vendor/winapi-0.2.8/src/ntdef.rs | 7 + vendor/winapi-0.2.8/src/ntsecapi.rs | 1589 +++++ vendor/winapi-0.2.8/src/ntstatus.rs | 2474 +++++++ vendor/winapi-0.2.8/src/oaidl.rs | 590 ++ vendor/winapi-0.2.8/src/objbase.rs | 5 + vendor/winapi-0.2.8/src/objidl.rs | 100 + vendor/winapi-0.2.8/src/objidlbase.rs | 93 + vendor/winapi-0.2.8/src/olectl.rs | 10 + vendor/winapi-0.2.8/src/pdh.rs | 52 + vendor/winapi-0.2.8/src/playsoundapi.rs | 19 + vendor/winapi-0.2.8/src/processsnapshot.rs | 58 + vendor/winapi-0.2.8/src/processthreadsapi.rs | 62 + vendor/winapi-0.2.8/src/propidl.rs | 10 + vendor/winapi-0.2.8/src/propsys.rs | 4 + vendor/winapi-0.2.8/src/prsht.rs | 262 + vendor/winapi-0.2.8/src/psapi.rs | 166 + vendor/winapi-0.2.8/src/qos.rs | 16 + vendor/winapi-0.2.8/src/reason.rs | 63 + .../winapi-0.2.8/src/restrictederrorinfo.rs | 9 + vendor/winapi-0.2.8/src/roapi.rs | 13 + vendor/winapi-0.2.8/src/roerrorapi.rs | 11 + vendor/winapi-0.2.8/src/rpc.rs | 5 + vendor/winapi-0.2.8/src/rpcdce.rs | 535 ++ vendor/winapi-0.2.8/src/sapi.rs | 2431 +++++++ vendor/winapi-0.2.8/src/schannel.rs | 333 + vendor/winapi-0.2.8/src/servprov.rs | 11 + vendor/winapi-0.2.8/src/setupapi.rs | 1301 ++++ vendor/winapi-0.2.8/src/shellapi.rs | 62 + vendor/winapi-0.2.8/src/shellscalingapi.rs | 19 + vendor/winapi-0.2.8/src/shlguid.rs | 2 + vendor/winapi-0.2.8/src/shlobj.rs | 94 + vendor/winapi-0.2.8/src/shobjidl.rs | 652 ++ vendor/winapi-0.2.8/src/shtypes.rs | 40 + vendor/winapi-0.2.8/src/spapidef.rs | 48 + vendor/winapi-0.2.8/src/sql.rs | 179 + vendor/winapi-0.2.8/src/sqltypes.rs | 130 + vendor/winapi-0.2.8/src/sspi.rs | 657 ++ vendor/winapi-0.2.8/src/strmif.rs | 4 + vendor/winapi-0.2.8/src/subauth.rs | 198 + vendor/winapi-0.2.8/src/synchapi.rs | 14 + vendor/winapi-0.2.8/src/sysinfoapi.rs | 46 + vendor/winapi-0.2.8/src/threadpoolapi.rs | 7 + vendor/winapi-0.2.8/src/timezoneapi.rs | 27 + vendor/winapi-0.2.8/src/tlhelp32.rs | 104 + vendor/winapi-0.2.8/src/unknwnbase.rs | 29 + vendor/winapi-0.2.8/src/urlhist.rs | 56 + vendor/winapi-0.2.8/src/urlmon.rs | 6 + vendor/winapi-0.2.8/src/usb.rs | 18 + vendor/winapi-0.2.8/src/usbspec.rs | 41 + vendor/winapi-0.2.8/src/usp10.rs | 201 + vendor/winapi-0.2.8/src/vadefs.rs | 7 + vendor/winapi-0.2.8/src/vsbackup.rs | 303 + vendor/winapi-0.2.8/src/vss.rs | 256 + vendor/winapi-0.2.8/src/vsserror.rs | 85 + vendor/winapi-0.2.8/src/vswriter.rs | 241 + vendor/winapi-0.2.8/src/werapi.rs | 8 + vendor/winapi-0.2.8/src/winbase.rs | 552 ++ vendor/winapi-0.2.8/src/wincon.rs | 198 + vendor/winapi-0.2.8/src/wincred.rs | 209 + vendor/winapi-0.2.8/src/wincrypt.rs | 2206 ++++++ vendor/winapi-0.2.8/src/windef.rs | 57 + vendor/winapi-0.2.8/src/windowscodecs.rs | 363 + vendor/winapi-0.2.8/src/windowsx.rs | 22 + vendor/winapi-0.2.8/src/winerror.rs | 6065 +++++++++++++++++ vendor/winapi-0.2.8/src/winevt.rs | 40 + vendor/winapi-0.2.8/src/wingdi.rs | 1238 ++++ vendor/winapi-0.2.8/src/winhttp.rs | 441 ++ vendor/winapi-0.2.8/src/winioctl.rs | 754 ++ vendor/winapi-0.2.8/src/winnetwk.rs | 275 + vendor/winapi-0.2.8/src/winnls.rs | 164 + vendor/winapi-0.2.8/src/winnt.rs | 2368 +++++++ vendor/winapi-0.2.8/src/winreg.rs | 41 + vendor/winapi-0.2.8/src/winscard.rs | 269 + vendor/winapi-0.2.8/src/winsmcrd.rs | 157 + vendor/winapi-0.2.8/src/winsock2.rs | 429 ++ vendor/winapi-0.2.8/src/winspool.rs | 29 + vendor/winapi-0.2.8/src/winstring.rs | 3 + vendor/winapi-0.2.8/src/winsvc.rs | 200 + vendor/winapi-0.2.8/src/winusb.rs | 33 + vendor/winapi-0.2.8/src/winusbio.rs | 18 + vendor/winapi-0.2.8/src/winuser.rs | 2334 +++++++ vendor/winapi-0.2.8/src/ws2def.rs | 279 + vendor/winapi-0.2.8/src/ws2ipdef.rs | 42 + vendor/winapi-0.2.8/src/ws2spi.rs | 57 + vendor/winapi-0.2.8/src/ws2tcpip.rs | 27 + vendor/winapi-0.2.8/src/wtypes.rs | 75 + vendor/winapi-0.2.8/src/wtypesbase.rs | 37 + vendor/winapi-0.2.8/src/xinput.rs | 118 + vendor/winapi-build/.cargo-checksum.json | 1 + vendor/winapi-build/Cargo.toml | 11 + vendor/winapi-build/src/lib.rs | 14 + version | 2 +- 3363 files changed, 139825 insertions(+), 65903 deletions(-) create mode 100644 src/ci/docker/dist-armv7-linux/crosstool-ng.sh delete mode 100644 src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch create mode 100644 src/doc/reference/src/expressions/await-expr.md create mode 100644 src/doc/rust-by-example/src/conversion/try_from_try_into.md create mode 100644 src/doc/rust-by-example/src/error/option_unwrap/question_mark.md create mode 100644 src/doc/rust-by-example/src/trait/dyn.md create mode 100644 src/doc/rust-by-example/src/trait/impl_trait.md create mode 100644 src/doc/rust-by-example/src/traits/disambiguating.md create mode 100644 src/doc/rust-by-example/src/traits/supertraits.md mode change 100644 => 100755 src/doc/rustc-guide/ci/build-ignore-timeouts.sh delete mode 100644 src/doc/rustc-guide/src/existential-types.md create mode 100644 src/doc/rustc-guide/src/opaque-types-type-alias-impl-trait.md create mode 100644 src/doc/rustc-guide/src/stability.md create mode 100644 src/doc/unstable-book/src/language-features/or-patterns.md delete mode 100644 src/doc/unstable-book/src/language-features/param-attrs.md create mode 100644 src/libcore/bool.rs create mode 100644 src/libcore/tests/bool.rs create mode 100644 src/librustc/middle/diagnostic_items.rs rename src/{librustc => librustc_ast_borrowck}/cfg/construct.rs (84%) rename src/{librustc => librustc_ast_borrowck}/cfg/graphviz.rs (88%) rename src/{librustc => librustc_ast_borrowck}/cfg/mod.rs (51%) delete mode 100644 src/librustc_data_structures/obligation_forest/node_index.rs create mode 100644 src/librustc_driver/args.rs create mode 100644 src/librustc_interface/build.rs create mode 100644 src/librustc_lint/redundant_semicolon.rs create mode 100644 src/librustc_mir/dataflow/generic.rs create mode 100644 src/librustc_plugin/deprecated/Cargo.toml create mode 100644 src/librustc_plugin/deprecated/lib.rs create mode 100644 src/librustc_target/spec/aarch64_uwp_windows_msvc.rs delete mode 100644 src/librustc_target/spec/arm_wrs_vxworks_sf.rs delete mode 100644 src/librustc_target/spec/armv7_wrs_vxworks.rs rename src/librustc_target/spec/{arm_wrs_vxworks.rs => armv7_wrs_vxworks_eabihf.rs} (77%) delete mode 100644 src/librustc_target/spec/i586_wrs_vxworks.rs create mode 100644 src/librustc_target/spec/i686_unknown_uefi.rs create mode 100644 src/librustc_target/spec/i686_uwp_windows_msvc.rs delete mode 100644 src/librustc_target/spec/i686_wrs_vxworks_gnu.rs create mode 100644 src/librustc_target/spec/linux_kernel_base.rs rename src/librustc_target/spec/{powerpc64_wrs_vxworks_gnusf.rs => mips64_unknown_linux_muslabi64.rs} (52%) create mode 100644 src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs delete mode 100644 src/librustc_target/spec/powerpc_wrs_vxworks_gnusf.rs delete mode 100644 src/librustc_target/spec/powerpc_wrs_vxworks_gnuspesf.rs create mode 100644 src/librustc_target/spec/sparc64_unknown_openbsd.rs create mode 100644 src/librustc_target/spec/windows_uwp_msvc_base.rs create mode 100644 src/librustc_target/spec/x86_64_apple_ios_macabi.rs create mode 100644 src/librustc_target/spec/x86_64_linux_kernel.rs create mode 100644 src/librustc_target/spec/x86_64_uwp_windows_msvc.rs create mode 100644 src/librustc_typeck/check/pat.rs create mode 100644 src/librustdoc/html/sources.rs create mode 100644 src/libstd/backtrace.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/mod.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/printing/dladdr.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/printing/mod.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/mod.rs delete mode 100644 src/libstd/sys/vxworks/process/rtp.rs delete mode 100644 src/libsyntax/diagnostics/metadata.rs delete mode 100644 src/libsyntax/diagnostics/plugin.rs delete mode 100644 src/libsyntax/feature_gate.rs create mode 100644 src/libsyntax/feature_gate/accepted.rs create mode 100644 src/libsyntax/feature_gate/active.rs create mode 100644 src/libsyntax/feature_gate/builtin_attrs.rs create mode 100644 src/libsyntax/feature_gate/check.rs create mode 100644 src/libsyntax/feature_gate/mod.rs create mode 100644 src/libsyntax/feature_gate/removed.rs create mode 100644 src/libsyntax_ext/cmdline_attrs.rs delete mode 100644 src/stdarch/.appveyor.yml create mode 100644 src/stdarch/.cirrus.yml rename src/stdarch/{azure-pipelines.yml => ci/azure.yml} (78%) create mode 100644 src/test/codegen/README.md create mode 100644 src/test/codegen/integer-cmp.rs create mode 100644 src/test/codegen/iter-fold-closure-no-dupes.rs create mode 100644 src/test/codegen/iter-fold-closure-no-iterator.rs create mode 100644 src/test/codegen/var-names.rs rename src/test/{ui/issues => compile-fail}/issue-44415.rs (100%) create mode 100644 src/test/mir-opt/no-spurious-drop-after-call.rs rename src/test/run-make-fulldeps/libtest-json/{output.json => output-default.json} (91%) create mode 100644 src/test/run-make-fulldeps/libtest-json/output-stdout-success.json create mode 100644 src/test/run-make-fulldeps/lto-empty/Makefile create mode 100644 src/test/run-make-fulldeps/lto-empty/lib.rs create mode 100644 src/test/rustdoc-js/exact-match.js create mode 100644 src/test/rustdoc-js/exact-match.rs create mode 100644 src/test/rustdoc-js/module-substring.js create mode 100644 src/test/rustdoc-js/module-substring.rs create mode 100644 src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs create mode 100644 src/test/rustdoc/inline_cross/impl_trait.rs rename src/test/ui/{ => abi}/abi-sysv64-arg-passing.rs (100%) rename src/test/ui/{ => abi}/abi-sysv64-register-usage.rs (100%) rename src/test/ui/{ => abi}/abort-on-c-abi.rs (100%) rename src/test/ui/{ => abi}/anon-extern-mod.rs (100%) rename src/test/ui/{ => abi}/auxiliary/anon-extern-mod-cross-crate-1.rs (100%) rename src/test/ui/{ => abi}/auxiliary/foreign_lib.rs (100%) rename src/test/ui/{ => abi}/c-stack-as-value.rs (100%) rename src/test/ui/{ => abi}/cabi-int-widening.rs (100%) rename src/test/ui/{ => abi}/consts/auxiliary/anon-extern-mod-cross-crate-1.rs (100%) rename src/test/ui/{ => abi}/cross-crate/anon-extern-mod-cross-crate-2.rs (100%) rename src/test/ui/{ => abi}/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs (100%) rename src/test/ui/{ => abi}/duplicated-external-mods.rs (100%) rename src/test/ui/{ => abi}/extern/auxiliary/extern-crosscrate-source.rs (100%) rename src/test/ui/{ => abi}/extern/extern-call-deep.rs (100%) rename src/test/ui/{ => abi}/extern/extern-call-deep2.rs (100%) rename src/test/ui/{ => abi}/extern/extern-call-direct.rs (100%) rename src/test/ui/{ => abi}/extern/extern-call-indirect.rs (100%) rename src/test/ui/{ => abi}/extern/extern-call-scrub.rs (100%) rename src/test/ui/{ => abi}/extern/extern-crosscrate.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-TwoU16s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-TwoU32s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-TwoU64s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-TwoU8s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-char.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-double.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-empty.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-u32.rs (100%) rename src/test/ui/{ => abi}/extern/extern-pass-u64.rs (100%) rename src/test/ui/{ => abi}/extern/extern-return-TwoU16s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-return-TwoU32s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-return-TwoU64s.rs (100%) rename src/test/ui/{ => abi}/extern/extern-return-TwoU8s.rs (100%) rename src/test/ui/{ => abi}/foreign/auxiliary/foreign_lib.rs (100%) rename src/test/ui/{ => abi}/foreign/foreign-call-no-runtime.rs (100%) rename src/test/ui/{ => abi}/foreign/foreign-dupe.rs (100%) rename src/test/ui/{ => abi}/foreign/foreign-fn-with-byval.rs (100%) rename src/test/ui/{ => abi}/foreign/foreign-no-abi.rs (100%) rename src/test/ui/{ => abi}/invoke-external-foreign.rs (100%) rename src/test/ui/{ => abi}/lib-defaults.rs (100%) rename src/test/ui/{ => abi}/macros/macros-in-extern.rs (100%) rename src/test/ui/{ => abi}/macros/macros-in-extern.stderr (100%) rename src/test/ui/{ => abi}/mir/mir_codegen_calls_variadic.rs (100%) rename src/test/ui/{ => abi}/numbers-arithmetic/i128-ffi.rs (100%) create mode 100644 src/test/ui/abi/proc-macro/auxiliary/test-macros.rs rename src/test/ui/{ => abi}/proc-macro/macros-in-extern.rs (100%) rename src/test/ui/{ => abi}/proc-macro/macros-in-extern.stderr (100%) rename src/test/ui/{ => abi}/segfault-no-out-of-stack.rs (100%) rename src/test/ui/{ => abi}/stack-probes-lto.rs (100%) rename src/test/ui/{ => abi}/stack-probes.rs (100%) rename src/test/ui/{ => abi}/statics/static-mut-foreign.rs (100%) rename src/test/ui/{structs-enums => abi/struct-enums}/struct-return.rs (100%) rename src/test/ui/{ => abi}/union/union-c-interop.rs (100%) rename src/test/ui/{ => abi}/variadic-ffi.rs (100%) create mode 100644 src/test/ui/allocator/hygiene.rs create mode 100644 src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs create mode 100644 src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr create mode 100644 src/test/ui/ast-json/ast-json-ice.rs create mode 100644 src/test/ui/ast-json/ast-json-output.rs create mode 100644 src/test/ui/ast-json/ast-json-output.stdout create mode 100644 src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs create mode 100644 src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr create mode 100644 src/test/ui/async-await/async-borrowck-escaping-closure-error.rs create mode 100644 src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr create mode 100644 src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs create mode 100644 src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs create mode 100644 src/test/ui/async-await/issue-61949-self-return-type.rs create mode 100644 src/test/ui/async-await/issue-61949-self-return-type.stderr create mode 100644 src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs create mode 100644 src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs create mode 100644 src/test/ui/async-await/issue-64130-non-send-future-diags.rs create mode 100644 src/test/ui/async-await/issue-64130-non-send-future-diags.stderr create mode 100644 src/test/ui/async-await/issue-64391.rs create mode 100644 src/test/ui/async-await/issues/issue-54752-async-block.stderr create mode 100644 src/test/ui/async-await/issues/issue-62517-1.rs create mode 100644 src/test/ui/async-await/issues/issue-62517-2.rs create mode 100644 src/test/ui/async-await/issues/issue-63388-1.nll.stderr create mode 100644 src/test/ui/async-await/issues/issue-63388-1.rs create mode 100644 src/test/ui/async-await/issues/issue-63388-1.stderr create mode 100644 src/test/ui/async-await/issues/issue-63388-2.nll.stderr create mode 100644 src/test/ui/async-await/issues/issue-63388-2.rs create mode 100644 src/test/ui/async-await/issues/issue-63388-2.stderr create mode 100644 src/test/ui/async-await/issues/issue-63388-3.rs create mode 100644 src/test/ui/async-await/issues/issue-63388-4.rs create mode 100644 src/test/ui/async-await/issues/issue-64391-2.rs create mode 100644 src/test/ui/async-await/issues/issue-64433.rs create mode 100644 src/test/ui/async-await/issues/issue-64477.rs create mode 100644 src/test/ui/async-await/issues/issue-64964.rs create mode 100644 src/test/ui/async-await/issues/non-async-enclosing-span.rs create mode 100644 src/test/ui/async-await/issues/non-async-enclosing-span.stderr create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr create mode 100644 src/test/ui/async-await/nested-in-impl.rs delete mode 100644 src/test/ui/async-await/no-args-non-move-async-closure.rs create mode 100644 src/test/ui/async-await/no-params-non-move-async-closure.rs rename src/test/ui/async-await/{no-args-non-move-async-closure.stderr => no-params-non-move-async-closure.stderr} (63%) create mode 100644 src/test/ui/async-await/suggest-switching-edition-on-await.rs create mode 100644 src/test/ui/async-await/suggest-switching-edition-on-await.stderr create mode 100644 src/test/ui/async-await/unreachable-lint-1.rs create mode 100644 src/test/ui/async-await/unreachable-lint-1.stderr create mode 100644 src/test/ui/async-await/unreachable-lint.rs create mode 100644 src/test/ui/attributes/unnamed-field-attributes.rs create mode 100644 src/test/ui/attrs-resolution-errors.rs create mode 100644 src/test/ui/attrs-resolution-errors.stderr create mode 100644 src/test/ui/attrs-resolution.rs delete mode 100644 src/test/ui/bind-by-move/bind-by-move-no-guards.rs delete mode 100644 src/test/ui/bind-by-move/bind-by-move-no-guards.stderr create mode 100644 src/test/ui/block-expr-precedence.stderr create mode 100644 src/test/ui/borrowck/move-error-snippets-ext.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.stderr create mode 100644 src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr create mode 100644 src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs create mode 100644 src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr create mode 100644 src/test/ui/coherence/conflicting-impl-with-err.rs create mode 100644 src/test/ui/coherence/conflicting-impl-with-err.stderr create mode 100644 src/test/ui/commandline-argfile-badutf8.args create mode 100644 src/test/ui/commandline-argfile-badutf8.rs create mode 100644 src/test/ui/commandline-argfile-badutf8.stderr create mode 100644 src/test/ui/commandline-argfile-missing.rs create mode 100644 src/test/ui/commandline-argfile-missing.stderr create mode 100644 src/test/ui/commandline-argfile.args create mode 100644 src/test/ui/commandline-argfile.rs create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr create mode 100644 src/test/ui/const-generics/foreign-item-const-parameter.rs create mode 100644 src/test/ui/const-generics/foreign-item-const-parameter.stderr create mode 100644 src/test/ui/const-generics/issue-61432.rs create mode 100644 src/test/ui/const-generics/issue-61432.stderr create mode 100644 src/test/ui/const-generics/issue-64519.rs create mode 100644 src/test/ui/const-generics/issue-64519.stderr create mode 100644 src/test/ui/consts/auxiliary/issue-63226.rs create mode 100644 src/test/ui/consts/const-err3.rs create mode 100644 src/test/ui/consts/const-err3.stderr create mode 100644 src/test/ui/consts/const-eval/const_fn_ptr.rs create mode 100644 src/test/ui/consts/const-eval/const_fn_ptr.stderr create mode 100644 src/test/ui/consts/const-eval/const_fn_ptr_fail.rs create mode 100644 src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs create mode 100644 src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr create mode 100644 src/test/ui/consts/const-eval/dangling.rs create mode 100644 src/test/ui/consts/const-eval/dangling.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors2.rs create mode 100644 src/test/ui/consts/const-eval/promoted_errors2.stderr create mode 100644 src/test/ui/consts/const-eval/ub-wide-ptr.rs create mode 100644 src/test/ui/consts/const-eval/ub-wide-ptr.stderr delete mode 100644 src/test/ui/consts/const-eval/union-ub-fat-ptr.rs delete mode 100644 src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr create mode 100644 src/test/ui/consts/issue-63226.rs create mode 100644 src/test/ui/consts/issue-64059-2.rs create mode 100644 src/test/ui/consts/issue-64059.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs rename src/test/ui/consts/min_const_fn/{min_const_fn_unsafe.stderr => min_const_fn_unsafe_bad.stderr} (79%) rename src/test/ui/consts/min_const_fn/{min_const_fn_unsafe.rs => min_const_fn_unsafe_ok.rs} (61%) create mode 100644 src/test/ui/consts/miri_unleashed/enum_discriminants.rs create mode 100644 src/test/ui/consts/miri_unleashed/enum_discriminants.stderr create mode 100644 src/test/ui/consts/miri_unleashed/mutable_const.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_const.stderr create mode 100644 src/test/ui/consts/packed_pattern.stderr create mode 100644 src/test/ui/consts/packed_pattern2.stderr create mode 100644 src/test/ui/consts/too_generic_eval_ice.rs create mode 100644 src/test/ui/consts/too_generic_eval_ice.stderr create mode 100644 src/test/ui/consts/zst_no_llvm_alloc.rs create mode 100644 src/test/ui/derives/derive-hygiene.rs delete mode 100644 src/test/ui/did_you_mean/multiple-pattern-typo.rs delete mode 100644 src/test/ui/did_you_mean/multiple-pattern-typo.stderr delete mode 100644 src/test/ui/error-codes/E0008.rs delete mode 100644 src/test/ui/error-codes/E0008.stderr delete mode 100644 src/test/ui/error-codes/E0301.rs delete mode 100644 src/test/ui/error-codes/E0301.stderr delete mode 100644 src/test/ui/error-codes/E0302.rs delete mode 100644 src/test/ui/error-codes/E0302.stderr create mode 100644 src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs create mode 100644 src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-async-await.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-async-await.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr rename src/test/{run-pass => ui}/generator/niche-in-generator.rs (95%) delete mode 100644 src/test/ui/generator/no-arguments-on-generators.stderr rename src/test/ui/generator/{no-arguments-on-generators.rs => no-parameters-on-generators.rs} (90%) create mode 100644 src/test/ui/generator/no-parameters-on-generators.stderr create mode 100644 src/test/ui/hrtb/due-to-where-clause.rs create mode 100644 src/test/ui/hrtb/due-to-where-clause.stderr create mode 100644 src/test/ui/hygiene/auxiliary/codegen-attrs.rs create mode 100644 src/test/ui/hygiene/auxiliary/not-libstd.rs create mode 100644 src/test/ui/hygiene/cross-crate-codegen-attrs.rs create mode 100644 src/test/ui/hygiene/prelude-import-hygiene.rs create mode 100644 src/test/ui/if-ret.stderr create mode 100644 src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs create mode 100644 src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs create mode 100644 src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs create mode 100644 src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr create mode 100644 src/test/ui/in-band-lifetimes/nested-items.rs delete mode 100644 src/test/ui/inaccessible-test-modules.stderr create mode 100644 src/test/ui/include-macros/data.bin create mode 100644 src/test/ui/include-macros/normalization.rs create mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs create mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr create mode 100644 src/test/ui/inference/cannot-infer-async.rs create mode 100644 src/test/ui/inference/cannot-infer-async.stderr create mode 100644 src/test/ui/inference/cannot-infer-closure.rs create mode 100644 src/test/ui/inference/cannot-infer-closure.stderr create mode 100644 src/test/ui/intrinsics-always-extern.rs create mode 100644 src/test/ui/intrinsics-always-extern.stderr create mode 100644 src/test/ui/issues/issue-33575.rs create mode 100644 src/test/ui/issues/issue-33575.stderr create mode 100644 src/test/ui/issues/issue-36836.rs create mode 100644 src/test/ui/issues/issue-36836.stderr delete mode 100644 src/test/ui/issues/issue-44415.stderr create mode 100644 src/test/ui/issues/issue-49934-errors.rs create mode 100644 src/test/ui/issues/issue-49934-errors.stderr create mode 100644 src/test/ui/issues/issue-50301.rs create mode 100644 src/test/ui/issues/issue-63983.rs create mode 100644 src/test/ui/issues/issue-63983.stderr create mode 100644 src/test/ui/issues/issue-64430.rs create mode 100644 src/test/ui/issues/issue-64430.stderr create mode 100644 src/test/ui/issues/issue-64559.rs create mode 100644 src/test/ui/issues/issue-64559.stderr create mode 100644 src/test/ui/issues/issue-64593.rs create mode 100644 src/test/ui/issues/issue-65611.rs create mode 100644 src/test/ui/issues/issue-65611.stderr create mode 100644 src/test/ui/issues/issue-8460-const2.rs create mode 100644 src/test/ui/issues/issue-8460-const2.stderr create mode 100644 src/test/ui/iterators/iter-count-overflow-debug.rs create mode 100644 src/test/ui/iterators/iter-count-overflow-ndebug.rs create mode 100644 src/test/ui/iterators/iter-map-fold-type-length.rs create mode 100644 src/test/ui/iterators/iter-position-overflow-debug.rs create mode 100644 src/test/ui/iterators/iter-position-overflow-ndebug.rs create mode 100644 src/test/ui/json-multiple.polonius.stderr create mode 100644 src/test/ui/json-options.polonius.stderr create mode 100644 src/test/ui/lang-item-missing-generator.rs create mode 100644 src/test/ui/lang-item-missing-generator.stderr create mode 100644 src/test/ui/lint/lint-dead-code-const-and-self.rs create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum.rs create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr create mode 100644 src/test/ui/lint/lint-dead-code-unused-enum.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-enum.stderr create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant-pub.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant.stderr create mode 100644 src/test/ui/lint/opaque-ty-ffi-unsafe.rs create mode 100644 src/test/ui/lint/opaque-ty-ffi-unsafe.stderr create mode 100644 src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs create mode 100644 src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs create mode 100644 src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr create mode 100644 src/test/ui/lint/unreachable-async-fn.rs create mode 100644 src/test/ui/macros/macro-in-fn.rs create mode 100644 src/test/ui/match/non-exhaustive-defined-here.rs create mode 100644 src/test/ui/match/non-exhaustive-defined-here.stderr create mode 100644 src/test/ui/nll/self-assign-ref-mut.rs rename src/test/ui/{non-interger-atomic.rs => non-integer-atomic.rs} (100%) rename src/test/ui/{non-interger-atomic.stderr => non-integer-atomic.stderr} (83%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs create mode 100644 src/test/ui/or-patterns/already-bound-name.rs create mode 100644 src/test/ui/or-patterns/already-bound-name.stderr create mode 100644 src/test/ui/or-patterns/consistent-bindings.rs create mode 100644 src/test/ui/or-patterns/consistent-bindings.stderr create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns.rs create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns.stderr create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.fixed create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.rs create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.stderr create mode 100644 src/test/ui/or-patterns/inconsistent-modes.rs create mode 100644 src/test/ui/or-patterns/inconsistent-modes.stderr create mode 100644 src/test/ui/or-patterns/missing-bindings.rs create mode 100644 src/test/ui/or-patterns/missing-bindings.stderr create mode 100644 src/test/ui/or-patterns/multiple-pattern-typo.rs create mode 100644 src/test/ui/or-patterns/multiple-pattern-typo.stderr rename src/test/ui/{ => or-patterns}/or-pattern-mismatch.rs (100%) rename src/test/ui/{ => or-patterns}/or-pattern-mismatch.stderr (100%) create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail.rs create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass.rs create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr create mode 100644 src/test/ui/or-patterns/remove-leading-vert.fixed create mode 100644 src/test/ui/or-patterns/remove-leading-vert.rs create mode 100644 src/test/ui/or-patterns/remove-leading-vert.stderr create mode 100644 src/test/ui/or-patterns/while-parsing-this-or-pattern.rs create mode 100644 src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr create mode 100644 src/test/ui/parser/assoc-type-in-type-arg.rs create mode 100644 src/test/ui/parser/assoc-type-in-type-arg.stderr create mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs create mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr create mode 100644 src/test/ui/proc-macro/attributes-on-definitions.rs create mode 100644 src/test/ui/proc-macro/attributes-on-definitions.stderr create mode 100644 src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs create mode 100644 src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs create mode 100644 src/test/ui/proc-macro/derive-helper-configured.rs create mode 100644 src/test/ui/proc-macro/gen-macro-rules.rs create mode 100644 src/test/ui/reachable/expr_return_in_macro.rs create mode 100644 src/test/ui/reachable/expr_return_in_macro.stderr create mode 100644 src/test/ui/reify-intrinsic.rs create mode 100644 src/test/ui/reify-intrinsic.stderr create mode 100644 src/test/ui/resolve/block-with-trait-parent.rs delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr delete mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs create mode 100644 src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs create mode 100644 src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr create mode 100644 src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/attr-without-param.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs delete mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs delete mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr delete mode 100644 src/test/ui/rust-unstable-column-gated.rs delete mode 100644 src/test/ui/rust-unstable-column-gated.stderr create mode 100644 src/test/ui/save-analysis/issue-63663.rs create mode 100644 src/test/ui/save-analysis/issue-64659.rs create mode 100644 src/test/ui/save-analysis/issue-65411.rs create mode 100644 src/test/ui/save-analysis/issue-65590.rs create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr create mode 100644 src/test/ui/self/elision/alias-async.rs create mode 100644 src/test/ui/self/elision/assoc-async.rs create mode 100644 src/test/ui/self/elision/lt-alias-async.rs create mode 100644 src/test/ui/self/elision/lt-assoc-async.rs create mode 100644 src/test/ui/self/elision/lt-ref-self-async.nll.stderr create mode 100644 src/test/ui/self/elision/lt-ref-self-async.rs create mode 100644 src/test/ui/self/elision/lt-ref-self-async.stderr create mode 100644 src/test/ui/self/elision/lt-self-async.rs create mode 100644 src/test/ui/self/elision/lt-struct-async.rs create mode 100644 src/test/ui/self/elision/multiple-ref-self-async.rs create mode 100644 src/test/ui/self/elision/ref-alias-async.rs create mode 100644 src/test/ui/self/elision/ref-assoc-async.rs create mode 100644 src/test/ui/self/elision/ref-mut-alias-async.rs create mode 100644 src/test/ui/self/elision/ref-mut-self-async.nll.stderr create mode 100644 src/test/ui/self/elision/ref-mut-self-async.rs create mode 100644 src/test/ui/self/elision/ref-mut-self-async.stderr create mode 100644 src/test/ui/self/elision/ref-mut-struct-async.nll.stderr create mode 100644 src/test/ui/self/elision/ref-mut-struct-async.rs create mode 100644 src/test/ui/self/elision/ref-mut-struct-async.stderr create mode 100644 src/test/ui/self/elision/ref-self-async.nll.stderr create mode 100644 src/test/ui/self/elision/ref-self-async.rs create mode 100644 src/test/ui/self/elision/ref-self-async.stderr create mode 100644 src/test/ui/self/elision/ref-struct-async.nll.stderr create mode 100644 src/test/ui/self/elision/ref-struct-async.rs create mode 100644 src/test/ui/self/elision/ref-struct-async.stderr create mode 100644 src/test/ui/self/elision/self-async.rs create mode 100644 src/test/ui/self/elision/struct-async.rs create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-method.rs create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-method.stderr create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr create mode 100644 src/test/ui/self/self_lifetime-async.rs create mode 100644 src/test/ui/span/type-annotations-needed-expr.rs create mode 100644 src/test/ui/span/type-annotations-needed-expr.stderr create mode 100644 src/test/ui/specialization/issue-63716-parse-async.rs create mode 100644 src/test/ui/std-backtrace.rs create mode 100644 src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr create mode 100644 src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs create mode 100644 src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr create mode 100644 src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr create mode 100644 src/test/ui/suggestions/mismatched-types-numeric-from.rs create mode 100644 src/test/ui/suggestions/mismatched-types-numeric-from.stderr create mode 100644 src/test/ui/suggestions/opaque-type-error.rs create mode 100644 src/test/ui/suggestions/opaque-type-error.stderr create mode 100644 src/test/ui/suggestions/suggest-box.fixed create mode 100644 src/test/ui/suggestions/suggest-box.rs create mode 100644 src/test/ui/suggestions/suggest-box.stderr create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-1.rs create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-1.stderr create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-2.rs create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-2.stderr create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-3.rs create mode 100644 src/test/ui/suggestions/suggest-closure-return-type-3.stderr delete mode 100644 src/test/ui/syntax-extension-minor.stderr create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-2.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-2.stderr create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming.stderr create mode 100644 src/test/ui/terminal-width/whitespace-trimming-2.rs create mode 100644 src/test/ui/terminal-width/whitespace-trimming-2.stderr create mode 100644 src/test/ui/terminal-width/whitespace-trimming.rs create mode 100644 src/test/ui/terminal-width/whitespace-trimming.stderr rename src/test/ui/{test-shadowing => test-attrs}/auxiliary/test_macro.rs (100%) create mode 100644 src/test/ui/test-attrs/decl-macro-test.rs rename src/test/ui/{ => test-attrs}/inaccessible-test-modules.rs (56%) create mode 100644 src/test/ui/test-attrs/inaccessible-test-modules.stderr rename src/test/ui/{ => test-attrs}/test-allow-fail-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-attr-non-associated-functions.rs (100%) rename src/test/ui/{ => test-attrs}/test-attr-non-associated-functions.stderr (100%) rename src/test/ui/{test-shadowing => test-attrs}/test-cant-be-shadowed.rs (100%) rename src/test/ui/{ => test-attrs}/test-fn-signature-verification-for-explicit-return-type.rs (100%) rename src/test/ui/{ => test-attrs}/test-main-not-dead-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-main-not-dead.rs (100%) rename src/test/ui/{ => test-attrs}/test-on-macro.rs (100%) rename src/test/ui/{ => test-attrs}/test-on-macro.stderr (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-buried-main.rs (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-main.rs (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-start.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-fail-good-message.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-panic-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-panic-attr.stderr (100%) rename src/test/ui/{ => test-attrs}/test-vs-cfg-test.rs (100%) rename src/test/ui/{ => test-attrs}/test-warns-dead-code.rs (100%) rename src/test/ui/{ => test-attrs}/test-warns-dead-code.stderr (100%) create mode 100644 src/test/ui/tool-attributes/diagnostic_item.rs create mode 100644 src/test/ui/tool-attributes/diagnostic_item.stderr create mode 100644 src/test/ui/tool-attributes/diagnostic_item2.rs create mode 100644 src/test/ui/tool-attributes/diagnostic_item3.rs rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/underscore-imports.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.stderr (100%) create mode 100644 src/test/ui/underscore-imports/cycle.rs rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/intercrate.rs (100%) create mode 100644 src/test/ui/underscore-imports/shadow.rs create mode 100644 src/test/ui/underscore-imports/shadow.stderr rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.stderr (100%) create mode 100644 src/test/ui/wrapping-int-combinations.rs create mode 100644 src/tools/error_index_generator/build.rs create mode 100644 src/tools/rustc-std-workspace-std/Cargo.toml create mode 100644 src/tools/rustc-std-workspace-std/README.md create mode 100644 src/tools/rustc-std-workspace-std/lib.rs create mode 100644 vendor/backtrace/Cargo.lock delete mode 100644 vendor/backtrace/azure-pipelines.yml delete mode 100644 vendor/backtrace/ci/azure-install-rust.yml delete mode 100644 vendor/backtrace/ci/azure-test-all.yml create mode 100644 vendor/backtrace/src/print.rs create mode 100644 vendor/backtrace/src/print/fuchsia.rs create mode 100644 vendor/backtrace/tests/concurrent-panics.rs create mode 100644 vendor/byteorder/build.rs delete mode 100644 vendor/clap/index.html delete mode 100644 vendor/env_logger-0.5.13/.cargo-checksum.json delete mode 100644 vendor/env_logger-0.5.13/Cargo.toml delete mode 100644 vendor/env_logger-0.5.13/README.md delete mode 100644 vendor/env_logger-0.5.13/examples/custom_default_format.rs delete mode 100644 vendor/env_logger-0.5.13/examples/custom_format.rs delete mode 100644 vendor/env_logger-0.5.13/examples/custom_logger.rs delete mode 100644 vendor/env_logger-0.5.13/examples/default.rs delete mode 100644 vendor/env_logger-0.5.13/examples/direct_logger.rs delete mode 100644 vendor/env_logger-0.5.13/src/filter/mod.rs delete mode 100644 vendor/env_logger-0.5.13/src/filter/regex.rs delete mode 100644 vendor/env_logger-0.5.13/src/filter/string.rs delete mode 100644 vendor/env_logger-0.5.13/src/fmt.rs delete mode 100644 vendor/env_logger-0.5.13/src/lib.rs delete mode 100644 vendor/env_logger-0.5.13/tests/log-in-log.rs delete mode 100644 vendor/env_logger-0.5.13/tests/regexp_filter.rs create mode 100644 vendor/env_logger/CHANGELOG.md create mode 100644 vendor/env_logger/Cargo.lock create mode 100644 vendor/env_logger/examples/filters_from_code.rs delete mode 100644 vendor/getopts/appveyor.yml create mode 100644 vendor/getrandom/build.rs create mode 100644 vendor/getrandom/src/windows_uwp.rs delete mode 100644 vendor/hashbrown-0.4.0/.cargo-checksum.json delete mode 100644 vendor/hashbrown-0.4.0/CHANGELOG.md delete mode 100644 vendor/hashbrown-0.4.0/Cargo.toml delete mode 100644 vendor/hashbrown-0.4.0/README.md delete mode 100644 vendor/hashbrown-0.4.0/benches/bench.rs delete mode 100644 vendor/hashbrown-0.4.0/clippy.toml delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/mod.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/helpers.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/map.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/mod.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/raw.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/set.rs delete mode 100644 vendor/hashbrown-0.4.0/src/external_trait_impls/serde.rs delete mode 100644 vendor/hashbrown-0.4.0/src/fx.rs delete mode 100644 vendor/hashbrown-0.4.0/src/lib.rs delete mode 100644 vendor/hashbrown-0.4.0/src/macros.rs delete mode 100644 vendor/hashbrown-0.4.0/src/map.rs delete mode 100644 vendor/hashbrown-0.4.0/src/raw/bitmask.rs delete mode 100644 vendor/hashbrown-0.4.0/src/raw/generic.rs delete mode 100644 vendor/hashbrown-0.4.0/src/raw/mod.rs delete mode 100644 vendor/hashbrown-0.4.0/src/raw/sse2.rs delete mode 100644 vendor/hashbrown-0.4.0/src/rustc_entry.rs delete mode 100644 vendor/hashbrown-0.4.0/src/scopeguard.rs delete mode 100644 vendor/hashbrown-0.4.0/src/set.rs delete mode 100644 vendor/hashbrown-0.4.0/tests/hasher.rs delete mode 100644 vendor/hashbrown-0.4.0/tests/rayon.rs delete mode 100644 vendor/hashbrown-0.4.0/tests/serde.rs delete mode 100644 vendor/hashbrown-0.4.0/tests/set.rs create mode 100644 vendor/kernel32-sys/.cargo-checksum.json create mode 100644 vendor/kernel32-sys/Cargo.toml create mode 100644 vendor/kernel32-sys/README.md create mode 100644 vendor/kernel32-sys/build.rs create mode 100644 vendor/kernel32-sys/src/lib.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs create mode 100644 vendor/libc/src/vxworks/aarch64.rs create mode 100644 vendor/libc/src/vxworks/arm.rs create mode 100644 vendor/libc/src/vxworks/armv7.rs create mode 100755 vendor/libc/src/vxworks/mod.rs create mode 100644 vendor/libc/src/vxworks/powerpc.rs create mode 100644 vendor/libc/src/vxworks/powerpc64.rs create mode 100644 vendor/libc/src/vxworks/x86.rs create mode 100644 vendor/libc/src/vxworks/x86_64.rs create mode 100644 vendor/lock_api-0.1.3/.cargo-checksum.json create mode 100644 vendor/lock_api-0.1.3/Cargo.toml create mode 100644 vendor/lock_api-0.1.3/src/lib.rs create mode 100644 vendor/lock_api-0.1.3/src/mutex.rs create mode 100644 vendor/lock_api-0.1.3/src/remutex.rs create mode 100644 vendor/lock_api-0.1.3/src/rwlock.rs rename vendor/{env_logger-0.5.13 => lock_api}/LICENSE-APACHE (100%) rename vendor/{quote => lock_api}/LICENSE-MIT (100%) delete mode 100644 vendor/log/appveyor.yml create mode 100644 vendor/log/build.rs create mode 100644 vendor/log/src/kv/error.rs create mode 100644 vendor/log/src/kv/key.rs create mode 100644 vendor/log/src/kv/mod.rs create mode 100644 vendor/log/src/kv/source.rs create mode 100644 vendor/log/src/kv/value/impls.rs create mode 100644 vendor/log/src/kv/value/internal.rs create mode 100644 vendor/log/src/kv/value/mod.rs create mode 100644 vendor/log/src/kv/value/test.rs create mode 100644 vendor/once_cell/.cargo-checksum.json create mode 100644 vendor/once_cell/CHANGELOG.md create mode 100644 vendor/once_cell/Cargo.lock create mode 100644 vendor/once_cell/Cargo.toml rename vendor/{hashbrown-0.4.0 => once_cell}/LICENSE-APACHE (100%) rename vendor/{syn => once_cell}/LICENSE-MIT (100%) create mode 100644 vendor/once_cell/README.md create mode 100644 vendor/once_cell/examples/bench.rs create mode 100644 vendor/once_cell/examples/bench_vs_lazy_static.rs create mode 100644 vendor/once_cell/examples/lazy_static.rs create mode 100644 vendor/once_cell/examples/reentrant_init_deadlocks.rs create mode 100644 vendor/once_cell/examples/regex.rs create mode 100644 vendor/once_cell/src/imp_pl.rs create mode 100644 vendor/once_cell/src/imp_std.rs create mode 100644 vendor/once_cell/src/lib.rs create mode 100644 vendor/once_cell/tests/test.rs delete mode 100644 vendor/owning_ref/.cargo-checksum.json delete mode 100644 vendor/owning_ref/Cargo.toml delete mode 100644 vendor/owning_ref/README.md delete mode 100644 vendor/owning_ref/src/lib.rs create mode 100644 vendor/parking_lot/build.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/cloudabi.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/mod.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/redox.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/sgx.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/wasm.rs create mode 100644 vendor/parking_lot_core/src/thread_parker/wasm_atomic.rs create mode 100644 vendor/polonius-engine/src/output/initialization.rs rename vendor/{proc-macro2 => proc-macro2-0.4.30}/.cargo-checksum.json (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/Cargo.toml (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/LICENSE-APACHE (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/LICENSE-MIT (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/README.md (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/build.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/src/fallback.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/src/lib.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/src/strnom.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/src/wrapper.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/tests/marker.rs (100%) rename vendor/{proc-macro2 => proc-macro2-0.4.30}/tests/test.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/.cargo-checksum.json (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/CONTRIBUTING.md (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/Cargo.toml (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/LICENSE (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/README.md (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/azure-pipelines.yml (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/benches/html_rendering.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/benches/lib.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/build.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/examples/event-filter.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/examples/string-to-string.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/specs/footnotes.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/specs/regression.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/specs/table.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/entities.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/escape.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/html.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/lib.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/linklabel.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/main.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/parse.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/puncttable.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/scanners.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/simd.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/strings.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/src/tree.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/errors.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/html.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/lib.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/footnotes.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/gfm_strikethrough.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/gfm_table.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/gfm_tasklist.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/mod.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/regression.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/spec.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tests/suite/table.rs (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/CommonMark/LICENSE (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/CommonMark/README.google (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/CommonMark/spec.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/GitHub/LICENSE (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/GitHub/gfm_strikethrough.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/GitHub/gfm_table.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/GitHub/gfm_tasklist.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/GitHub/spec.txt (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/xi-editor/LICENSE (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/third_party/xi-editor/crdt.md (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tools/mk_entities.py (100%) rename vendor/{pulldown-cmark => pulldown-cmark-0.5.3}/tools/mk_puncttable.py (100%) rename vendor/{quote => quote-0.6.12}/.cargo-checksum.json (100%) rename vendor/{quote => quote-0.6.12}/Cargo.toml (100%) rename vendor/{quote => quote-0.6.12}/LICENSE-APACHE (100%) rename vendor/{env_logger-0.5.13 => quote-0.6.12}/LICENSE-MIT (95%) rename vendor/{quote => quote-0.6.12}/README.md (100%) rename vendor/{quote => quote-0.6.12}/src/ext.rs (100%) rename vendor/{quote => quote-0.6.12}/src/lib.rs (100%) rename vendor/{quote => quote-0.6.12}/src/runtime.rs (100%) rename vendor/{quote => quote-0.6.12}/src/to_tokens.rs (100%) rename vendor/{quote => quote-0.6.12}/tests/conditional/integer128.rs (100%) rename vendor/{quote => quote-0.6.12}/tests/test.rs (100%) create mode 100644 vendor/strsim/benches/benches.rs rename vendor/{syn => syn-0.15.35}/.cargo-checksum.json (100%) rename vendor/{syn => syn-0.15.35}/Cargo.toml (100%) rename vendor/{syn => syn-0.15.35}/LICENSE-APACHE (100%) rename vendor/{toml-0.4.10 => syn-0.15.35}/LICENSE-MIT (96%) rename vendor/{syn => syn-0.15.35}/README.md (100%) rename vendor/{syn => syn-0.15.35}/build.rs (100%) rename vendor/{syn => syn-0.15.35}/src/attr.rs (100%) rename vendor/{syn => syn-0.15.35}/src/buffer.rs (100%) rename vendor/{syn => syn-0.15.35}/src/custom_keyword.rs (100%) rename vendor/{syn => syn-0.15.35}/src/custom_punctuation.rs (100%) rename vendor/{syn => syn-0.15.35}/src/data.rs (100%) rename vendor/{syn => syn-0.15.35}/src/derive.rs (100%) rename vendor/{syn => syn-0.15.35}/src/error.rs (100%) rename vendor/{syn => syn-0.15.35}/src/export.rs (100%) rename vendor/{syn => syn-0.15.35}/src/expr.rs (100%) rename vendor/{syn => syn-0.15.35}/src/ext.rs (100%) rename vendor/{syn => syn-0.15.35}/src/file.rs (100%) rename vendor/{syn => syn-0.15.35}/src/gen/fold.rs (100%) rename vendor/{syn => syn-0.15.35}/src/gen/visit.rs (100%) rename vendor/{syn => syn-0.15.35}/src/gen/visit_mut.rs (100%) rename vendor/{syn => syn-0.15.35}/src/gen_helper.rs (100%) rename vendor/{syn => syn-0.15.35}/src/generics.rs (100%) rename vendor/{syn => syn-0.15.35}/src/group.rs (100%) rename vendor/{syn => syn-0.15.35}/src/ident.rs (100%) rename vendor/{syn => syn-0.15.35}/src/item.rs (100%) rename vendor/{syn => syn-0.15.35}/src/keyword.rs (100%) rename vendor/{syn => syn-0.15.35}/src/lib.rs (100%) rename vendor/{syn => syn-0.15.35}/src/lifetime.rs (100%) rename vendor/{syn => syn-0.15.35}/src/lit.rs (100%) rename vendor/{syn => syn-0.15.35}/src/lookahead.rs (100%) rename vendor/{syn => syn-0.15.35}/src/mac.rs (100%) rename vendor/{syn => syn-0.15.35}/src/macros.rs (100%) rename vendor/{syn => syn-0.15.35}/src/op.rs (100%) rename vendor/{syn => syn-0.15.35}/src/parse.rs (100%) rename vendor/{syn => syn-0.15.35}/src/parse_macro_input.rs (100%) rename vendor/{syn => syn-0.15.35}/src/parse_quote.rs (100%) rename vendor/{syn => syn-0.15.35}/src/path.rs (100%) rename vendor/{syn => syn-0.15.35}/src/print.rs (100%) rename vendor/{syn => syn-0.15.35}/src/punctuated.rs (100%) rename vendor/{syn => syn-0.15.35}/src/sealed.rs (100%) rename vendor/{syn => syn-0.15.35}/src/span.rs (100%) rename vendor/{syn => syn-0.15.35}/src/spanned.rs (100%) rename vendor/{syn => syn-0.15.35}/src/thread.rs (100%) rename vendor/{syn => syn-0.15.35}/src/token.rs (100%) rename vendor/{syn => syn-0.15.35}/src/tt.rs (100%) rename vendor/{syn => syn-0.15.35}/src/ty.rs (100%) create mode 100644 vendor/term_size/.cargo-checksum.json create mode 100644 vendor/term_size/CHANGELOG.md create mode 100644 vendor/term_size/CONTRIBUTORS.md create mode 100644 vendor/term_size/Cargo.toml rename vendor/{toml-0.4.10 => term_size}/LICENSE-APACHE (100%) rename vendor/{owning_ref/LICENSE => term_size/LICENSE-MIT} (96%) create mode 100644 vendor/term_size/README.md create mode 100644 vendor/term_size/appveyor.yml create mode 100644 vendor/term_size/index.html create mode 100644 vendor/term_size/justfile create mode 100644 vendor/term_size/rustfmt.toml create mode 100644 vendor/term_size/src/lib.rs create mode 100644 vendor/textwrap/src/indentation.rs create mode 100644 vendor/textwrap/src/splitting.rs delete mode 100644 vendor/toml-0.4.10/.cargo-checksum.json delete mode 100644 vendor/toml-0.4.10/Cargo.toml delete mode 100644 vendor/toml-0.4.10/README.md delete mode 100644 vendor/toml-0.4.10/examples/decode.rs delete mode 100644 vendor/toml-0.4.10/examples/enum_external.rs delete mode 100644 vendor/toml-0.4.10/examples/toml2json.rs delete mode 100644 vendor/toml-0.4.10/src/datetime.rs delete mode 100644 vendor/toml-0.4.10/src/de.rs delete mode 100644 vendor/toml-0.4.10/src/lib.rs delete mode 100644 vendor/toml-0.4.10/src/macros.rs delete mode 100644 vendor/toml-0.4.10/src/ser.rs delete mode 100644 vendor/toml-0.4.10/src/spanned.rs delete mode 100644 vendor/toml-0.4.10/src/tokens.rs delete mode 100644 vendor/toml-0.4.10/src/value.rs delete mode 100644 vendor/toml-0.4.10/tests/enum_external_deserialize.rs create mode 100644 vendor/unicode-xid-0.1.0/.cargo-checksum.json create mode 100644 vendor/unicode-xid-0.1.0/COPYRIGHT create mode 100644 vendor/unicode-xid-0.1.0/Cargo.toml create mode 100644 vendor/unicode-xid-0.1.0/LICENSE-APACHE create mode 100644 vendor/unicode-xid-0.1.0/LICENSE-MIT create mode 100644 vendor/unicode-xid-0.1.0/README.md rename vendor/{unicode-xid => unicode-xid-0.1.0}/scripts/unicode.py (100%) create mode 100644 vendor/unicode-xid-0.1.0/src/lib.rs create mode 100644 vendor/unicode-xid-0.1.0/src/tables.rs create mode 100644 vendor/unicode-xid-0.1.0/src/tests.rs create mode 100644 vendor/wasi/.cargo-checksum.json create mode 100644 vendor/wasi/0001-maybe.patch create mode 100644 vendor/wasi/CODE_OF_CONDUCT.md create mode 100644 vendor/wasi/CONTRIBUTING.md create mode 100644 vendor/wasi/Cargo.toml create mode 100644 vendor/wasi/LICENSE-APACHE create mode 100644 vendor/wasi/LICENSE-Apache-2.0_WITH_LLVM-exception rename vendor/{hashbrown-0.4.0 => wasi}/LICENSE-MIT (96%) create mode 100644 vendor/wasi/README.md create mode 100644 vendor/wasi/clip.log create mode 100644 vendor/wasi/old-bitflags.patch create mode 100644 vendor/wasi/rusty-tags.vi create mode 100644 vendor/wasi/src/lib.rs create mode 100644 vendor/wasi/src/wasi_unstable/mod.rs create mode 100644 vendor/wasi/src/wasi_unstable/raw.rs create mode 100644 vendor/winapi-0.2.8/.cargo-checksum.json create mode 100644 vendor/winapi-0.2.8/Cargo.toml create mode 100644 vendor/winapi-0.2.8/LICENSE.md create mode 100644 vendor/winapi-0.2.8/src/activation.rs create mode 100644 vendor/winapi-0.2.8/src/audioclient.rs create mode 100644 vendor/winapi-0.2.8/src/audiosessiontypes.rs create mode 100644 vendor/winapi-0.2.8/src/basetsd.rs create mode 100644 vendor/winapi-0.2.8/src/bcrypt.rs create mode 100644 vendor/winapi-0.2.8/src/cfg.rs create mode 100644 vendor/winapi-0.2.8/src/cfgmgr32.rs create mode 100644 vendor/winapi-0.2.8/src/combaseapi.rs create mode 100644 vendor/winapi-0.2.8/src/commctrl.rs create mode 100644 vendor/winapi-0.2.8/src/commdlg.rs create mode 100644 vendor/winapi-0.2.8/src/corsym.rs create mode 100644 vendor/winapi-0.2.8/src/d2d1.rs create mode 100644 vendor/winapi-0.2.8/src/d2dbasetypes.rs create mode 100644 vendor/winapi-0.2.8/src/d3d10shader.rs create mode 100644 vendor/winapi-0.2.8/src/d3d11.rs create mode 100644 vendor/winapi-0.2.8/src/d3d11shader.rs create mode 100644 vendor/winapi-0.2.8/src/d3d12.rs create mode 100644 vendor/winapi-0.2.8/src/d3d12sdklayers.rs create mode 100644 vendor/winapi-0.2.8/src/d3d12shader.rs create mode 100644 vendor/winapi-0.2.8/src/d3d9.rs create mode 100644 vendor/winapi-0.2.8/src/d3d9caps.rs create mode 100644 vendor/winapi-0.2.8/src/d3d9types.rs create mode 100644 vendor/winapi-0.2.8/src/d3dcommon.rs create mode 100644 vendor/winapi-0.2.8/src/d3dcompiler.rs create mode 100644 vendor/winapi-0.2.8/src/dbghelp.rs create mode 100644 vendor/winapi-0.2.8/src/dcommon.rs create mode 100644 vendor/winapi-0.2.8/src/devpropdef.rs create mode 100644 vendor/winapi-0.2.8/src/docobj.rs create mode 100644 vendor/winapi-0.2.8/src/dpapi.rs create mode 100644 vendor/winapi-0.2.8/src/dsgetdc.rs create mode 100644 vendor/winapi-0.2.8/src/dsound.rs create mode 100644 vendor/winapi-0.2.8/src/dsrole.rs create mode 100644 vendor/winapi-0.2.8/src/dwmapi.rs create mode 100644 vendor/winapi-0.2.8/src/dwrite.rs create mode 100644 vendor/winapi-0.2.8/src/dxgi.rs create mode 100644 vendor/winapi-0.2.8/src/dxgi1_2.rs create mode 100644 vendor/winapi-0.2.8/src/dxgi1_3.rs create mode 100644 vendor/winapi-0.2.8/src/dxgi1_4.rs create mode 100644 vendor/winapi-0.2.8/src/dxgiformat.rs create mode 100644 vendor/winapi-0.2.8/src/dxgitype.rs create mode 100644 vendor/winapi-0.2.8/src/errhandlingapi.rs create mode 100644 vendor/winapi-0.2.8/src/excpt.rs create mode 100644 vendor/winapi-0.2.8/src/fileapi.rs create mode 100644 vendor/winapi-0.2.8/src/gl.rs create mode 100644 vendor/winapi-0.2.8/src/guiddef.rs create mode 100644 vendor/winapi-0.2.8/src/heapapi.rs create mode 100644 vendor/winapi-0.2.8/src/hidclass.rs create mode 100644 vendor/winapi-0.2.8/src/hidpi.rs create mode 100644 vendor/winapi-0.2.8/src/hidsdi.rs create mode 100644 vendor/winapi-0.2.8/src/hidusage.rs create mode 100644 vendor/winapi-0.2.8/src/hstring.rs create mode 100644 vendor/winapi-0.2.8/src/http.rs create mode 100644 vendor/winapi-0.2.8/src/imm.rs create mode 100644 vendor/winapi-0.2.8/src/inaddr.rs create mode 100644 vendor/winapi-0.2.8/src/inspectable.rs create mode 100644 vendor/winapi-0.2.8/src/ksmedia.rs create mode 100644 vendor/winapi-0.2.8/src/lib.rs create mode 100644 vendor/winapi-0.2.8/src/libloaderapi.rs create mode 100644 vendor/winapi-0.2.8/src/lmaccess.rs create mode 100644 vendor/winapi-0.2.8/src/lmcons.rs create mode 100644 vendor/winapi-0.2.8/src/lmdfs.rs create mode 100644 vendor/winapi-0.2.8/src/lmerrlog.rs create mode 100644 vendor/winapi-0.2.8/src/lmjoin.rs create mode 100644 vendor/winapi-0.2.8/src/lsalookup.rs create mode 100644 vendor/winapi-0.2.8/src/macros.rs create mode 100644 vendor/winapi-0.2.8/src/memoryapi.rs create mode 100644 vendor/winapi-0.2.8/src/minschannel.rs create mode 100644 vendor/winapi-0.2.8/src/minwinbase.rs create mode 100644 vendor/winapi-0.2.8/src/minwindef.rs create mode 100644 vendor/winapi-0.2.8/src/mmdeviceapi.rs create mode 100644 vendor/winapi-0.2.8/src/mmreg.rs create mode 100644 vendor/winapi-0.2.8/src/mmsystem.rs create mode 100644 vendor/winapi-0.2.8/src/mscat.rs create mode 100644 vendor/winapi-0.2.8/src/mssip.rs create mode 100644 vendor/winapi-0.2.8/src/nb30.rs create mode 100644 vendor/winapi-0.2.8/src/ncrypt.rs create mode 100644 vendor/winapi-0.2.8/src/ntdef.rs create mode 100644 vendor/winapi-0.2.8/src/ntsecapi.rs create mode 100644 vendor/winapi-0.2.8/src/ntstatus.rs create mode 100644 vendor/winapi-0.2.8/src/oaidl.rs create mode 100644 vendor/winapi-0.2.8/src/objbase.rs create mode 100644 vendor/winapi-0.2.8/src/objidl.rs create mode 100644 vendor/winapi-0.2.8/src/objidlbase.rs create mode 100644 vendor/winapi-0.2.8/src/olectl.rs create mode 100644 vendor/winapi-0.2.8/src/pdh.rs create mode 100644 vendor/winapi-0.2.8/src/playsoundapi.rs create mode 100644 vendor/winapi-0.2.8/src/processsnapshot.rs create mode 100644 vendor/winapi-0.2.8/src/processthreadsapi.rs create mode 100644 vendor/winapi-0.2.8/src/propidl.rs create mode 100644 vendor/winapi-0.2.8/src/propsys.rs create mode 100644 vendor/winapi-0.2.8/src/prsht.rs create mode 100644 vendor/winapi-0.2.8/src/psapi.rs create mode 100644 vendor/winapi-0.2.8/src/qos.rs create mode 100644 vendor/winapi-0.2.8/src/reason.rs create mode 100644 vendor/winapi-0.2.8/src/restrictederrorinfo.rs create mode 100644 vendor/winapi-0.2.8/src/roapi.rs create mode 100644 vendor/winapi-0.2.8/src/roerrorapi.rs create mode 100644 vendor/winapi-0.2.8/src/rpc.rs create mode 100644 vendor/winapi-0.2.8/src/rpcdce.rs create mode 100644 vendor/winapi-0.2.8/src/sapi.rs create mode 100644 vendor/winapi-0.2.8/src/schannel.rs create mode 100644 vendor/winapi-0.2.8/src/servprov.rs create mode 100644 vendor/winapi-0.2.8/src/setupapi.rs create mode 100644 vendor/winapi-0.2.8/src/shellapi.rs create mode 100644 vendor/winapi-0.2.8/src/shellscalingapi.rs create mode 100644 vendor/winapi-0.2.8/src/shlguid.rs create mode 100644 vendor/winapi-0.2.8/src/shlobj.rs create mode 100644 vendor/winapi-0.2.8/src/shobjidl.rs create mode 100644 vendor/winapi-0.2.8/src/shtypes.rs create mode 100644 vendor/winapi-0.2.8/src/spapidef.rs create mode 100644 vendor/winapi-0.2.8/src/sql.rs create mode 100644 vendor/winapi-0.2.8/src/sqltypes.rs create mode 100644 vendor/winapi-0.2.8/src/sspi.rs create mode 100644 vendor/winapi-0.2.8/src/strmif.rs create mode 100644 vendor/winapi-0.2.8/src/subauth.rs create mode 100644 vendor/winapi-0.2.8/src/synchapi.rs create mode 100644 vendor/winapi-0.2.8/src/sysinfoapi.rs create mode 100644 vendor/winapi-0.2.8/src/threadpoolapi.rs create mode 100644 vendor/winapi-0.2.8/src/timezoneapi.rs create mode 100644 vendor/winapi-0.2.8/src/tlhelp32.rs create mode 100644 vendor/winapi-0.2.8/src/unknwnbase.rs create mode 100644 vendor/winapi-0.2.8/src/urlhist.rs create mode 100644 vendor/winapi-0.2.8/src/urlmon.rs create mode 100644 vendor/winapi-0.2.8/src/usb.rs create mode 100644 vendor/winapi-0.2.8/src/usbspec.rs create mode 100644 vendor/winapi-0.2.8/src/usp10.rs create mode 100644 vendor/winapi-0.2.8/src/vadefs.rs create mode 100644 vendor/winapi-0.2.8/src/vsbackup.rs create mode 100644 vendor/winapi-0.2.8/src/vss.rs create mode 100644 vendor/winapi-0.2.8/src/vsserror.rs create mode 100644 vendor/winapi-0.2.8/src/vswriter.rs create mode 100644 vendor/winapi-0.2.8/src/werapi.rs create mode 100644 vendor/winapi-0.2.8/src/winbase.rs create mode 100644 vendor/winapi-0.2.8/src/wincon.rs create mode 100644 vendor/winapi-0.2.8/src/wincred.rs create mode 100644 vendor/winapi-0.2.8/src/wincrypt.rs create mode 100644 vendor/winapi-0.2.8/src/windef.rs create mode 100644 vendor/winapi-0.2.8/src/windowscodecs.rs create mode 100644 vendor/winapi-0.2.8/src/windowsx.rs create mode 100644 vendor/winapi-0.2.8/src/winerror.rs create mode 100644 vendor/winapi-0.2.8/src/winevt.rs create mode 100644 vendor/winapi-0.2.8/src/wingdi.rs create mode 100644 vendor/winapi-0.2.8/src/winhttp.rs create mode 100644 vendor/winapi-0.2.8/src/winioctl.rs create mode 100644 vendor/winapi-0.2.8/src/winnetwk.rs create mode 100644 vendor/winapi-0.2.8/src/winnls.rs create mode 100644 vendor/winapi-0.2.8/src/winnt.rs create mode 100644 vendor/winapi-0.2.8/src/winreg.rs create mode 100644 vendor/winapi-0.2.8/src/winscard.rs create mode 100644 vendor/winapi-0.2.8/src/winsmcrd.rs create mode 100644 vendor/winapi-0.2.8/src/winsock2.rs create mode 100644 vendor/winapi-0.2.8/src/winspool.rs create mode 100644 vendor/winapi-0.2.8/src/winstring.rs create mode 100644 vendor/winapi-0.2.8/src/winsvc.rs create mode 100644 vendor/winapi-0.2.8/src/winusb.rs create mode 100644 vendor/winapi-0.2.8/src/winusbio.rs create mode 100644 vendor/winapi-0.2.8/src/winuser.rs create mode 100644 vendor/winapi-0.2.8/src/ws2def.rs create mode 100644 vendor/winapi-0.2.8/src/ws2ipdef.rs create mode 100644 vendor/winapi-0.2.8/src/ws2spi.rs create mode 100644 vendor/winapi-0.2.8/src/ws2tcpip.rs create mode 100644 vendor/winapi-0.2.8/src/wtypes.rs create mode 100644 vendor/winapi-0.2.8/src/wtypesbase.rs create mode 100644 vendor/winapi-0.2.8/src/xinput.rs create mode 100644 vendor/winapi-build/.cargo-checksum.json create mode 100644 vendor/winapi-build/Cargo.toml create mode 100644 vendor/winapi-build/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ab6731e4d4..5bc1938fee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,194 +4,212 @@ name = "adler32" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" [[package]] name = "aho-corasick" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins", + "core", + "rand 0.7.0", + "rand_xorshift 0.2.0", ] [[package]] name = "ammonia" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384d704f242a0a9faf793fff775a0be6ab9aa27edabffa097331d73779142520" dependencies = [ - "html5ever 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever", + "lazy_static 1.3.0", + "maplit", + "matches", + "tendril", + "url 1.7.2", ] [[package]] name = "annotate-snippets" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", ] [[package]] name = "arc-swap" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" [[package]] name = "arena" version = "0.0.0" dependencies = [ - "rustc_data_structures 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_data_structures", + "smallvec", ] [[package]] name = "argon2rs" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc", + "scoped_threadpool", ] [[package]] name = "arrayref" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" [[package]] name = "arrayvec" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" dependencies = [ - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop", ] [[package]] name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "termion", + "winapi 0.3.6", ] [[package]] name = "backtrace" -version = "0.3.34" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" dependencies = [ - "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "backtrace-sys", + "cfg-if", + "compiler_builtins", + "libc", + "rustc-demangle", + "rustc-std-workspace-core", ] [[package]] name = "backtrace-sys" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "cc", + "compiler_builtins", + "libc", + "rustc-std-workspace-core", ] [[package]] name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "bitflags" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" [[package]] name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "byte-tools", ] [[package]] name = "bootstrap" version = "0.0.0" dependencies = [ - "build_helper 0.1.0", - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "build_helper", + "cc", + "cmake", + "filetime", + "getopts", + "lazy_static 1.3.0", + "libc", + "num_cpus", + "petgraph", + "pretty_assertions", + "serde", + "serde_json", + "time", + "toml", ] [[package]] name = "bstr" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "853b090ce0f45d0265902666bf88039ea3da825e33796716c511a1ec9c170036" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "toml", ] [[package]] name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" [[package]] name = "build_helper" @@ -201,118 +219,144 @@ version = "0.1.0" name = "byte-tools" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" [[package]] name = "bytecount" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" dependencies = [ - "packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "packed_simd", ] [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" [[package]] name = "bytes" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "either", + "iovec", ] [[package]] name = "bytesize" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" [[package]] name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "ppv-lite86", ] [[package]] name = "cargo" -version = "0.39.0" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo-test-macro 0.1.0", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.27.0", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0", - "rustfix 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +version = "0.40.0" +dependencies = [ + "atty", + "bytesize", + "cargo-test-macro", + "cargo-test-support", + "clap", + "core-foundation", + "crates-io", + "crossbeam-utils 0.6.5", + "crypto-hash", + "curl", + "curl-sys", + "env_logger", + "failure", + "filetime", + "flate2", + "fs2", + "fwdansi", + "git2", + "git2-curl", + "glob", + "hex 0.4.0", + "home", + "humantime", + "ignore", + "im-rc", + "jobserver", + "lazy_static 1.3.0", + "lazycell", + "libc", + "libgit2-sys", + "log", + "memchr", + "miow 0.3.3", + "num_cpus", + "opener", + "openssl", + "percent-encoding 2.0.0", + "pretty_env_logger", + "remove_dir_all", + "rustc-workspace-hack", + "rustfix", + "same-file", + "semver", + "serde", + "serde_ignored", + "serde_json", + "shell-escape", + "strip-ansi-escapes", + "tar", + "tempfile", + "termcolor", + "toml", + "unicode-width", + "url 2.1.0", + "walkdir", + "winapi 0.3.6", ] [[package]] name = "cargo-test-macro" version = "0.1.0" +[[package]] +name = "cargo-test-support" +version = "0.1.0" +dependencies = [ + "cargo", + "cargo-test-macro", + "filetime", + "flate2", + "git2", + "glob", + "lazy_static 1.3.0", + "remove_dir_all", + "serde_json", + "tar", + "url 2.1.0", +] + [[package]] name = "cargo_metadata" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "929766d993a2fde7a0ae962ee82429069cd7b68839cd9375b98efd719df65d3a" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "semver", + "serde", + "serde_derive", + "serde_json", ] [[package]] @@ -323,73 +367,79 @@ version = "0.1.0" name = "cc" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" [[package]] name = "cfg-if" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89431bba4e6b7092fb5fcd00a6f6ca596c55cc26b2f1e6dcdd08a1f4933f66b2" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "compiler_builtins", + "rustc-std-workspace-core", ] [[package]] name = "chalk-engine" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a" dependencies = [ - "chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chalk-macros", + "rustc-hash", ] [[package]] name = "chalk-macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11", ] [[package]] name = "chrono" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits", + "time", ] [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", + "yaml-rust", ] [[package]] name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.212", - "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0", + "cargo_metadata", + "clippy-mini-macro-test", + "clippy_lints", + "compiletest_rs", + "derive-new", + "lazy_static 1.3.0", + "regex", + "rustc-workspace-hack", "rustc_tools_util 0.2.0", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", + "serde", ] [[package]] @@ -400,703 +450,766 @@ version = "0.2.0" name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata", + "if_chain", + "itertools 0.8.0", + "lazy_static 1.3.0", + "matches", + "pulldown-cmark 0.6.0", + "quine-mc_cluskey", + "regex-syntax", + "semver", + "serde", + "smallvec", + "toml", + "unicode-normalization", + "url 2.1.0", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "cmake" version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "colored" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11", ] [[package]] name = "commoncrypto" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" dependencies = [ - "commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "commoncrypto-sys", ] [[package]] name = "commoncrypto-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "compiler_builtins" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1c086a06d6f52f9c0d50cacdc021bfb6034ddeec9fb7e62f099f13f65472f4" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "cc", + "rustc-std-workspace-core", ] [[package]] name = "compiletest" version = "0.0.0" dependencies = [ - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfix 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "diff", + "env_logger", + "getopts", + "lazy_static 1.3.0", + "libc", + "log", + "miow 0.3.3", + "regex", + "rustfix", + "serde", + "serde_json", + "walkdir", + "winapi 0.3.6", ] [[package]] name = "compiletest_rs" version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" dependencies = [ - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfix 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "diff", + "filetime", + "getopts", + "libc", + "log", + "miow 0.3.3", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tempfile", + "tester", + "winapi 0.3.6", ] [[package]] name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" [[package]] name = "core" version = "0.0.0" dependencies = [ - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0", ] [[package]] name = "core-foundation" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "crates-io" -version = "0.27.0" +version = "0.28.0" dependencies = [ - "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curl", + "failure", + "percent-encoding 2.0.0", + "serde", + "serde_derive", + "serde_json", + "url 2.1.0", ] [[package]] name = "crc" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "build_const", ] [[package]] name = "crc32fast" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "crossbeam-channel" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", + "smallvec", ] [[package]] name = "crossbeam-deque" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.3.1", + "crossbeam-utils 0.2.2", ] [[package]] name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2", + "crossbeam-utils 0.6.5", ] [[package]] name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "cfg-if", + "crossbeam-utils 0.2.2", + "lazy_static 1.3.0", + "memoffset 0.2.1", + "nodrop", + "scopeguard 0.3.3", ] [[package]] name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "cfg-if", + "crossbeam-utils 0.6.5", + "lazy_static 1.3.0", + "memoffset 0.5.1", + "scopeguard 1.0.0", ] [[package]] name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", ] [[package]] name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "lazy_static 1.3.0", ] [[package]] name = "crypto-hash" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" dependencies = [ - "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "commoncrypto", + "hex 0.3.2", + "openssl", + "winapi 0.3.6", ] [[package]] name = "curl" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a85f2f95f2bd277d316d1aa8a477687ab4a6942258c7db7c89c187534669979c" dependencies = [ - "curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys", + "kernel32-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi 0.2.8", ] [[package]] name = "curl-sys" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d91a0052d5b982887d8e829bee0faffc7218ea3c6ebd3d6c2c8f678a93c9a42" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi 0.3.6", ] [[package]] name = "darling" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9158d690bc62a3a57c3e45b85e4d50de2008b39345592c64efd79345c7e24be0" dependencies = [ - "darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "darling_macro 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a368589465391e127e10c9e3a08efc8df66fd49b87dc8524c764bbe7f2ef82" dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv", + "ident_case", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "darling_macro" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244e8987bd4e174385240cde20a3657f607fb0797563c28255c353b5819a07b1" dependencies = [ - "darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_core", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "datafrog" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "derive-new" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "derive_more" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.12", + "rustc_version", + "syn 0.15.35", ] [[package]] name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" [[package]] name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "digest" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array", ] [[package]] name = "directories" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ccc83e029c3cebb4c8155c644d34e3a070ccdb4ff90d369c74cd73f7cb3c984" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys", ] [[package]] name = "dirs" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys", ] [[package]] name = "dirs-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_users", + "winapi 0.3.6", ] [[package]] name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "compiler_builtins", + "libc", + "rustc-std-workspace-core", ] [[package]] name = "dtoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" [[package]] name = "either" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" [[package]] name = "elasticlunr-rs" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "regex", + "serde", + "serde_derive", + "serde_json", + "strum", + "strum_macros", ] [[package]] name = "ena" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log", ] [[package]] name = "encoding_rs" version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "env_logger" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "humantime", + "log", + "regex", + "termcolor", ] [[package]] name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" dependencies = [ - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", ] [[package]] name = "error_index_generator" version = "0.0.0" dependencies = [ - "rustdoc 0.0.0", + "rustdoc", + "walkdir", ] [[package]] name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" dependencies = [ - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", + "synstructure", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", ] [[package]] name = "fixedbitset" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" [[package]] name = "flate2" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" dependencies = [ - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast", + "libc", + "libz-sys", + "miniz-sys", + "miniz_oxide_c_api", ] [[package]] name = "fmt_macros" version = "0.0.0" dependencies = [ - "syntax_pos 0.0.0", + "rustc_lexer", + "syntax_pos", ] [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8cbee5e872cf7db61a999a041f9bc4706ca7bf7df4cb914f53fabb1c1bc550" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "compiler_builtins", + "rustc-std-workspace-core", ] [[package]] name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.3.6", ] [[package]] name = "fs_extra" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" [[package]] name = "fst" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futf" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" dependencies = [ - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mac", + "new_debug_unreachable", ] [[package]] name = "futures" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" [[package]] name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "num_cpus", ] [[package]] name = "fwdansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", + "termcolor", ] [[package]] name = "generic-array" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "getopts" -version = "0.2.19" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core", + "rustc-std-workspace-std", + "unicode-width", ] [[package]] name = "getrandom" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "git2" -version = "0.9.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327d698f86a7ebdfeb86a4238ccdb004828939d3a3555b6ead679541d14e36c0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url 2.1.0", ] [[package]] name = "git2-curl" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6527e480187ce19aaf4fa6acfb7657b25628ce31cb8ffabdfca3bf731524c5" dependencies = [ - "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curl", + "git2", + "log", + "url 2.1.0", ] [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", ] [[package]] @@ -1107,402 +1220,523 @@ version = "0.0.0" name = "h2" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "bytes", + "fnv", + "futures", + "http", + "indexmap", + "log", + "slab", + "string", + "tokio-io", ] [[package]] name = "handlebars" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" dependencies = [ - "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-alloc 1.0.0", - "rustc-std-workspace-core 1.0.0", + "hashbrown", + "lazy_static 1.3.0", + "log", + "pest", + "pest_derive", + "quick-error", + "regex", + "serde", + "serde_json", ] [[package]] name = "hashbrown" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "serde", ] [[package]] name = "heck" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" dependencies = [ - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" + +[[package]] +name = "hex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" [[package]] name = "home" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" dependencies = [ - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0", + "winapi 0.3.6", ] [[package]] name = "html5ever" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "markup5ever 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "mac", + "markup5ever", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "http" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "fnv", + "itoa", ] [[package]] name = "http-body" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "http", + "tokio-buf", ] [[package]] name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "humantime" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error", ] [[package]] name = "hyper" version = "0.12.31" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "6481fff8269772d4463253ca83c788104a7305cb3fb9136bc651a6211e46e03f" +dependencies = [ + "bytes", + "futures", + "futures-cpupool", + "h2", + "http", + "http-body", + "httparse", + "iovec", + "itoa", + "log", + "net2", + "rustc_version", + "time", + "tokio", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want", ] [[package]] name = "hyper-tls" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "hyper", + "native-tls", + "tokio-io", ] [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "if_chain" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d" [[package]] name = "ignore" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" dependencies = [ - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "globset", + "lazy_static 1.3.0", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", ] [[package]] name = "im-rc" version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", + "sized-chunks", + "typenum", ] [[package]] name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" [[package]] name = "installer" version = "0.0.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "failure", + "flate2", + "lazy_static 1.3.0", + "num_cpus", + "rayon", + "remove_dir_all", + "tar", + "walkdir", + "winapi 0.3.6", + "xz2", ] [[package]] name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.2.8", ] [[package]] name = "is-match" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" [[package]] name = "itertools" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" [[package]] name = "jemalloc-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "fs_extra", + "libc", ] [[package]] name = "jobserver" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "log", + "rand 0.7.0", ] [[package]] name = "json" version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" + +[[package]] +name = "jsonrpc-client-transports" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39577db48b004cffb4c5b8e5c9b993c177c52599ecbee88711e815acf65144db" +dependencies = [ + "failure", + "futures", + "jsonrpc-core", + "jsonrpc-pubsub", + "jsonrpc-server-utils", + "log", + "parity-tokio-ipc", + "serde", + "serde_json", + "tokio", + "url 1.7.2", +] [[package]] name = "jsonrpc-core" -version = "12.0.0" +version = "13.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd42951eb35079520ee29b7efbac654d85821b397ef88c8151600ef7e2d00217" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "jsonrpc-core-client" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f047c10738edee7c3c6acf5241a0ce33df32ef9230c1a7fb03e4a77ee72c992f" +dependencies = [ + "jsonrpc-client-transports", +] + +[[package]] +name = "jsonrpc-derive" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f9149f785deaae92a4c834a9a1a83a4313b8cfedccf15362cd4cf039a64501" +dependencies = [ + "proc-macro-crate", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", +] + +[[package]] +name = "jsonrpc-ipc-server" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256c5e4292c17b4c2ecdf542299dc8e9d6b3939c075c54825570ad9317fe5751" +dependencies = [ + "jsonrpc-core", + "jsonrpc-server-utils", + "log", + "parity-tokio-ipc", + "parking_lot 0.9.0", + "tokio-service", +] + +[[package]] +name = "jsonrpc-pubsub" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c08b444cc0ed70263798834343d0ac875e664257df8079160f23ac1ea79446" +dependencies = [ + "jsonrpc-core", + "log", + "parking_lot 0.9.0", + "serde", +] + +[[package]] +name = "jsonrpc-server-utils" +version = "13.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44561bfdd31401bad790527f1e951dde144f2341ddc3e1b859d32945e1a34eff" +dependencies = [ + "bytes", + "globset", + "jsonrpc-core", + "lazy_static 1.3.0", + "log", + "num_cpus", + "tokio", + "tokio-codec", + "unicase 2.5.1", ] [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "lazy_static" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" [[package]] name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" [[package]] name = "lazycell" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" dependencies = [ - "rustc-std-workspace-core 1.0.0", + "rustc-std-workspace-core", ] [[package]] name = "libflate" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90c6f86f4b0caa347206f916f8b687b51d77c6ef8ff18d52dd007491fd580529" dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", + "byteorder", + "crc32fast", + "rle-decode-fast", + "take_mut", ] [[package]] name = "libgit2-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2078aec6f4b16d1b89f6a72e4f6eb1e75ffa85312023291e89c6d3087bc8fb" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", ] [[package]] name = "libnghttp2-sys" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "libssh2-sys" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", ] [[package]] name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] @@ -1513,916 +1747,1109 @@ version = "0.1.0" name = "lock_api" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" +dependencies = [ + "owning_ref", + "scopeguard 0.3.3", +] + +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0", ] [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "log_settings" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", ] [[package]] name = "lsp-codec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "169d737ad89cf8ddd82d1804d9122f54568c49377665157277cc90d747b1d31a" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "serde_json", + "tokio-codec", ] [[package]] name = "lsp-types" -version = "0.57.2" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3edefcd66dde1f7f1df706f46520a3c93adc5ca4bc5747da6621195e894efd" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "serde", + "serde_json", + "serde_repr", + "url 2.1.0", ] [[package]] name = "lzma-sys" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b5c59c57cc4d39e7999f50431aa312ea78af7c93b23fbb0c3567bd672e7f35" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", ] [[package]] name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "macro-utils" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510" [[package]] name = "maplit" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" [[package]] name = "markup5ever" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "phf", + "phf_codegen", + "serde", + "serde_derive", + "serde_json", + "string_cache", + "string_cache_codegen", + "tendril", ] [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mdbook" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ammonia 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "949bb2acb2cff9fa5c375cf9c43e70b3dba0a974d9fe01c31285d7a84d2a0fa2" +dependencies = [ + "ammonia", + "chrono", + "clap", + "elasticlunr-rs", + "env_logger", + "error-chain", + "handlebars", + "itertools 0.8.0", + "lazy_static 1.3.0", + "log", + "memchr", + "open", + "pulldown-cmark 0.5.3", + "regex", + "serde", + "serde_derive", + "serde_json", + "shlex", + "tempfile", + "toml", + "toml-query", ] [[package]] name = "mdbook-linkcheck" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10" dependencies = [ - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger", + "failure", + "log", + "mdbook", + "memchr", + "pulldown-cmark 0.5.3", + "rayon", + "regex", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "structopt 0.2.18", + "url 1.7.2", ] [[package]] name = "measureme" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d09de7dafa3aa334bc806447c7e4de69419723312f4b88b80b561dea66601ce8" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "memmap", + "rustc-hash", ] [[package]] name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" [[package]] name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.3.6", ] [[package]] name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" [[package]] name = "memoffset" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "mime" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" dependencies = [ - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1", ] [[package]] name = "mime_guess" version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" dependencies = [ - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mime", + "phf", + "phf_codegen", + "unicase 1.4.2", ] [[package]] name = "minifier" version = "0.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332" dependencies = [ - "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "macro-utils", ] [[package]] name = "miniz-sys" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "miniz_oxide" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", ] [[package]] name = "miniz_oxide_c_api" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "crc", + "libc", + "miniz_oxide", ] [[package]] name = "mio" version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "lazycell", + "libc", + "log", + "miow 0.2.1", + "net2", + "slab", + "winapi 0.2.8", ] [[package]] name = "mio-named-pipes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "mio", + "miow 0.3.3", + "winapi 0.3.6", ] [[package]] name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec", + "libc", + "mio", ] [[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] name = "miow" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" dependencies = [ - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2", + "winapi 0.3.6", ] [[package]] name = "miri" version = "0.1.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "directories 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "cargo_metadata", + "colored", + "compiletest_rs", + "directories", + "env_logger", + "getrandom", + "hex 0.3.2", + "log", + "num-traits", + "rand 0.7.0", + "rustc-workspace-hack", + "rustc_version", + "shell-escape", + "vergen", ] [[package]] name = "native-tls" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "winapi 0.3.6", ] [[package]] name = "new_debug_unreachable" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" [[package]] name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num-derive" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" [[package]] name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "num-traits" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" [[package]] name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] +[[package]] +name = "once_cell" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0" + [[package]] name = "open" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" [[package]] name = "opener" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", ] [[package]] name = "openssl" version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "cfg-if", + "foreign-types", + "lazy_static 1.3.0", + "libc", + "openssl-sys", ] [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-src" -version = "111.3.0+1.1.1c" +version = "111.6.0+1.1.1d" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "openssl-sys" version = "0.9.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "openssl-src", + "pkg-config", + "rustc_version", + "vcpkg", ] [[package]] name = "ordermap" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" [[package]] name = "ordslice" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" [[package]] name = "owning_ref" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" dependencies = [ - "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait", ] [[package]] name = "packed_simd" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins", + "core", + "libc", ] [[package]] name = "panic_unwind" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "unwind 0.0.0", + "alloc", + "cfg-if", + "compiler_builtins", + "core", + "libc", + "unwind", +] + +[[package]] +name = "parity-tokio-ipc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8281bf4f1d6429573f89589bf68d89451c46750977a8264f8ea3edbabeba7947" +dependencies = [ + "bytes", + "futures", + "log", + "mio-named-pipes", + "miow 0.3.3", + "rand 0.7.0", + "tokio", + "tokio-named-pipes", + "tokio-uds", + "winapi 0.3.6", ] [[package]] name = "parking_lot" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +dependencies = [ + "lock_api 0.1.3", + "parking_lot_core 0.4.0", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.1", + "parking_lot_core 0.6.2", + "rustc_version", ] [[package]] name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +dependencies = [ + "libc", + "rand 0.6.1", + "rustc_version", + "smallvec", + "winapi 0.3.6", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec", + "winapi 0.3.6", ] [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" [[package]] name = "pest" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3" dependencies = [ - "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-trie", ] [[package]] name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" dependencies = [ - "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_generator", ] [[package]] name = "pest_generator" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" dependencies = [ - "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_meta", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "pest_meta" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e" dependencies = [ - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit", + "pest", + "sha-1", ] [[package]] name = "petgraph" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" dependencies = [ - "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fixedbitset", + "ordermap", ] [[package]] name = "phf" version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared", ] [[package]] name = "phf_codegen" version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator", + "phf_shared", ] [[package]] name = "phf_generator" version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared", + "rand 0.6.1", ] [[package]] name = "phf_shared" version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher", + "unicase 1.4.2", ] [[package]] name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" [[package]] name = "polonius-engine" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe" dependencies = [ - "datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "datafrog", + "log", + "rustc-hash", ] [[package]] name = "ppv-lite86" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "pretty_assertions" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "difference", ] [[package]] name = "pretty_env_logger" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono", + "env_logger", + "log", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +dependencies = [ + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.5", ] [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" +dependencies = [ + "unicode-xid 0.2.0", ] [[package]] name = "proc_macro" version = "0.0.0" +dependencies = [ + "std", +] [[package]] name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "cc", + "compiler_builtins", + "core", ] [[package]] name = "pulldown-cmark" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77043da1282374688ee212dc44b3f37ff929431de9c9adc3053bd3cee5630357" +dependencies = [ + "bitflags", + "getopts", + "memchr", + "unicase 2.5.1", +] + +[[package]] +name = "pulldown-cmark" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b0ad0d4c1702965ee6bb5b4ff5e71f83850b497d497e9444302987bf9e26a4" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "getopts", + "memchr", + "unicase 2.5.1", ] [[package]] name = "punycode" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3" [[package]] name = "quick-error" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" [[package]] name = "quine-mc_cluskey" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" [[package]] name = "quote" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +dependencies = [ + "proc-macro2 1.0.3", ] [[package]] name = "racer" -version = "2.1.25" +version = "2.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "clap", + "derive_more", + "env_logger", + "humantime", + "lazy_static 1.3.0", + "log", + "rls-span", + "rustc-ap-syntax", ] [[package]] name = "rand" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-zircon", + "libc", + "rand_chacha 0.1.0", + "rand_core 0.3.0", + "rand_hc 0.1.0", + "rand_isaac", + "rand_pcg", + "rand_xorshift 0.1.0", + "rustc_version", + "winapi 0.3.6", ] [[package]] name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha 0.2.1", + "rand_core 0.5.0", + "rand_hc 0.2.0", ] [[package]] name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", + "rustc_version", ] [[package]] name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha", + "rand_core 0.5.0", ] [[package]] name = "rand_core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" [[package]] name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" [[package]] name = "rand_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0", ] [[package]] name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", ] [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.0", + "rdrand", + "winapi 0.3.6", ] [[package]] name = "rand_pcg" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", + "rustc_version", ] [[package]] name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", ] [[package]] name = "rand_xorshift" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0", ] [[package]] name = "rayon" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3", + "crossbeam-queue", + "crossbeam-utils 0.6.5", + "lazy_static 1.3.0", + "num_cpus", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0", ] [[package]] name = "redox_syscall" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" [[package]] name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" dependencies = [ - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall", ] [[package]] name = "redox_users" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "argon2rs", + "failure", + "rand_os", + "redox_syscall", ] [[package]] name = "regex" version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", + "utf8-ranges", ] [[package]] name = "regex-syntax" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util", ] [[package]] @@ -2437,526 +2864,579 @@ version = "0.1.0" name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", ] [[package]] name = "reqwest" version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "e542d9f077c126af32536b6aacc75bb7325400eab8cd0743543be5d91660780d" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures", + "http", + "hyper", + "hyper-tls", + "libflate", + "log", + "mime", + "mime_guess", + "native-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-threadpool", + "tokio-timer", + "url 1.7.2", + "uuid", ] [[package]] name = "rle-decode-fast" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" [[package]] name = "rls" -version = "1.38.0" -dependencies = [ - "cargo 0.39.0", - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.212", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.57.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-rustc 0.6.0", - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0", +version = "1.39.0" +dependencies = [ + "cargo", + "cargo_metadata", + "clippy_lints", + "crossbeam-channel", + "difference", + "env_logger", + "failure", + "futures", + "heck", + "home", + "itertools 0.8.0", + "jsonrpc-core", + "lazy_static 1.3.0", + "log", + "lsp-codec", + "lsp-types", + "num_cpus", + "ordslice", + "racer", + "rand 0.6.1", + "rayon", + "regex", + "rls-analysis", + "rls-data", + "rls-ipc", + "rls-rustc", + "rls-span", + "rls-vfs", + "rustc-serialize", + "rustc-workspace-hack", "rustc_tools_util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 1.4.4", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly", + "serde", + "serde_derive", + "serde_ignored", + "serde_json", + "tempfile", + "tokio", + "tokio-process", + "tokio-timer", + "toml", + "url 2.1.0", + "walkdir", ] [[package]] name = "rls-analysis" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0d208ad66717501222c74b42d9e823a7612592e85ed78b04074c8f58c0be0a" dependencies = [ - "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new", + "fst", + "itertools 0.7.8", + "json", + "log", + "rls-data", + "rls-span", + "serde", + "serde_json", ] [[package]] name = "rls-data" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c72ea97e045be5f6290bb157ebdc5ee9f2b093831ff72adfaf59025cf5c491" +dependencies = [ + "rls-span", + "serde", +] + +[[package]] +name = "rls-ipc" +version = "0.1.0" dependencies = [ - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "jsonrpc-ipc-server", + "rls-data", + "serde", ] [[package]] name = "rls-rustc" version = "0.6.0" +dependencies = [ + "clippy_lints", + "env_logger", + "failure", + "futures", + "log", + "rand 0.6.1", + "rls-data", + "rls-ipc", + "serde", + "tokio", +] [[package]] name = "rls-span" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1cb4694410d8d2ce43ccff3682f1c782158a018d5a9a92185675677f7533eb3" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "rls-vfs" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce4b57b25b4330ed5ec14028fc02141e083ddafda327e7eb598dc0569c8c83c9" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "rls-span", ] [[package]] name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook-linkcheck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "failure", + "mdbook", + "mdbook-linkcheck", ] [[package]] name = "rustc" version = "0.0.0" dependencies = [ - "arena 0.0.0", - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fmt_macros 0.0.0", - "graphviz 0.0.0", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "measureme 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_apfloat 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_fs_util 0.0.0", - "rustc_macros 0.1.0", - "rustc_target 0.0.0", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "arena", + "backtrace", + "bitflags", + "byteorder", + "chalk-engine", + "fmt_macros", + "graphviz", + "jobserver", + "log", + "measureme", + "num_cpus", + "parking_lot 0.9.0", + "polonius-engine", + "rustc-rayon", + "rustc-rayon-core", + "rustc_apfloat", + "rustc_data_structures", + "rustc_errors", + "rustc_fs_util", + "rustc_macros", + "rustc_target", + "scoped-tls", + "serialize", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "rustc-ap-arena" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5" dependencies = [ - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures", + "smallvec", ] [[package]] name = "rustc-ap-graphviz" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142" [[package]] name = "rustc-ap-rustc_data_structures" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils 0.6.5", + "ena", + "indexmap", + "jobserver", + "lazy_static 1.3.0", + "log", + "parking_lot 0.7.1", + "rustc-ap-graphviz", + "rustc-ap-serialize", + "rustc-hash", + "rustc-rayon", + "rustc-rayon-core", + "smallvec", + "stable_deref_trait", ] [[package]] name = "rustc-ap-rustc_errors" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333" dependencies = [ - "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets", + "atty", + "log", + "rustc-ap-rustc_data_structures", + "rustc-ap-serialize", + "rustc-ap-syntax_pos", + "term_size", + "termcolor", + "unicode-width", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305" +dependencies = [ + "unicode-xid 0.2.0", +] [[package]] name = "rustc-ap-rustc_macros" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f" dependencies = [ - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", + "synstructure", ] [[package]] name = "rustc-ap-rustc_target" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "log", + "rustc-ap-rustc_data_structures", + "rustc-ap-serialize", + "rustc-ap-syntax_pos", ] [[package]] name = "rustc-ap-serialize" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6" dependencies = [ - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap", + "smallvec", ] [[package]] name = "rustc-ap-syntax" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "lazy_static 1.3.0", + "log", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_target", + "rustc-ap-serialize", + "rustc-ap-syntax_pos", + "scoped-tls", + "smallvec", ] [[package]] name = "rustc-ap-syntax_pos" -version = "546.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "rustc-ap-arena", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_macros", + "rustc-ap-serialize", + "scoped-tls", + "unicode-width", ] [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" dependencies = [ - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", + "compiler_builtins", + "rustc-std-workspace-core", ] [[package]] name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_codegen_ssa 0.0.0", - "rustc_driver 0.0.0", - "rustc_target 0.0.0", + "jemalloc-sys", + "rustc_codegen_ssa", + "rustc_driver", + "rustc_target", ] [[package]] name = "rustc-rayon" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.2.0", + "either", + "rustc-rayon-core", ] [[package]] name = "rustc-rayon-core" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.2.0", + "lazy_static 1.3.0", + "libc", + "num_cpus", ] [[package]] name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc-std-workspace-alloc" -version = "1.0.0" +version = "1.99.0" dependencies = [ - "alloc 0.0.0", + "alloc", ] [[package]] name = "rustc-std-workspace-core" -version = "1.0.0" +version = "1.99.0" +dependencies = [ + "core", +] + +[[package]] +name = "rustc-std-workspace-std" +version = "1.99.0" dependencies = [ - "core 0.0.0", + "std", ] [[package]] name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", + "serde", + "serde_json", + "smallvec", + "url 2.1.0", + "winapi 0.3.6", ] [[package]] name = "rustc_apfloat" version = "0.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "smallvec", ] [[package]] name = "rustc_asan" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "build_helper 0.1.0", - "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "alloc", + "build_helper", + "cmake", + "compiler_builtins", + "core", ] [[package]] name = "rustc_ast_borrowck" version = "0.0.0" dependencies = [ - "graphviz 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "graphviz", + "log", + "rustc", + "rustc_data_structures", + "rustc_errors", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_llvm 0.0.0", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_llvm", ] [[package]] name = "rustc_codegen_ssa" version = "0.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_apfloat 0.0.0", - "rustc_codegen_utils 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_fs_util 0.0.0", - "rustc_incremental 0.0.0", - "rustc_target 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "cc", + "jobserver", + "libc", + "log", + "memmap", + "num_cpus", + "parking_lot 0.9.0", + "rustc", + "rustc_apfloat", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_errors", + "rustc_fs_util", + "rustc_incremental", + "rustc_target", + "serialize", + "syntax", + "syntax_pos", + "tempfile", ] [[package]] name = "rustc_codegen_utils" version = "0.0.0" dependencies = [ - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "rustc_metadata 0.0.0", - "rustc_target 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "flate2", + "log", + "punycode", + "rustc", + "rustc-demangle", + "rustc_data_structures", + "rustc_metadata", + "rustc_target", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "graphviz 0.0.0", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils 0.6.5", + "ena", + "graphviz", + "indexmap", + "jobserver", + "lazy_static 1.3.0", + "log", + "parking_lot 0.9.0", + "rustc-hash", + "rustc-rayon", + "rustc-rayon-core", + "serialize", + "smallvec", + "stable_deref_trait", ] [[package]] name = "rustc_driver" version = "0.0.0" dependencies = [ - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "graphviz 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_ast_borrowck 0.0.0", - "rustc_codegen_utils 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_interface 0.0.0", - "rustc_metadata 0.0.0", - "rustc_mir 0.0.0", - "rustc_save_analysis 0.0.0", - "rustc_target 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "env_logger", + "graphviz", + "lazy_static 1.3.0", + "log", + "rustc", + "rustc_ast_borrowck", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_errors", + "rustc_interface", + "rustc_metadata", + "rustc_mir", + "rustc_plugin", + "rustc_plugin_impl", + "rustc_save_analysis", + "rustc_target", + "serialize", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "serialize 0.0.0", - "syntax_pos 0.0.0", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets", + "atty", + "log", + "rustc_data_structures", + "serialize", + "syntax_pos", + "term_size", + "termcolor", + "unicode-width", ] [[package]] @@ -2967,225 +3447,234 @@ version = "0.0.0" name = "rustc_incremental" version = "0.0.0" dependencies = [ - "graphviz 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_fs_util 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "graphviz", + "log", + "rand 0.7.0", + "rustc", + "rustc_data_structures", + "rustc_fs_util", + "serialize", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_interface" version = "0.0.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_ast_borrowck 0.0.0", - "rustc_codegen_ssa 0.0.0", - "rustc_codegen_utils 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_incremental 0.0.0", - "rustc_lint 0.0.0", - "rustc_metadata 0.0.0", - "rustc_mir 0.0.0", - "rustc_passes 0.0.0", - "rustc_plugin 0.0.0", - "rustc_privacy 0.0.0", - "rustc_resolve 0.0.0", - "rustc_traits 0.0.0", - "rustc_typeck 0.0.0", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_ext 0.0.0", - "syntax_pos 0.0.0", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "once_cell", + "rustc", + "rustc-rayon", + "rustc_ast_borrowck", + "rustc_codegen_ssa", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_errors", + "rustc_incremental", + "rustc_lint", + "rustc_metadata", + "rustc_mir", + "rustc_passes", + "rustc_plugin_impl", + "rustc_privacy", + "rustc_resolve", + "rustc_traits", + "rustc_typeck", + "serialize", + "smallvec", + "syntax", + "syntax_ext", + "syntax_pos", + "tempfile", ] [[package]] name = "rustc_lexer" version = "0.1.0" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0", ] [[package]] name = "rustc_lint" version = "0.0.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_target 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "log", + "rustc", + "rustc_data_structures", + "rustc_target", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_llvm" version = "0.0.0" dependencies = [ - "build_helper 0.1.0", - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "build_helper", + "cc", ] [[package]] name = "rustc_lsan" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "build_helper 0.1.0", - "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "alloc", + "build_helper", + "cmake", + "compiler_builtins", + "core", ] [[package]] name = "rustc_macros" version = "0.1.0" dependencies = [ - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", + "synstructure", ] [[package]] name = "rustc_metadata" version = "0.0.0" dependencies = [ - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_target 0.0.0", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "flate2", + "log", + "memmap", + "rustc", + "rustc_data_structures", + "rustc_errors", + "rustc_target", + "serialize", + "smallvec", + "stable_deref_trait", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_mir" version = "0.0.0" dependencies = [ - "arena 0.0.0", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "graphviz 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_apfloat 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_target 0.0.0", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "arena", + "byteorder", + "either", + "graphviz", + "log", + "log_settings", + "polonius-engine", + "rustc", + "rustc_apfloat", + "rustc_data_structures", + "rustc_errors", + "rustc_lexer", + "rustc_target", + "serialize", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_msan" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "build_helper 0.1.0", - "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "alloc", + "build_helper", + "cmake", + "compiler_builtins", + "core", ] [[package]] name = "rustc_passes" version = "0.0.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "log", + "rustc", + "rustc_data_structures", + "rustc_errors", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_plugin" version = "0.0.0" dependencies = [ - "rustc 0.0.0", - "rustc_errors 0.0.0", - "rustc_metadata 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "rustc_plugin_impl", +] + +[[package]] +name = "rustc_plugin_impl" +version = "0.0.0" +dependencies = [ + "rustc", + "rustc_errors", + "rustc_metadata", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_privacy" version = "0.0.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_typeck 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "log", + "rustc", + "rustc_data_structures", + "rustc_typeck", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_resolve" version = "0.0.0" dependencies = [ - "arena 0.0.0", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_metadata 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "arena", + "bitflags", + "indexmap", + "log", + "rustc", + "rustc_data_structures", + "rustc_errors", + "rustc_metadata", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_save_analysis" version = "0.0.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_codegen_utils 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_target 0.0.0", - "rustc_typeck 0.0.0", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "log", + "rls-data", + "rls-span", + "rustc", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_target", + "rustc_typeck", + "serde_json", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_target" version = "0.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "serialize 0.0.0", - "syntax_pos 0.0.0", + "bitflags", + "log", + "rustc_data_structures", + "serialize", + "syntax_pos", ] [[package]] @@ -3196,65 +3685,67 @@ version = "0.2.0" name = "rustc_tools_util" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" [[package]] name = "rustc_traits" version = "0.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "graphviz 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_target 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "bitflags", + "chalk-engine", + "graphviz", + "log", + "rustc", + "rustc_data_structures", + "rustc_target", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_tsan" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "build_helper 0.1.0", - "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", + "alloc", + "build_helper", + "cmake", + "compiler_builtins", + "core", ] [[package]] name = "rustc_typeck" version = "0.0.0" dependencies = [ - "arena 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_target 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "arena", + "log", + "rustc", + "rustc_data_structures", + "rustc_errors", + "rustc_target", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier", + "pulldown-cmark 0.5.3", + "rustc-rayon", + "tempfile", ] [[package]] @@ -3265,528 +3756,641 @@ version = "0.1.0" name = "rustdoc-tool" version = "0.0.0" dependencies = [ - "rustdoc 0.0.0", + "rustdoc", ] [[package]] name = "rustfix" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7150ac777a2931a53489f5a41eb0937b84e3092a20cd0e73ad436b65b507f607" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "log", + "serde", + "serde_json", ] [[package]] name = "rustfmt-config_proc_macro" -version = "0.1.2" +version = "0.2.0" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3", + "quote 1.0.2", + "serde", + "syn 1.0.5", ] [[package]] name = "rustfmt-nightly" -version = "1.4.4" -dependencies = [ - "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0", - "rustfmt-config_proc_macro 0.1.2", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +version = "1.4.8" +dependencies = [ + "annotate-snippets", + "bytecount", + "cargo_metadata", + "derive-new", + "diff", + "dirs", + "env_logger", + "failure", + "getopts", + "ignore", + "itertools 0.8.0", + "lazy_static 1.3.0", + "log", + "regex", + "rustc-ap-rustc_target", + "rustc-ap-syntax", + "rustc-ap-syntax_pos", + "rustc-workspace-hack", + "rustfmt-config_proc_macro", + "serde", + "serde_json", + "structopt 0.3.1", + "term 0.6.0", + "toml", + "unicode-segmentation", + "unicode-width", + "unicode_categories", ] [[package]] name = "ryu" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" [[package]] name = "same-file" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "winapi 0.3.6", ] [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "scoped_threadpool" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" [[package]] name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" [[package]] name = "security-framework" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" dependencies = [ - "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", ] [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", + "serde", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.92" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" dependencies = [ - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "serde_ignored" -version = "0.0.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c24bbb8f4b81834f618cd3e28698235c2fba06ddf7f4fbe30519dd081364e59" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "serde_json" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" +dependencies = [ + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.5", ] [[package]] name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "itoa", + "serde", + "url 1.7.2", ] [[package]] name = "serialize" version = "0.0.0" dependencies = [ - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap", + "smallvec", ] [[package]] name = "sha-1" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" dependencies = [ - "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "byte-tools", + "digest", + "fake-simd", ] [[package]] name = "shell-escape" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" [[package]] name = "shlex" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" [[package]] name = "signal-hook" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4" dependencies = [ - "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap", + "libc", ] [[package]] name = "siphasher" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" [[package]] name = "sized-chunks" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2eb3fe454976eefb479f78f9b394d34d661b647c6326a3a6e66f68bb12c26" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" [[package]] name = "socket2" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.6", ] [[package]] name = "stable_deref_trait" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" [[package]] name = "std" version = "0.0.0" dependencies = [ - "alloc 0.0.0", - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", - "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "panic_abort 0.0.0", - "panic_unwind 0.0.0", - "profiler_builtins 0.0.0", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_asan 0.0.0", - "rustc_lsan 0.0.0", - "rustc_msan 0.0.0", - "rustc_tsan 0.0.0", - "unwind 0.0.0", + "alloc", + "backtrace", + "cc", + "cfg-if", + "compiler_builtins", + "core", + "dlmalloc", + "fortanix-sgx-abi", + "hashbrown", + "libc", + "panic_abort", + "panic_unwind", + "profiler_builtins", + "rand 0.7.0", + "rustc_asan", + "rustc_lsan", + "rustc_msan", + "rustc_tsan", + "unwind", + "wasi", ] [[package]] name = "string" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", ] [[package]] name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", + "serde", + "string_cache_codegen", + "string_cache_shared", ] [[package]] name = "string_cache_codegen" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator", + "phf_shared", + "proc-macro2 0.4.30", + "quote 0.6.12", + "string_cache_shared", ] [[package]] name = "string_cache_shared" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" [[package]] name = "strip-ansi-escapes" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee" dependencies = [ - "vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vte", ] [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "structopt-derive 0.2.18", +] + +[[package]] +name = "structopt" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac9d6e93dd792b217bf89cda5c14566e3043960c6f9da890c2ba5d09d07804c" +dependencies = [ + "clap", + "structopt-derive 0.3.1", ] [[package]] name = "structopt-derive" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" +dependencies = [ + "heck", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", +] + +[[package]] +name = "structopt-derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae9e5165d463a0dea76967d021f8d0f9316057bf5163aa2a4843790e842ff37" dependencies = [ - "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.5", ] [[package]] name = "strum" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e" [[package]] name = "strum_macros" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136" dependencies = [ - "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "syn" version = "0.15.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.12", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3", + "quote 1.0.2", + "unicode-xid 0.2.0", ] [[package]] name = "synstructure" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", + "unicode-xid 0.1.0", ] [[package]] name = "syntax" version = "0.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_lexer 0.1.0", - "rustc_macros 0.1.0", - "rustc_target 0.0.0", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serialize 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax_pos 0.0.0", + "bitflags", + "lazy_static 1.3.0", + "log", + "rustc_data_structures", + "rustc_errors", + "rustc_lexer", + "rustc_macros", + "rustc_target", + "scoped-tls", + "serialize", + "smallvec", + "syntax_pos", ] [[package]] name = "syntax_ext" version = "0.0.0" dependencies = [ - "fmt_macros 0.0.0", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_target 0.0.0", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syntax 0.0.0", - "syntax_pos 0.0.0", + "fmt_macros", + "log", + "rustc_data_structures", + "rustc_errors", + "rustc_lexer", + "rustc_target", + "smallvec", + "syntax", + "syntax_pos", ] [[package]] name = "syntax_pos" version = "0.0.0" dependencies = [ - "arena 0.0.0", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_data_structures 0.0.0", - "rustc_macros 0.1.0", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serialize 0.0.0", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arena", + "cfg-if", + "rustc_data_structures", + "rustc_macros", + "scoped-tls", + "serialize", + "unicode-width", ] [[package]] name = "take_mut" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" [[package]] name = "tar" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" dependencies = [ - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime", + "libc", + "redox_syscall", + "xattr", ] [[package]] name = "tempfile" -version = "3.0.5" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "rand 0.7.0", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.6", ] [[package]] name = "tendril" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" dependencies = [ - "futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futf", + "mac", + "utf-8", ] [[package]] name = "term" version = "0.0.0" +dependencies = [ + "core", + "std", +] [[package]] name = "term" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "winapi 0.2.8", ] [[package]] name = "term" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" +dependencies = [ + "byteorder", + "dirs", + "winapi 0.3.6", +] + +[[package]] +name = "term_size" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "libc", + "winapi 0.2.8", ] [[package]] name = "termcolor" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor", ] [[package]] name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_syscall", + "redox_termios", ] [[package]] name = "test" version = "0.0.0" dependencies = [ - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "proc_macro 0.0.0", + "core", + "getopts", + "libc", + "panic_abort", + "panic_unwind", + "proc_macro", + "std", "term 0.0.0", ] @@ -3794,923 +4398,638 @@ dependencies = [ name = "tester" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e812cb26c597f86a49b26dbb58b878bd2a2b4b93fc069dc39499228fe556ff6" dependencies = [ - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts", + "libc", + "term 0.4.6", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", ] [[package]] name = "tidy" version = "0.1.0" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0", + "regex", + "serde", + "serde_json", + "walkdir", ] [[package]] name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_syscall", + "winapi 0.3.6", ] [[package]] name = "tokio" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", ] [[package]] name = "tokio-buf" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "either", + "futures", ] [[package]] name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "tokio-io", ] [[package]] name = "tokio-current-thread" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "tokio-executor", ] [[package]] name = "tokio-executor" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", + "futures", ] [[package]] name = "tokio-fs" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "tokio-io", + "tokio-threadpool", ] [[package]] name = "tokio-io" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +dependencies = [ + "bytes", + "futures", + "log", +] + +[[package]] +name = "tokio-named-pipes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "mio", + "mio-named-pipes", + "tokio", ] [[package]] name = "tokio-process" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88e1281e412013f1ff5787def044a9577a0bed059f451e835f1643201f8b777d" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "libc", + "mio", + "mio-named-pipes", + "tokio-io", + "tokio-reactor", + "tokio-signal", + "winapi 0.3.6", ] [[package]] name = "tokio-reactor" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", + "futures", + "lazy_static 1.3.0", + "log", + "mio", + "num_cpus", + "parking_lot 0.7.1", + "slab", + "tokio-executor", + "tokio-io", +] + +[[package]] +name = "tokio-service" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" +dependencies = [ + "futures", ] [[package]] name = "tokio-signal" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "libc", + "mio", + "mio-uds", + "signal-hook", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "winapi 0.3.6", ] [[package]] name = "tokio-tcp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-threadpool" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" dependencies = [ - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "crossbeam-deque 0.6.3", + "crossbeam-utils 0.6.5", + "futures", + "log", + "num_cpus", + "rand 0.6.1", + "tokio-executor", ] [[package]] name = "tokio-timer" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", + "futures", + "slab", + "tokio-executor", ] [[package]] name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-uds" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "toml" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "toml-query" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24369a1894ac8224efcfd567c3d141aea360292f49888e7ec7dcc316527aebb" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml-query_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "failure_derive", + "is-match", + "lazy_static 1.3.0", + "regex", + "toml", + "toml-query_derive", ] [[package]] name = "toml-query_derive" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c99ca245ec273c7e75c8ee58f47b882d0146f3c2c8495158082c6671e8b5335" dependencies = [ - "darling 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "darling", + "quote 0.6.12", + "syn 0.15.35", ] [[package]] name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" [[package]] name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" [[package]] name = "ucd-trie" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" [[package]] name = "ucd-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" [[package]] name = "unicase" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check", ] [[package]] name = "unicase" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check", ] [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" [[package]] name = "unicode-segmentation" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", + "rustc-std-workspace-std", +] [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unstable-book-gen" version = "0.1.0" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tidy 0.1.0", + "num-traits", + "tidy", ] [[package]] name = "unwind" version = "0.0.0" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "cfg-if", + "compiler_builtins", + "core", + "libc", ] [[package]] name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", ] [[package]] name = "url" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url_serde" -version = "0.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0", + "matches", + "percent-encoding 2.0.0", + "serde", ] [[package]] name = "utf-8" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" [[package]] name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" [[package]] name = "utf8parse" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" [[package]] name = "uuid" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" dependencies = [ - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1", ] [[package]] name = "vcpkg" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "vergen" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "chrono", + "failure", ] [[package]] name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "vte" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" dependencies = [ - "utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8parse", ] [[package]] name = "walkdir" version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi 0.3.6", + "winapi-util", ] [[package]] name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wincolor" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", + "winapi-util", ] [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "xattr" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "xz2" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8bf41d3030c3577c9458fd6640a05afbf43b150d0b531b16bd77d3f794f27a" dependencies = [ - "lzma-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-sys", ] [[package]] name = "yaml-rust" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum ammonia 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "384d704f242a0a9faf793fff775a0be6ab9aa27edabffa097331d73779142520" -"checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" -"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -"checksum bstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "853b090ce0f45d0265902666bf88039ea3da825e33796716c511a1ec9c170036" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" -"checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "929766d993a2fde7a0ae962ee82429069cd7b68839cd9375b98efd719df65d3a" -"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" -"checksum cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "89431bba4e6b7092fb5fcd00a6f6ca596c55cc26b2f1e6dcdd08a1f4933f66b2" -"checksum chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a" -"checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8" -"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" -"checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" -"checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1c086a06d6f52f9c0d50cacdc021bfb6034ddeec9fb7e62f099f13f65472f4" -"checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" -"checksum curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "a85f2f95f2bd277d316d1aa8a477687ab4a6942258c7db7c89c187534669979c" -"checksum curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "9d91a0052d5b982887d8e829bee0faffc7218ea3c6ebd3d6c2c8f678a93c9a42" -"checksum darling 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9158d690bc62a3a57c3e45b85e4d50de2008b39345592c64efd79345c7e24be0" -"checksum darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d2a368589465391e127e10c9e3a08efc8df66fd49b87dc8524c764bbe7f2ef82" -"checksum darling_macro 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "244e8987bd4e174385240cde20a3657f607fb0797563c28255c353b5819a07b1" -"checksum datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" -"checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" -"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" -"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -"checksum directories 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccc83e029c3cebb4c8155c644d34e3a070ccdb4ff90d369c74cd73f7cb3c984" -"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" -"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" -"checksum dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63" -"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" -"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" -"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" -"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8cbee5e872cf7db61a999a041f9bc4706ca7bf7df4cb914f53fabb1c1bc550" -"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" -"checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" -"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" -"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" -"checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" -"checksum git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cb400360e8a4d61b10e648285bbfa919bbf9519d0d5d5720354456f44349226" -"checksum git2-curl 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2293de73491c3dc4174c5949ef53d2cc037b27613f88d72032e3f5237247a7dd" -"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" -"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" -"checksum handlebars 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" -"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36" -"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" -"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff" -"checksum html5ever 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7" -"checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" -"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)" = "6481fff8269772d4463253ca83c788104a7305cb3fb9136bc651a6211e46e03f" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d" -"checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" -"checksum im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" -"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc" -"checksum jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" -"checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" -"checksum jsonrpc-core 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "288dca7f9713710a29e485076b9340156cb701edb46a881f5d0c31aa4f5b9143" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" -"checksum libflate 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "90c6f86f4b0caa347206f916f8b687b51d77c6ef8ff18d52dd007491fd580529" -"checksum libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c179ed6d19cd3a051e68c177fbbc214e79ac4724fac3a850ec9f3d3eb8a5578" -"checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" -"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" -"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" -"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" -"checksum lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "169d737ad89cf8ddd82d1804d9122f54568c49377665157277cc90d747b1d31a" -"checksum lsp-types 0.57.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b62b77309737b1e262b3bbf37ff8faa740562c633b14702afe9be85dbcb6f88a" -"checksum lzma-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "16b5c59c57cc4d39e7999f50431aa312ea78af7c93b23fbb0c3567bd672e7f35" -"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -"checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510" -"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" -"checksum markup5ever 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum mdbook 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "949bb2acb2cff9fa5c375cf9c43e70b3dba0a974d9fe01c31285d7a84d2a0fa2" -"checksum mdbook-linkcheck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10" -"checksum measureme 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d09de7dafa3aa334bc806447c7e4de69419723312f4b88b80b561dea66601ce8" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" -"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332" -"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" -"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" -"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" -"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" -"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)" = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797" -"checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" -"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" -"checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" -"checksum pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3" -"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" -"checksum pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e" -"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" -"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" -"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "77043da1282374688ee212dc44b3f37ff929431de9c9adc3053bd3cee5630357" -"checksum punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" -"checksum racer 2.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "0727b9d7baaf9e42851145545d7b980b5c1752bd16a4c77c925c5e573d0069d9" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" -"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e542d9f077c126af32536b6aacc75bb7325400eab8cd0743543be5d91660780d" -"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" -"checksum rls-analysis 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0d208ad66717501222c74b42d9e823a7612592e85ed78b04074c8f58c0be0a" -"checksum rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76c72ea97e045be5f6290bb157ebdc5ee9f2b093831ff72adfaf59025cf5c491" -"checksum rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f1cb4694410d8d2ce43ccff3682f1c782158a018d5a9a92185675677f7533eb3" -"checksum rls-vfs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce4b57b25b4330ed5ec14028fc02141e083ddafda327e7eb598dc0569c8c83c9" -"checksum rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc2e1e68b64268c543bfa6e63e3c0d9ea58074c71396f42f76931f35a9287f9" -"checksum rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c108d647ce0dd46477b048eafff5a6273b5652e02d47424b0cd684147379c811" -"checksum rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656771744e0783cb8e4481e3b8b1f975687610aaf18833b898018111a0e0e582" -"checksum rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e37064f6624bc799bfaa2968b61ee6880926dea2a8bba69f18aef6c8e69c9604" -"checksum rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5bc0a971823637ea23a857f0ef1467f44b1e05d71968821f83a0abe53e0fe3" -"checksum rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b90037e3336fe8835f468db44d0848ae10d9cc8533ae89b55828883f905b7e80" -"checksum rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cadf9ca07315eab3a7a21f63872f9cc81e250fd6ede0419c24f8926ade73a45d" -"checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602" -"checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84" -"checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" -"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -"checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" -"checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_tools_util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustfix 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7150ac777a2931a53489f5a41eb0937b84e3092a20cd0e73ad436b65b507f607" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" -"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" -"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" -"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" -"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" -"checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" -"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -"checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2eb3fe454976eefb479f78f9b394d34d661b647c6326a3a6e66f68bb12c26" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" -"checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" -"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" -"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" -"checksum strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" -"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" -"checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e" -"checksum strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136" -"checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" -"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" -"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" -"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" -"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" -"checksum term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e812cb26c597f86a49b26dbb58b878bd2a2b4b93fc069dc39499228fe556ff6" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" -"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88e1281e412013f1ff5787def044a9577a0bed059f451e835f1643201f8b777d" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" -"checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" -"checksum toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a24369a1894ac8224efcfd567c3d141aea360292f49888e7ec7dcc316527aebb" -"checksum toml-query_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c99ca245ec273c7e75c8ee58f47b882d0146f3c2c8495158082c6671e8b5335" -"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77ddaf52e65c6b81c56b7e957c0b1970f7937f21c5c6774c4e56fcb4e20b48c6" -"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" -"checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" -"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" -"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -"checksum xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "df8bf41d3030c3577c9458fd6640a05afbf43b150d0b531b16bd77d3f794f27a" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/Cargo.toml b/Cargo.toml index ccd7e8b765..a242f090fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } # here rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' } +rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' } [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/README.md b/README.md index 40df6a4737..96d7e938be 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,13 @@ or reading the [rustc guide][rustcguidebuild]. ### Building on *nix 1. Make sure you have installed the dependencies: - * `g++` 4.7 or later or `clang++` 3.x or later + * `g++` 5.1 or later or `clang++` 3.5 or later * `python` 2.7 (but not 3.x) * GNU `make` 3.81 or later * `cmake` 3.4.3 or later * `curl` * `git` + * `ssl` which comes in `libssl-dev` or `openssl-devel` 2. Clone the [source] with `git`: @@ -56,6 +57,8 @@ or reading the [rustc guide][rustcguidebuild]. an installation (using `./x.py install`) that you set the `prefix` value in the `[install]` section to a directory that you have write permissions. + Create install directory if you are not installing in default directory + 4. Build and install: ```sh @@ -144,10 +147,21 @@ then you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. ```batch -> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" > python x.py build ``` +### Building rustc with older host toolchains +It is still possible to build Rust with the older toolchain versions listed below, but only if the +LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN option is set to true in the config.toml file. + +* Clang 3.1 +* Apple Clang 3.1 +* GCC 4.8 +* Visual Studio 2015 (Update 3) + +Toolchain versions older than what is listed above cannot be used to build rustc. + #### Specifying an ABI Each specific ABI can also be used from either environment (for example, using diff --git a/RELEASES.md b/RELEASES.md index ecf49278f4..6daf7a13b6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,127 @@ +Version 1.39.0 (2019-11-07) +=========================== + +Language +-------- +- [You can now create `async` functions and blocks with `async fn`, `async move {}`, and + `async {}` respectively, and you can now call `.await` on async expressions.][63209] +- [You can now use certain attributes on function, closure, and function pointer + parameters.][64010] These attributes include `cfg`, `cfg_attr`, `allow`, `warn`, + `deny`, `forbid` as well as inert helper attributes used by procedural macro + attributes applied to items. e.g. + ```rust + fn len( + #[cfg(windows)] slice: &[u16], + #[cfg(not(windows))] slice: &[u8], + ) -> usize { + slice.len() + } + ``` +- [You can now take shared references to bind-by-move patterns in the `if` guards + of `match` arms.][63118] e.g. + ```rust + fn main() { + let array: Box<[u8; 4]> = Box::new([1, 2, 3, 4]); + + match array { + nums + // ---- `nums` is bound by move. + if nums.iter().sum::() == 10 + // ^------ `.iter()` implicitly takes a reference to `nums`. + => { + drop(nums); + // ----------- Legal as `nums` was bound by move and so we have ownership. + } + _ => unreachable!(), + } + } + ``` + + + +Compiler +-------- +- [Added tier 3\* support for the `i686-unknown-uefi` target.][64334] +- [Added tier 3 support for the `sparc64-unknown-openbsd` target.][63595] +- [rustc will now trim code snippets in diagnostics to fit in your terminal.][63402] + **Note** Cargo currently doesn't use this feature. Refer to + [cargo#7315][cargo/7315] to track this feature's progress. +- [You can now pass `--show-output` argument to test binaries to print the + output of successful tests.][62600] + + +\* Refer to Rust's [platform support page][forge-platform-support] for more +information on Rust's tiered platform support. + +Libraries +--------- +- [`Vec::new` and `String::new` are now `const` functions.][64028] +- [`LinkedList::new` is now a `const` function.][63684] +- [`str::len`, `[T]::len` and `str::as_bytes` are now `const` functions.][63770] +- [The `abs`, `wrapping_abs`, and `overflowing_abs` numeric functions are + now `const`.][63786] + +Stabilized APIs +--------------- +- [`Pin::into_inner`] +- [`Instant::checked_duration_since`] +- [`Instant::saturating_duration_since`] + +Cargo +----- +- [You can now publish git dependencies if supplied with a `version`.][cargo/7237] +- [The `--all` flag has been renamed to `--workspace`.][cargo/7241] Using + `--all` is now deprecated. + +Misc +---- +- [You can now pass `-Clinker` to rustdoc to control the linker used + for compiling doctests.][63834] + +Compatibility Notes +------------------- +- [Code that was previously accepted by the old borrow checker, but rejected by + the NLL borrow checker is now a hard error in Rust 2018.][63565] This was + previously a warning, and will also become a hard error in the Rust 2015 + edition in the 1.40.0 release. +- [`rustdoc` now requires `rustc` to be installed and in the same directory to + run tests.][63827] This should improve performance when running a large + amount of doctests. +- [The `try!` macro will now issue a deprecation warning.][62672] It is + recommended to use the `?` operator instead. +- [`asinh(-0.0)` now correctly returns `-0.0`.][63698] Previously this + returned `0.0`. + +[62600]: https://github.com/rust-lang/rust/pull/62600/ +[62672]: https://github.com/rust-lang/rust/pull/62672/ +[63118]: https://github.com/rust-lang/rust/pull/63118/ +[63209]: https://github.com/rust-lang/rust/pull/63209/ +[63402]: https://github.com/rust-lang/rust/pull/63402/ +[63565]: https://github.com/rust-lang/rust/pull/63565/ +[63595]: https://github.com/rust-lang/rust/pull/63595/ +[63684]: https://github.com/rust-lang/rust/pull/63684/ +[63698]: https://github.com/rust-lang/rust/pull/63698/ +[63770]: https://github.com/rust-lang/rust/pull/63770/ +[63786]: https://github.com/rust-lang/rust/pull/63786/ +[63827]: https://github.com/rust-lang/rust/pull/63827/ +[63834]: https://github.com/rust-lang/rust/pull/63834/ +[63927]: https://github.com/rust-lang/rust/pull/63927/ +[63933]: https://github.com/rust-lang/rust/pull/63933/ +[63934]: https://github.com/rust-lang/rust/pull/63934/ +[63938]: https://github.com/rust-lang/rust/pull/63938/ +[63940]: https://github.com/rust-lang/rust/pull/63940/ +[63941]: https://github.com/rust-lang/rust/pull/63941/ +[63945]: https://github.com/rust-lang/rust/pull/63945/ +[64010]: https://github.com/rust-lang/rust/pull/64010/ +[64028]: https://github.com/rust-lang/rust/pull/64028/ +[64334]: https://github.com/rust-lang/rust/pull/64334/ +[cargo/7237]: https://github.com/rust-lang/cargo/pull/7237/ +[cargo/7241]: https://github.com/rust-lang/cargo/pull/7241/ +[cargo/7315]: https://github.com/rust-lang/cargo/pull/7315/ +[`Pin::into_inner`]: https://doc.rust-lang.org/std/pin/struct.Pin.html#method.into_inner +[`Instant::checked_duration_since`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.checked_duration_since +[`Instant::saturating_duration_since`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.saturating_duration_since + Version 1.38.0 (2019-09-26) ========================== @@ -47,8 +171,6 @@ Stabilized APIs - [`<*mut T>::cast`] - [`Duration::as_secs_f32`] - [`Duration::as_secs_f64`] -- [`Duration::div_duration_f32`] -- [`Duration::div_duration_f64`] - [`Duration::div_f32`] - [`Duration::div_f64`] - [`Duration::from_secs_f32`] @@ -70,10 +192,10 @@ Misc Compatibility Notes ------------------- -- Unfortunately the [`x86_64-unknown-uefi` platform can not be built][62785] - with rustc 1.39.0. -- The [`armv7-unknown-linux-gnueabihf` platform is also known to have - issues][62896] for certain crates such as libc. +- The [`x86_64-unknown-uefi` platform can not be built][62785] with rustc + 1.38.0. +- The [`armv7-unknown-linux-gnueabihf` platform is known to have + issues][62896] with certain crates such as libc. [60260]: https://github.com/rust-lang/rust/pull/60260/ [61457]: https://github.com/rust-lang/rust/pull/61457/ @@ -100,8 +222,6 @@ Compatibility Notes [`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast [`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32 [`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64 -[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32 -[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64 [`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32 [`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64 [`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32 diff --git a/config.toml.example b/config.toml.example index cb9f388a8e..848147c297 100644 --- a/config.toml.example +++ b/config.toml.example @@ -141,10 +141,10 @@ # library and facade crates. #compiler-docs = false -# Indicate whether submodules are managed and updated automatically. +# Indicate whether git submodules are managed and updated automatically. #submodules = true -# Update submodules only when the checked out commit in the submodules differs +# Update git submodules only when the checked out commit in the submodules differs # from what is committed in the main rustc repo. #fast-submodules = true @@ -184,7 +184,7 @@ # default. #extended = false -# Installs chosen set of extended tools if enables. By default builds all. +# Installs chosen set of extended tools if enabled. By default builds all. # If chosen tool failed to build the installation fails. #tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] @@ -382,11 +382,6 @@ # This is the name of the directory in which codegen backends will get installed #codegen-backends-dir = "codegen-backends" -# Flag indicating whether `libstd` calls an imported function to handle basic IO -# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown` -# target, as without this option the test output will not be captured. -#wasm-syscall = false - # Indicates whether LLD will be compiled and made available in the sysroot for # rustc to execute. #lld = false diff --git a/git-commit-hash b/git-commit-hash index c039f4b9e7..c702c5c981 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -625451e376bb2e5283fc4741caa0a3e8a2ca4d54 \ No newline at end of file +4560ea788cb760f0a34127156c78e2552949f734 \ No newline at end of file diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 589ee9276a..c27c318f5a 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -44,7 +44,7 @@ cc = "1.0.35" libc = "0.2" serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" -toml = "0.4" +toml = "0.5" lazy_static = "1.3.0" time = "0.1" petgraph = "0.4.13" diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index bd1a87c574..138b7f4b26 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -5,9 +5,6 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use bootstrap::{Config, Build}; diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 54b689fb06..475f2e9046 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -15,11 +15,7 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; -use std::ffi::OsString; use std::io; use std::path::PathBuf; use std::process::Command; @@ -27,35 +23,7 @@ use std::str::FromStr; use std::time::Instant; fn main() { - let mut args = env::args_os().skip(1).collect::>(); - - // Append metadata suffix for internal crates. See the corresponding entry - // in bootstrap/lib.rs for details. - if let Ok(s) = env::var("RUSTC_METADATA_SUFFIX") { - for i in 1..args.len() { - // Dirty code for borrowing issues - let mut new = None; - if let Some(current_as_str) = args[i].to_str() { - if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) || - current_as_str.starts_with("-Cmetadata") { - new = Some(format!("{}-{}", current_as_str, s)); - } - } - if let Some(new) = new { args[i] = new.into(); } - } - } - - // Drop `--error-format json` because despite our desire for json messages - // from Cargo we don't want any from rustc itself. - if let Some(n) = args.iter().position(|n| n == "--error-format") { - args.remove(n); - args.remove(n); - } - - if let Some(s) = env::var_os("RUSTC_ERROR_FORMAT") { - args.push("--error-format".into()); - args.push(s); - } + let args = env::args_os().skip(1).collect::>(); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) @@ -101,47 +69,19 @@ fn main() { if let Some(crate_name) = crate_name { if let Some(target) = env::var_os("RUSTC_TIME") { if target == "all" || - target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name) + target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name) { cmd.arg("-Ztime"); } } } - // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift - // compiler libraries and such from stage 1 to 2. - if stage == "0" { - cmd.arg("--cfg").arg("bootstrap"); - } - // Print backtrace in case of ICE if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() { cmd.env("RUST_BACKTRACE", "1"); } - cmd.env("RUSTC_BREAK_ON_ICE", "1"); - - if let Ok(debuginfo_level) = env::var("RUSTC_DEBUGINFO_LEVEL") { - cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); - } - - if env::var_os("RUSTC_DENY_WARNINGS").is_some() && - env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { - // When extending this list, search for `NO-RUSTC-WRAPPER` and add the new lints - // there as well, some code doesn't go through this `rustc` wrapper. - cmd.arg("-Dwarnings"); - cmd.arg("-Drust_2018_idioms"); - cmd.arg("-Dunused_lifetimes"); - // cfg(not(bootstrap)): Remove this during the next stage 0 compiler update. - // `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`. - let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version"); - if cfg_not_bootstrap && use_internal_lints(crate_name) { - cmd.arg("-Zunstable-options"); - cmd.arg("-Drustc::internal"); - } - } - - if let Some(target) = target { + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, // unless one is already set. @@ -149,43 +89,6 @@ fn main() { cmd.arg("--sysroot").arg(&sysroot); } - cmd.arg("-Zexternal-macro-backtrace"); - - // Link crates to the proc macro crate for the target, but use a host proc macro crate - // to actually run the macros - if env::var_os("RUST_DUAL_PROC_MACROS").is_some() { - cmd.arg("-Zdual-proc-macros"); - } - - // When we build Rust dylibs they're all intended for intermediate - // usage, so make sure we pass the -Cprefer-dynamic flag instead of - // linking all deps statically into the dylib. - if env::var_os("RUSTC_NO_PREFER_DYNAMIC").is_none() { - cmd.arg("-Cprefer-dynamic"); - } - - // Help the libc crate compile by assisting it in finding various - // sysroot native libraries. - if let Some(s) = env::var_os("MUSL_ROOT") { - if target.contains("musl") { - let mut root = OsString::from("native="); - root.push(&s); - root.push("/lib"); - cmd.arg("-L").arg(&root); - } - } - if let Some(s) = env::var_os("WASI_ROOT") { - let mut root = OsString::from("native="); - root.push(&s); - root.push("/lib/wasm32-wasi"); - cmd.arg("-L").arg(&root); - } - - // Override linker if necessary. - if let Ok(target_linker) = env::var("RUSTC_TARGET_LINKER") { - cmd.arg(format!("-Clinker={}", target_linker)); - } - // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any // other crate intentionally as this is the only crate for now that we @@ -212,86 +115,18 @@ fn main() { // The compiler builtins are pretty sensitive to symbols referenced in // libcore and such, so we never compile them with debug assertions. + // + // FIXME(rust-lang/cargo#7253) we should be doing this in `builder.rs` + // with env vars instead of doing it here in this script. if crate_name == Some("compiler_builtins") { cmd.arg("-C").arg("debug-assertions=no"); } else { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } - - if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { - cmd.arg("-C").arg(format!("codegen-units={}", s)); - } - - // Emit save-analysis info. - if env::var("RUSTC_SAVE_ANALYSIS") == Ok("api".to_string()) { - cmd.arg("-Zsave-analysis"); - cmd.env("RUST_SAVE_ANALYSIS_CONFIG", - "{\"output_file\": null,\"full_docs\": false,\ - \"pub_only\": true,\"reachable_only\": false,\ - \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}"); - } - - // Dealing with rpath here is a little special, so let's go into some - // detail. First off, `-rpath` is a linker option on Unix platforms - // which adds to the runtime dynamic loader path when looking for - // dynamic libraries. We use this by default on Unix platforms to ensure - // that our nightlies behave the same on Windows, that is they work out - // of the box. This can be disabled, of course, but basically that's why - // we're gated on RUSTC_RPATH here. - // - // Ok, so the astute might be wondering "why isn't `-C rpath` used - // here?" and that is indeed a good question to task. This codegen - // option is the compiler's current interface to generating an rpath. - // Unfortunately it doesn't quite suffice for us. The flag currently - // takes no value as an argument, so the compiler calculates what it - // should pass to the linker as `-rpath`. This unfortunately is based on - // the **compile time** directory structure which when building with - // Cargo will be very different than the runtime directory structure. - // - // All that's a really long winded way of saying that if we use - // `-Crpath` then the executables generated have the wrong rpath of - // something like `$ORIGIN/deps` when in fact the way we distribute - // rustc requires the rpath to be `$ORIGIN/../lib`. - // - // So, all in all, to set up the correct rpath we pass the linker - // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it - // fun to pass a flag to a tool to pass a flag to pass a flag to a tool - // to change a flag in a binary? - if env::var("RUSTC_RPATH") == Ok("true".to_string()) { - let rpath = if target.contains("apple") { - - // Note that we need to take one extra step on macOS to also pass - // `-Wl,-instal_name,@rpath/...` to get things to work right. To - // do that we pass a weird flag to the compiler to get it to do - // so. Note that this is definitely a hack, and we should likely - // flesh out rpath support more fully in the future. - cmd.arg("-Z").arg("osx-rpath-install-name"); - Some("-Wl,-rpath,@loader_path/../lib") - } else if !target.contains("windows") && - !target.contains("wasm32") && - !target.contains("fuchsia") { - Some("-Wl,-rpath,$ORIGIN/../lib") - } else { - None - }; - if let Some(rpath) = rpath { - cmd.arg("-C").arg(format!("link-args={}", rpath)); - } - } - - if let Ok(s) = env::var("RUSTC_CRT_STATIC") { - if s == "true" { - cmd.arg("-C").arg("target-feature=+crt-static"); - } - if s == "false" { - cmd.arg("-C").arg("target-feature=-crt-static"); - } - } - - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { - cmd.arg("--remap-path-prefix").arg(&map); - } } else { + // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars + // here, but rather Cargo should know what flags to pass rustc itself. + // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { cmd.arg(format!("-Clinker={}", host_linker)); @@ -307,6 +142,10 @@ fn main() { } } + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); + } + // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates // also in the sysroot. We also do this for host crates, since those @@ -315,10 +154,6 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } - if env::var_os("RUSTC_PARALLEL_COMPILER").is_some() { - cmd.arg("--cfg").arg("parallel_compiler"); - } - if verbose > 1 { eprintln!( "rustc command: {:?}={:?} {:?}", @@ -369,14 +204,6 @@ fn main() { std::process::exit(code); } -// Rustc crates for which internal lints are in effect. -fn use_internal_lints(crate_name: Option<&str>) -> bool { - crate_name.map_or(false, |crate_name| { - crate_name.starts_with("rustc") || crate_name.starts_with("syntax") || - ["arena", "fmt_macros"].contains(&crate_name) - }) -} - #[cfg(unix)] fn exec_cmd(cmd: &mut Command) -> io::Result { use std::os::unix::process::CommandExt; diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index ff38ee8788..a13ff69a7b 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -2,12 +2,10 @@ //! //! See comments in `src/bootstrap/rustc.rs` for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use std::process::Command; use std::path::PathBuf; +use std::ffi::OsString; fn main() { let args = env::args_os().skip(1).collect::>(); @@ -47,7 +45,9 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } if let Some(linker) = env::var_os("RUSTC_TARGET_LINKER") { - cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); + let mut arg = OsString::from("-Clinker="); + arg.push(&linker); + cmd.arg(arg); } // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 86901792d7..65129eeeec 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -320,7 +320,7 @@ class RustBuild(object): def __init__(self): self.cargo_channel = '' self.date = '' - self._download_url = 'https://static.rust-lang.org' + self._download_url = '' self.rustc_channel = '' self.build = '' self.build_dir = os.path.join(os.getcwd(), "build") @@ -523,6 +523,10 @@ class RustBuild(object): 'value2' >>> rb.get_toml('key', 'c') is None True + + >>> rb.config_toml = 'key1 = true' + >>> rb.get_toml("key1") + 'true' """ cur_section = None @@ -571,6 +575,12 @@ class RustBuild(object): >>> RustBuild.get_string(' "devel" ') 'devel' + >>> RustBuild.get_string(" 'devel' ") + 'devel' + >>> RustBuild.get_string('devel') is None + True + >>> RustBuild.get_string(' "devel ') + '' """ start = line.find('"') if start != -1: @@ -631,6 +641,9 @@ class RustBuild(object): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += "-C linker=" + target_linker + " " + env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes " + if self.get_toml("deny-warnings", "rust") != "false": + env["RUSTFLAGS"] += "-Dwarnings " env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] @@ -666,7 +679,7 @@ class RustBuild(object): def update_submodule(self, module, checked_out, recorded_submodules): module_path = os.path.join(self.rust_root, module) - if checked_out != None: + if checked_out is not None: default_encoding = sys.getdefaultencoding() checked_out = checked_out.communicate()[0].decode(default_encoding).strip() if recorded_submodules[module] == checked_out: @@ -695,6 +708,14 @@ class RustBuild(object): if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ self.get_toml('submodules') == "false": return + + # check the existence of 'git' command + try: + subprocess.check_output(['git', '--version']) + except (subprocess.CalledProcessError, OSError): + print("error: `git` is not found, please make sure it's installed and in the path.") + sys.exit(1) + slow_submodules = self.get_toml('fast-submodules') == "false" start_time = time() if slow_submodules: @@ -731,9 +752,19 @@ class RustBuild(object): self.update_submodule(module[0], module[1], recorded_submodules) print("Submodules updated in %.2f seconds" % (time() - start_time)) + def set_normal_environment(self): + """Set download URL for normal environment""" + if 'RUSTUP_DIST_SERVER' in os.environ: + self._download_url = os.environ['RUSTUP_DIST_SERVER'] + else: + self._download_url = 'https://static.rust-lang.org' + def set_dev_environment(self): """Set download URL for development environment""" - self._download_url = 'https://dev-static.rust-lang.org' + if 'RUSTUP_DEV_DIST_SERVER' in os.environ: + self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER'] + else: + self._download_url = 'https://dev-static.rust-lang.org' def check_vendored_status(self): """Check that vendoring is configured properly""" @@ -809,13 +840,13 @@ def bootstrap(help_triggered): except (OSError, IOError): pass - match = re.search(r'\nverbose = (\d+)', build.config_toml) - if match is not None: - build.verbose = max(build.verbose, int(match.group(1))) + config_verbose = build.get_toml('verbose', 'build') + if config_verbose is not None: + build.verbose = max(build.verbose, int(config_verbose)) - build.use_vendored_sources = '\nvendor = true' in build.config_toml + build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true' - build.use_locked_deps = '\nlocked-deps = true' in build.config_toml + build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true' build.check_vendored_status() @@ -826,6 +857,8 @@ def bootstrap(help_triggered): if 'dev' in data: build.set_dev_environment() + else: + build.set_normal_environment() build.update_submodules() diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e54c9360ba..5d586f0c46 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::collections::HashMap; use std::env; +use std::ffi::OsStr; use std::fmt::Debug; use std::fs; use std::hash::Hash; @@ -145,7 +146,7 @@ impl StepDescription { only_hosts: S::ONLY_HOSTS, should_run: S::should_run, make_run: S::make_run, - name: unsafe { ::std::intrinsics::type_name::() }, + name: std::any::type_name::(), } } @@ -337,7 +338,6 @@ impl<'a> Builder<'a> { match kind { Kind::Build => describe!( compile::Std, - compile::Test, compile::Rustc, compile::CodegenBackend, compile::StartupObjects, @@ -363,7 +363,6 @@ impl<'a> Builder<'a> { ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, - check::Test, check::Rustc, check::CodegenBackend, check::Rustdoc @@ -425,8 +424,6 @@ impl<'a> Builder<'a> { doc::TheBook, doc::Standalone, doc::Std, - doc::Test, - doc::WhitelistedRustc, doc::Rustc, doc::Rustdoc, doc::ErrorIndex, @@ -618,13 +615,7 @@ impl<'a> Builder<'a> { } fn run(self, builder: &Builder<'_>) -> Interned { - let compiler = self.compiler; - let config = &builder.build.config; - let lib = if compiler.stage >= 1 && config.libdir_relative().is_some() { - builder.build.config.libdir_relative().unwrap() - } else { - Path::new("lib") - }; + let lib = builder.sysroot_libdir_relative(self.compiler); let sysroot = builder .sysroot(self.compiler) .join(lib) @@ -678,9 +669,21 @@ impl<'a> Builder<'a> { } } + /// Returns the compiler's relative libdir where the standard library and other artifacts are + /// found for a compiler's sysroot. + /// + /// For example this returns `lib` on Unix and Windows. + pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { + match self.config.libdir_relative() { + Some(relative_libdir) if compiler.stage >= 1 + => relative_libdir, + _ => Path::new("lib") + } + } + /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. - pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { + pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) { // Windows doesn't need dylib path munging because the dlls for the // compiler live next to the compiler and the system will find them // automatically. @@ -688,7 +691,7 @@ impl<'a> Builder<'a> { return; } - add_lib_path(vec![self.rustc_libdir(compiler)], cmd); + add_lib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command); } /// Gets a path to the compiler specified. @@ -750,85 +753,39 @@ impl<'a> Builder<'a> { mode: Mode, target: Interned, cmd: &str, - ) -> Command { + ) -> Cargo { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); - // command specific path, we call clear_if_dirty with this - let mut my_out = match cmd { - "build" => self.cargo_out(compiler, mode, target), - - // This is the intended out directory for crate documentation. - "doc" | "rustdoc" => self.crate_doc_out(target), - - _ => self.stage_out(compiler, mode), - }; - - // This is for the original compiler, but if we're forced to use stage 1, then - // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since - // we copy the libs forward. - let cmp = self.compiler_for(compiler.stage, compiler.host, target); - - let libstd_stamp = match cmd { - "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), - _ => compile::libstd_stamp(self, cmp, target), - }; - - let libtest_stamp = match cmd { - "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), - _ => compile::libtest_stamp(self, cmp, target), - }; - - let librustc_stamp = match cmd { - "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), - _ => compile::librustc_stamp(self, cmp, target), - }; + // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, + // so we need to explicitly clear out if they've been updated. + for backend in self.codegen_backends(compiler) { + self.clear_if_dirty(&out_dir, &backend); + } if cmd == "doc" || cmd == "rustdoc" { - if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { + let my_out = match mode { // This is the intended out directory for compiler documentation. - my_out = self.compiler_doc_out(target); - } + Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target), + _ => self.crate_doc_out(target), + }; let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); - } else if cmd != "test" { - match mode { - Mode::Std => { - self.clear_if_dirty(&my_out, &self.rustc(compiler)); - for backend in self.codegen_backends(compiler) { - self.clear_if_dirty(&my_out, &backend); - } - }, - Mode::Test => { - self.clear_if_dirty(&my_out, &libstd_stamp); - }, - Mode::Rustc => { - self.clear_if_dirty(&my_out, &self.rustc(compiler)); - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - }, - Mode::Codegen => { - self.clear_if_dirty(&my_out, &librustc_stamp); - }, - Mode::ToolBootstrap => { }, - Mode::ToolStd => { - self.clear_if_dirty(&my_out, &libstd_stamp); - }, - Mode::ToolTest => { - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - }, - Mode::ToolRustc => { - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - self.clear_if_dirty(&my_out, &librustc_stamp); - }, - } } cargo .env("CARGO_TARGET_DIR", out_dir) - .arg(cmd); + .arg(cmd) + .arg("-Zconfig-profile"); + + let profile_var = |name: &str| { + let profile = if self.config.rust_optimize { + "RELEASE" + } else { + "DEV" + }; + format!("CARGO_PROFILE_{}_{}", profile, name) + }; // See comment in librustc_llvm/build.rs for why this is necessary, largely llvm-config // needs to not accidentally link to libLLVM in stage0/lib. @@ -850,17 +807,46 @@ impl<'a> Builder<'a> { cargo.env("RUST_CHECK", "1"); } + let stage; + if compiler.stage == 0 && self.local_rebuild { + // Assume the local-rebuild rustc already has stage1 features. + stage = 1; + } else { + stage = compiler.stage; + } + + let mut rustflags = Rustflags::new(&target); + if stage != 0 { + rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); + } else { + rustflags.env("RUSTFLAGS_BOOTSTRAP"); + rustflags.arg("--cfg=bootstrap"); + } + match mode { - Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {}, + Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}, Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { // Build proc macros both for the host and the target if target != compiler.host && cmd != "check" { cargo.arg("-Zdual-proc-macros"); - cargo.env("RUST_DUAL_PROC_MACROS", "1"); + rustflags.arg("-Zdual-proc-macros"); } }, } + // This tells Cargo (and in turn, rustc) to output more complete + // dependency information. Most importantly for rustbuild, this + // includes sysroot artifacts, like libstd, which means that we don't + // need to track those in rustbuild (an error prone process!). This + // feature is currently unstable as there may be some bugs and such, but + // it represents a big improvement in rustbuild's reliability on + // rebuilds, so we're using it here. + // + // For some additional context, see #63470 (the PR originally adding + // this), as well as #63012 which is the tracking issue for this + // feature on the rustc side. + cargo.arg("-Zbinary-dep-depinfo"); + cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS"); @@ -889,44 +875,16 @@ impl<'a> Builder<'a> { // things still build right, please do! match mode { Mode::Std => metadata.push_str("std"), - Mode::Test => metadata.push_str("test"), _ => {}, } cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata); - let stage; - if compiler.stage == 0 && self.local_rebuild { - // Assume the local-rebuild rustc already has stage1 features. - stage = 1; - } else { - stage = compiler.stage; - } - - let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default(); - if stage != 0 { - let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default(); - if !extra_args.is_empty() { - extra_args.push_str(" "); - } - extra_args.push_str(&s); - } - if cmd == "clippy" { - extra_args.push_str("-Zforce-unstable-if-unmarked -Zunstable-options \ - --json-rendered=termcolor"); - } - - if !extra_args.is_empty() { - cargo.env( - "RUSTFLAGS", - format!( - "{} {}", - env::var("RUSTFLAGS").unwrap_or_default(), - extra_args - ), - ); + rustflags.arg("-Zforce-unstable-if-unmarked"); } + rustflags.arg("-Zexternal-macro-backtrace"); + let want_rustdoc = self.doc_tests != DocTests::No; // We synthetically interpret a stage0 compiler used to build tools as a @@ -962,7 +920,6 @@ impl<'a> Builder<'a> { ) .env("RUSTC_SYSROOT", &sysroot) .env("RUSTC_LIBDIR", &libdir) - .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) .env( "RUSTDOC_REAL", @@ -972,16 +929,63 @@ impl<'a> Builder<'a> { PathBuf::from("/path/to/nowhere/rustdoc/not/required") }, ) - .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()); + .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()) + .env("RUSTC_BREAK_ON_ICE", "1"); + + // Dealing with rpath here is a little special, so let's go into some + // detail. First off, `-rpath` is a linker option on Unix platforms + // which adds to the runtime dynamic loader path when looking for + // dynamic libraries. We use this by default on Unix platforms to ensure + // that our nightlies behave the same on Windows, that is they work out + // of the box. This can be disabled, of course, but basically that's why + // we're gated on RUSTC_RPATH here. + // + // Ok, so the astute might be wondering "why isn't `-C rpath` used + // here?" and that is indeed a good question to task. This codegen + // option is the compiler's current interface to generating an rpath. + // Unfortunately it doesn't quite suffice for us. The flag currently + // takes no value as an argument, so the compiler calculates what it + // should pass to the linker as `-rpath`. This unfortunately is based on + // the **compile time** directory structure which when building with + // Cargo will be very different than the runtime directory structure. + // + // All that's a really long winded way of saying that if we use + // `-Crpath` then the executables generated have the wrong rpath of + // something like `$ORIGIN/deps` when in fact the way we distribute + // rustc requires the rpath to be `$ORIGIN/../lib`. + // + // So, all in all, to set up the correct rpath we pass the linker + // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it + // fun to pass a flag to a tool to pass a flag to pass a flag to a tool + // to change a flag in a binary? + if self.config.rust_rpath { + let rpath = if target.contains("apple") { + + // Note that we need to take one extra step on macOS to also pass + // `-Wl,-instal_name,@rpath/...` to get things to work right. To + // do that we pass a weird flag to the compiler to get it to do + // so. Note that this is definitely a hack, and we should likely + // flesh out rpath support more fully in the future. + rustflags.arg("-Zosx-rpath-install-name"); + Some("-Wl,-rpath,@loader_path/../lib") + } else if !target.contains("windows") && + !target.contains("wasm32") && + !target.contains("fuchsia") { + Some("-Wl,-rpath,$ORIGIN/../lib") + } else { + None + }; + if let Some(rpath) = rpath { + rustflags.arg(&format!("-Clink-args={}", rpath)); + } + } if let Some(host_linker) = self.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); } if let Some(target_linker) = self.linker(target) { - cargo.env("RUSTC_TARGET_LINKER", target_linker); - } - if let Some(ref error_format) = self.config.rustc_error_format { - cargo.env("RUSTC_ERROR_FORMAT", error_format); + let target = crate::envify(&target); + cargo.env(&format!("CARGO_TARGET_{}_LINKER", target), target_linker); } if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); @@ -989,36 +993,22 @@ impl<'a> Builder<'a> { let debuginfo_level = match mode { Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc, - Mode::Std | Mode::Test => self.config.rust_debuginfo_level_std, + Mode::Std => self.config.rust_debuginfo_level_std, Mode::ToolBootstrap | Mode::ToolStd | - Mode::ToolTest | Mode::ToolRustc => self.config.rust_debuginfo_level_tools, + Mode::ToolRustc => self.config.rust_debuginfo_level_tools, }; - cargo.env("RUSTC_DEBUGINFO_LEVEL", debuginfo_level.to_string()); + cargo.env(profile_var("DEBUG"), debuginfo_level.to_string()); if !mode.is_tool() { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); - - // Currently the compiler depends on crates from crates.io, and - // then other crates can depend on the compiler (e.g., proc-macro - // crates). Let's say, for example that rustc itself depends on the - // bitflags crate. If an external crate then depends on the - // bitflags crate as well, we need to make sure they don't - // conflict, even if they pick the same version of bitflags. We'll - // want to make sure that e.g., a plugin and rustc each get their - // own copy of bitflags. - - // Cargo ensures that this works in general through the -C metadata - // flag. This flag will frob the symbols in the binary to make sure - // they're different, even though the source code is the exact - // same. To solve this problem for the compiler we extend Cargo's - // already-passed -C metadata flag with our own. Our rustc.rs - // wrapper around the actual rustc will detect -C metadata being - // passed and frob it with this extra string we're passing in. - cargo.env("RUSTC_METADATA_SUFFIX", "rustc"); } if let Some(x) = self.crt_static(target) { - cargo.env("RUSTC_CRT_STATIC", x.to_string()); + if x { + rustflags.arg("-Ctarget-feature=+crt-static"); + } else { + rustflags.arg("-Ctarget-feature=-crt-static"); + } } if let Some(x) = self.crt_static(compiler.host) { @@ -1077,8 +1067,21 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); - if self.config.deny_warnings { - cargo.env("RUSTC_DENY_WARNINGS", "1"); + if !mode.is_tool() { + // When extending this list, add the new lints to the RUSTFLAGS of the + // build_bootstrap function of src/bootstrap/bootstrap.py as well as + // some code doesn't go through this `rustc` wrapper. + rustflags.arg("-Wrust_2018_idioms"); + rustflags.arg("-Wunused_lifetimes"); + + if self.config.deny_warnings { + rustflags.arg("-Dwarnings"); + } + } + + if let Mode::Rustc | Mode::Codegen = mode { + rustflags.arg("-Zunstable-options"); + rustflags.arg("-Wrustc::internal"); } // Throughout the build Cargo can execute a number of build scripts @@ -1131,12 +1134,15 @@ impl<'a> Builder<'a> { } } - if (cmd == "build" || cmd == "rustc") - && mode == Mode::Std + if mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) { - cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); + rustflags.arg("-Zsave-analysis"); + cargo.env("RUST_SAVE_ANALYSIS_CONFIG", + "{\"output_file\": null,\"full_docs\": false,\ + \"pub_only\": true,\"reachable_only\": false,\ + \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}"); } // For `cargo doc` invocations, make rustdoc print the Rust version into the docs @@ -1191,9 +1197,8 @@ impl<'a> Builder<'a> { match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) { (Mode::Std, Some(n), _) | - (Mode::Test, Some(n), _) | (_, _, Some(n)) => { - cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); + cargo.env(profile_var("CODEGEN_UNITS"), n.to_string()); } _ => { // Don't set anything @@ -1214,9 +1219,21 @@ impl<'a> Builder<'a> { cargo.arg("--frozen"); } + cargo.env("RUSTC_INSTALL_BINDIR", &self.config.bindir); + self.ci_env.force_coloring_in_ci(&mut cargo); - cargo + // When we build Rust dylibs they're all intended for intermediate + // usage, so make sure we pass the -Cprefer-dynamic flag instead of + // linking all deps statically into the dylib. + if let Mode::Std | Mode::Rustc | Mode::Codegen = mode { + rustflags.arg("-Cprefer-dynamic"); + } + + Cargo { + command: cargo, + rustflags, + } } /// Ensure that a given step is built, returning its output. This will @@ -1316,3 +1333,78 @@ impl<'a> Builder<'a> { #[cfg(test)] mod tests; + +#[derive(Debug)] +struct Rustflags(String); + +impl Rustflags { + fn new(target: &str) -> Rustflags { + let mut ret = Rustflags(String::new()); + + // Inherit `RUSTFLAGS` by default ... + ret.env("RUSTFLAGS"); + + // ... and also handle target-specific env RUSTFLAGS if they're + // configured. + let target_specific = format!("CARGO_TARGET_{}_RUSTFLAGS", crate::envify(target)); + ret.env(&target_specific); + + ret + } + + fn env(&mut self, env: &str) { + if let Ok(s) = env::var(env) { + for part in s.split_whitespace() { + self.arg(part); + } + } + } + + fn arg(&mut self, arg: &str) -> &mut Self { + assert_eq!(arg.split_whitespace().count(), 1); + if self.0.len() > 0 { + self.0.push_str(" "); + } + self.0.push_str(arg); + self + } +} + +#[derive(Debug)] +pub struct Cargo { + command: Command, + rustflags: Rustflags, +} + +impl Cargo { + pub fn rustflag(&mut self, arg: &str) -> &mut Cargo { + self.rustflags.arg(arg); + self + } + + pub fn arg(&mut self, arg: impl AsRef) -> &mut Cargo { + self.command.arg(arg.as_ref()); + self + } + + pub fn args(&mut self, args: I) -> &mut Cargo + where I: IntoIterator, S: AsRef + { + for arg in args { + self.arg(arg.as_ref()); + } + self + } + + pub fn env(&mut self, key: impl AsRef, value: impl AsRef) -> &mut Cargo { + self.command.env(key.as_ref(), value.as_ref()); + self + } +} + +impl From for Command { + fn from(mut cargo: Cargo) -> Command { + cargo.command.env("RUSTFLAGS", &cargo.rustflags.0); + cargo.command + } +} diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index d1542b1fca..2bb90fdb04 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -365,27 +365,6 @@ fn dist_with_same_targets_and_hosts() { }, ] ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); assert_eq!( first(builder.cache.all::()), &[ @@ -415,7 +394,47 @@ fn build_default() { let b = INTERNER.intern_str("B"); let c = INTERNER.intern_str("C"); - assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Std { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); assert!(!builder.cache.all::().is_empty()); assert_eq!( first(builder.cache.all::()), @@ -450,63 +469,61 @@ fn build_default() { }, ] ); +} + +#[test] +fn build_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); assert_eq!( - first(builder.cache.all::()), + first(builder.cache.all::()), &[ - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c, }, ] ); -} - -#[test] -fn build_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.skip_only_host_steps = true; - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); assert_eq!( first(builder.cache.all::()), &[ @@ -541,48 +558,6 @@ fn build_with_target_flag() { }, ] ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); } #[test] diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index c58a98bac3..a4cb81d3d1 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -46,7 +46,7 @@ fn cc2ar(cc: &Path, target: &str) -> Option { } else if target.contains("openbsd") { Some(PathBuf::from("ar")) } else if target.contains("vxworks") { - Some(PathBuf::from("vx-ar")) + Some(PathBuf::from("wr-ar")) } else { let parent = cc.parent().unwrap(); let file = cc.file_name().unwrap().to_str().unwrap(); diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 8e8d8f5e78..caa4843da4 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.38.0"; +pub const CFG_RELEASE_NUM: &str = "1.39.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 11b082ac3f..cadb9a7e44 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,6 +1,6 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, +use crate::compile::{run_cargo, std_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step}; use crate::tool::{prepare_tool_cargo, SourceType}; @@ -34,7 +34,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { @@ -52,7 +52,7 @@ impl Step for Std { builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &libstd_stamp(builder, compiler, target), true); @@ -92,7 +92,7 @@ impl Step for Rustc { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - builder.ensure(Test { target }); + builder.ensure(Std { target }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, cargo_subcommand(builder.kind)); @@ -100,7 +100,7 @@ impl Step for Rustc { builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &librustc_stamp(builder, compiler, target), true); @@ -152,54 +152,13 @@ impl Step for CodegenBackend { // We won't build LLVM if it's not available, as it shouldn't affect `check`. run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &codegen_backend_stamp(builder, compiler, target, backend), true); } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Test { - pub target: Interned, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("test") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); - let target = self.target; - - builder.ensure(Std { target }); - - let mut cargo = builder.cargo(compiler, Mode::Test, target, cargo_subcommand(builder.kind)); - test_cargo(builder, &compiler, target, &mut cargo); - - builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); - run_cargo(builder, - &mut cargo, - args(builder.kind), - &libtest_stamp(builder, compiler, target), - true); - - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); - add_to_sysroot(builder, &libdir, &hostdir, &libtest_stamp(builder, compiler, target)); - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustdoc { pub target: Interned, @@ -226,18 +185,18 @@ impl Step for Rustdoc { builder.ensure(Rustc { target }); - let mut cargo = prepare_tool_cargo(builder, - compiler, - Mode::ToolRustc, - target, - cargo_subcommand(builder.kind), - "src/tools/rustdoc", - SourceType::InTree, - &[]); + let cargo = prepare_tool_cargo(builder, + compiler, + Mode::ToolRustc, + target, + cargo_subcommand(builder.kind), + "src/tools/rustdoc", + SourceType::InTree, + &[]); println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &rustdoc_stamp(builder, compiler, target), true); @@ -245,7 +204,6 @@ impl Step for Rustdoc { let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); - builder.cargo(compiler, Mode::ToolRustc, target, "clean"); } } @@ -259,16 +217,6 @@ pub fn libstd_stamp( builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp") } -/// Cargo's output path for libtest in a given stage, compiled by a particular -/// compiler for the specified target. -pub fn libtest_stamp( - builder: &Builder<'_>, - compiler: Compiler, - target: Interned, -) -> PathBuf { - builder.cargo_out(compiler, Mode::Test, target).join(".libtest-check.stamp") -} - /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. pub fn librustc_stamp( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4cd793adaf..6ea32edfb2 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -15,12 +15,13 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio, exit}; use std::str; -use build_helper::{output, mtime, t, up_to_date}; +use build_helper::{output, t, up_to_date}; use filetime::FileTime; use serde::Deserialize; use serde_json; use crate::dist; +use crate::builder::Cargo; use crate::util::{exe, is_dylib}; use crate::{Compiler, Mode, GitRepo}; use crate::native; @@ -39,7 +40,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { @@ -98,7 +99,7 @@ impl Step for Std { builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, vec![], &libstd_stamp(builder, compiler, target), false); @@ -156,7 +157,7 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: pub fn std_cargo(builder: &Builder<'_>, compiler: &Compiler, target: Interned, - cargo: &mut Command) { + cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -212,21 +213,26 @@ pub fn std_cargo(builder: &Builder<'_>, emscripten: false, }); cargo.env("LLVM_CONFIG", llvm_config); + cargo.env("RUSTC_BUILD_SANITIZERS", "1"); } cargo.arg("--features").arg(features) .arg("--manifest-path") - .arg(builder.src.join("src/libstd/Cargo.toml")); + .arg(builder.src.join("src/libtest/Cargo.toml")); + // Help the libc crate compile by assisting it in finding various + // sysroot native libraries. if target.contains("musl") { if let Some(p) = builder.musl_root(target) { - cargo.env("MUSL_ROOT", p); + let root = format!("native={}/lib", p.to_str().unwrap()); + cargo.rustflag("-L").rustflag(&root); } } if target.ends_with("-wasi") { if let Some(p) = builder.wasi_root(target) { - cargo.env("WASI_ROOT", p); + let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap()); + cargo.rustflag("-L").rustflag(&root); } } } @@ -274,8 +280,6 @@ impl Step for StdLink { // for reason why the sanitizers are not built in stage0. copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } - - builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); } } @@ -360,131 +364,6 @@ impl Step for StartupObjects { } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Test { - pub target: Interned, - pub compiler: Compiler, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("test") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - compiler: run.builder.compiler(run.builder.top_stage, run.host), - target: run.target, - }); - } - - /// Builds libtest. - /// - /// This will build libtest and supporting libraries for a particular stage of - /// the build using the `compiler` targeting the `target` architecture. The - /// artifacts created will also be linked into the sysroot directory. - fn run(self, builder: &Builder<'_>) { - let target = self.target; - let compiler = self.compiler; - - builder.ensure(Std { compiler, target }); - - if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old libtest. This may not behave well."); - builder.ensure(TestLink { - compiler, - target_compiler: compiler, - target, - }); - return; - } - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - if compiler_to_use != compiler { - builder.ensure(Test { - compiler: compiler_to_use, - target, - }); - builder.info( - &format!("Uplifting stage1 test ({} -> {})", builder.config.build, target)); - builder.ensure(TestLink { - compiler: compiler_to_use, - target_compiler: compiler, - target, - }); - return; - } - - let mut cargo = builder.cargo(compiler, Mode::Test, target, "build"); - test_cargo(builder, &compiler, target, &mut cargo); - - builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage, - &compiler.host, target)); - run_cargo(builder, - &mut cargo, - vec![], - &libtest_stamp(builder, compiler, target), - false); - - builder.ensure(TestLink { - compiler: builder.compiler(compiler.stage, builder.config.build), - target_compiler: compiler, - target, - }); - } -} - -/// Same as `std_cargo`, but for libtest -pub fn test_cargo(builder: &Builder<'_>, - _compiler: &Compiler, - _target: Interned, - cargo: &mut Command) { - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { - cargo.env("MACOSX_DEPLOYMENT_TARGET", target); - } - cargo.arg("--manifest-path") - .arg(builder.src.join("src/libtest/Cargo.toml")); -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct TestLink { - pub compiler: Compiler, - pub target_compiler: Compiler, - pub target: Interned, -} - -impl Step for TestLink { - type Output = (); - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - /// Same as `std_link`, only for libtest - fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target_compiler = self.target_compiler; - let target = self.target; - builder.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})", - target_compiler.stage, - compiler.stage, - &compiler.host, - target_compiler.host, - target)); - add_to_sysroot( - builder, - &builder.sysroot_libdir(target_compiler, target), - &builder.sysroot_libdir(target_compiler, compiler.host), - &libtest_stamp(builder, compiler, target) - ); - - builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); - } -} - #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: Interned, @@ -516,7 +395,7 @@ impl Step for Rustc { let compiler = self.compiler; let target = self.target; - builder.ensure(Test { compiler, target }); + builder.ensure(Std { compiler, target }); if builder.config.keep_stage.contains(&compiler.stage) { builder.info("Warning: Using a potentially old librustc. This may not behave well."); @@ -545,7 +424,7 @@ impl Step for Rustc { } // Ensure that build scripts and proc macros have a std / libproc_macro to link against. - builder.ensure(Test { + builder.ensure(Std { compiler: builder.compiler(self.compiler.stage, builder.config.build), target: builder.config.build, }); @@ -556,7 +435,7 @@ impl Step for Rustc { builder.info(&format!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, vec![], &librustc_stamp(builder, compiler, target), false); @@ -569,14 +448,14 @@ impl Step for Rustc { } } -pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Command) { +pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo) { cargo.arg("--features").arg(builder.rustc_features()) .arg("--manifest-path") .arg(builder.src.join("src/rustc/Cargo.toml")); rustc_cargo_env(builder, cargo); } -pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Command) { +pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) @@ -601,7 +480,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Command) { cargo.env("CFG_DEFAULT_LINKER", s); } if builder.config.rustc_parallel { - cargo.env("RUSTC_PARALLEL_COMPILER", "1"); + cargo.rustflag("--cfg=parallel_compiler"); } if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); @@ -639,7 +518,6 @@ impl Step for RustcLink { &builder.sysroot_libdir(target_compiler, compiler.host), &librustc_stamp(builder, compiler, target) ); - builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); } } @@ -704,14 +582,11 @@ impl Step for CodegenBackend { rustc_cargo_env(builder, &mut cargo); let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); + cargo.arg("--features").arg(features); let tmp_stamp = out_dir.join(".tmp.stamp"); - let files = run_cargo(builder, - cargo.arg("--features").arg(features), - vec![], - &tmp_stamp, - false); + let files = run_cargo(builder, cargo, vec![], &tmp_stamp, false); if builder.config.dry_run { return; } @@ -736,7 +611,7 @@ impl Step for CodegenBackend { } pub fn build_codegen_backend(builder: &Builder<'_>, - cargo: &mut Command, + cargo: &mut Cargo, compiler: &Compiler, target: Interned, backend: Interned) -> String { @@ -795,6 +670,9 @@ pub fn build_codegen_backend(builder: &Builder<'_>, if builder.config.llvm_use_libcxx { cargo.env("LLVM_USE_LIBCXX", "1"); } + if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { + cargo.env("LLVM_NDEBUG", "1"); + } } _ => panic!("unknown backend: {}", backend), } @@ -874,16 +752,6 @@ pub fn libstd_stamp( builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp") } -/// Cargo's output path for libtest in a given stage, compiled by a particular -/// compiler for the specified target. -pub fn libtest_stamp( - builder: &Builder<'_>, - compiler: Compiler, - target: Interned, -) -> PathBuf { - builder.cargo_out(compiler, Mode::Test, target).join(".libtest.stamp") -} - /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. pub fn librustc_stamp( @@ -1083,7 +951,7 @@ pub fn add_to_sysroot( } pub fn run_cargo(builder: &Builder<'_>, - cargo: &mut Command, + cargo: Cargo, tail_args: Vec, stamp: &Path, is_check: bool) @@ -1116,10 +984,6 @@ pub fn run_cargo(builder: &Builder<'_>, }, .. } => (filenames, crate_types), - CargoMessage::CompilerMessage { message } => { - eprintln!("{}", message.rendered); - return; - } _ => return, }; for filename in filenames { @@ -1206,58 +1070,35 @@ pub fn run_cargo(builder: &Builder<'_>, deps.push((path_to_add.into(), false)); } - // Now we want to update the contents of the stamp file, if necessary. First - // we read off the previous contents along with its mtime. If our new - // contents (the list of files to copy) is different or if any dep's mtime - // is newer then we rewrite the stamp file. deps.sort(); - let stamp_contents = fs::read(stamp); - let stamp_mtime = mtime(&stamp); let mut new_contents = Vec::new(); - let mut max = None; - let mut max_path = None; for (dep, proc_macro) in deps.iter() { - let mtime = mtime(dep); - if Some(mtime) > max { - max = Some(mtime); - max_path = Some(dep.clone()); - } new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"\0"); } - let max = max.unwrap(); - let max_path = max_path.unwrap(); - let contents_equal = stamp_contents - .map(|contents| contents == new_contents) - .unwrap_or_default(); - if contents_equal && max <= stamp_mtime { - builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", - stamp, max, stamp_mtime)); - return deps.into_iter().map(|(d, _)| d).collect() - } - if max > stamp_mtime { - builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); - } else { - builder.verbose(&format!("updating {:?} as deps changed", stamp)); - } t!(fs::write(&stamp, &new_contents)); deps.into_iter().map(|(d, _)| d).collect() } pub fn stream_cargo( builder: &Builder<'_>, - cargo: &mut Command, + cargo: Cargo, tail_args: Vec, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { + let mut cargo = Command::from(cargo); if builder.config.dry_run { return true; } // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. - cargo.arg("--message-format").arg("json") - .stdout(Stdio::piped()); + let mut message_format = String::from("json-render-diagnostics"); + if let Some(s) = &builder.config.rustc_error_format { + message_format.push_str(",json-diagnostic-"); + message_format.push_str(s); + } + cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); for arg in tail_args { cargo.arg(arg); @@ -1310,12 +1151,4 @@ pub enum CargoMessage<'a> { BuildScriptExecuted { package_id: Cow<'a, str>, }, - CompilerMessage { - message: ClippyMessage<'a> - } -} - -#[derive(Deserialize)] -pub struct ClippyMessage<'a> { - rendered: Cow<'a, str>, } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a5bfafdfdb..52b5cd888d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -122,7 +122,6 @@ pub struct Config { // libstd features pub backtrace: bool, // support for RUST_BACKTRACE - pub wasm_syscall: bool, // misc pub low_priority: bool, @@ -138,7 +137,7 @@ pub struct Config { pub sysconfdir: Option, pub datadir: Option, pub docdir: Option, - pub bindir: Option, + pub bindir: PathBuf, pub libdir: Option, pub mandir: Option, pub codegen_tests: bool, @@ -318,7 +317,6 @@ struct Rust { save_toolstates: Option, codegen_backends: Option>, codegen_backends_dir: Option, - wasm_syscall: Option, lld: Option, lldb: Option, llvm_tools: Option, @@ -402,6 +400,7 @@ impl Config { config.incremental = flags.incremental; config.dry_run = flags.dry_run; config.keep_stage = flags.keep_stage; + config.bindir = "bin".into(); // default if let Some(value) = flags.deny_warnings { config.deny_warnings = value; } @@ -484,7 +483,7 @@ impl Config { config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from); config.datadir = install.datadir.clone().map(PathBuf::from); config.docdir = install.docdir.clone().map(PathBuf::from); - config.bindir = install.bindir.clone().map(PathBuf::from); + set(&mut config.bindir, install.bindir.clone().map(PathBuf::from)); config.libdir = install.libdir.clone().map(PathBuf::from); config.mandir = install.mandir.clone().map(PathBuf::from); } @@ -558,7 +557,6 @@ impl Config { if let Some(true) = rust.incremental { config.incremental = true; } - set(&mut config.wasm_syscall, rust.wasm_syscall); set(&mut config.lld_enabled, rust.lld); set(&mut config.lldb_enabled, rust.lldb); set(&mut config.llvm_tools_enabled, rust.llvm_tools); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 552965863d..d9dff77a30 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,7 +18,7 @@ use build_helper::{output, t}; use crate::{Compiler, Mode, LLVM_TOOLS}; use crate::channel; -use crate::util::{is_dylib, exe}; +use crate::util::{is_dylib, exe, timeit}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::compile; use crate::tool::{self, Tool}; @@ -91,14 +91,15 @@ impl Step for Docs { let name = pkgname(builder, "rust-docs"); - builder.info(&format!("Dist docs ({})", host)); if !builder.config.docs { - builder.info("\tskipping - docs disabled"); return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } builder.default_doc(None); + builder.info(&format!("Dist docs ({})", host)); + let _time = timeit(builder); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -151,9 +152,7 @@ impl Step for RustcDocs { let name = pkgname(builder, "rustc-docs"); - builder.info(&format!("Dist compiler docs ({})", host)); if !builder.config.compiler_docs { - builder.info("\tskipping - compiler docs disabled"); return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } @@ -179,6 +178,9 @@ impl Step for RustcDocs { .arg("--component-name=rustc-docs") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); + + builder.info(&format!("Dist compiler docs ({})", host)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); @@ -350,6 +352,7 @@ impl Step for Mingw { } builder.info(&format!("Dist mingw ({})", host)); + let _time = timeit(builder); let name = pkgname(builder, "rust-mingw"); let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -403,7 +406,6 @@ impl Step for Rustc { let compiler = self.compiler; let host = self.compiler.host; - builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host)); let name = pkgname(builder, "rustc"); let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -460,6 +462,9 @@ impl Step for Rustc { .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rustc") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); builder.remove_dir(&overlay); @@ -469,7 +474,6 @@ impl Step for Rustc { fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { let host = compiler.host; let src = builder.sysroot(compiler); - let libdir = builder.rustc_libdir(compiler); // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); @@ -481,11 +485,14 @@ impl Step for Rustc { // Copy runtime DLLs needed by the compiler if libdir_relative.to_str() != Some("bin") { + let libdir = builder.rustc_libdir(compiler); for entry in builder.read_dir(&libdir) { let name = entry.file_name(); if let Some(s) = name.to_str() { if is_dylib(s) { - builder.install(&entry.path(), &image.join(&libdir_relative), 0o644); + // Don't use custom libdir here because ^lib/ will be resolved again + // with installer + builder.install(&entry.path(), &image.join("lib"), 0o644); } } } @@ -493,8 +500,11 @@ impl Step for Rustc { // Copy over the codegen backends let backends_src = builder.sysroot_codegen_backends(compiler); - let backends_rel = backends_src.strip_prefix(&src).unwrap(); - let backends_dst = image.join(&backends_rel); + let backends_rel = backends_src.strip_prefix(&src).unwrap() + .strip_prefix(builder.sysroot_libdir_relative(compiler)).unwrap(); + // Don't use custom libdir here because ^lib/ will be resolved again with installer + let backends_dst = image.join("lib").join(&backends_rel); + t!(fs::create_dir_all(&backends_dst)); builder.cp_r(&backends_src, &backends_dst); @@ -657,8 +667,6 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - builder.info(&format!("Dist std stage{} ({} -> {})", - compiler.stage, &compiler.host, target)); // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. @@ -673,12 +681,7 @@ impl Step for Std { if builder.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { - if builder.no_std(target) == Some(true) { - // the `test` doesn't compile for no-std targets - builder.ensure(compile::Std { compiler, target }); - } else { - builder.ensure(compile::Test { compiler, target }); - } + builder.ensure(compile::Std { compiler, target }); } let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); @@ -714,6 +717,10 @@ impl Step for Std { .arg(format!("--package-name={}-{}", name, target)) .arg(format!("--component-name=rust-std-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist std stage{} ({} -> {})", + compiler.stage, &compiler.host, target)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) @@ -754,15 +761,13 @@ impl Step for Analysis { let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - builder.info("Dist analysis"); let name = pkgname(builder, "rust-analysis"); if &compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } - builder.ensure(Std { compiler, target }); + builder.ensure(compile::Std { compiler, target }); let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); @@ -786,6 +791,9 @@ impl Step for Analysis { .arg(format!("--package-name={}-{}", name, target)) .arg(format!("--component-name=rust-analysis-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info("Dist analysis"); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) @@ -874,8 +882,6 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.info("Dist src"); - let name = pkgname(builder, "rust-src"); let image = tmpdir(builder).join(format!("{}-image", name)); let _ = fs::remove_dir_all(&image); @@ -908,6 +914,7 @@ impl Step for Src { "src/libproc_macro", "src/tools/rustc-std-workspace-core", "src/tools/rustc-std-workspace-alloc", + "src/tools/rustc-std-workspace-std", "src/librustc", "src/libsyntax", ]; @@ -929,6 +936,9 @@ impl Step for Src { .arg(format!("--package-name={}", name)) .arg("--component-name=rust-src") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info("Dist src"); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); @@ -956,8 +966,6 @@ impl Step for PlainSourceTarball { /// Creates the plain source tarball fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.info("Create plain source tarball"); - // Make sure that the root folder of tarball has the correct name let plain_name = format!("{}-src", pkgname(builder, "rustc")); let plain_dst_src = tmpdir(builder).join(&plain_name); @@ -1019,6 +1027,9 @@ impl Step for PlainSourceTarball { .arg("--output").arg(&tarball) .arg("--work-dir=.") .current_dir(tmpdir(builder)); + + builder.info("Create plain source tarball"); + let _time = timeit(builder); builder.run(&mut cmd); distdir(builder).join(&format!("{}.tar.gz", plain_name)) } @@ -1072,7 +1083,6 @@ impl Step for Cargo { let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/cargo"); let etc = src.join("src/etc"); let release_num = builder.release_num("cargo"); @@ -1125,6 +1135,9 @@ impl Step for Cargo { .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=cargo") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } @@ -1160,7 +1173,6 @@ impl Step for Rls { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rls"); let release_num = builder.release_num("rls"); let name = pkgname(builder, "rls"); @@ -1209,6 +1221,8 @@ impl Step for Rls { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rls-preview"); + builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1244,7 +1258,6 @@ impl Step for Clippy { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/clippy"); let release_num = builder.release_num("clippy"); let name = pkgname(builder, "clippy"); @@ -1298,6 +1311,8 @@ impl Step for Clippy { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=clippy-preview"); + builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1333,7 +1348,6 @@ impl Step for Miri { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/miri"); let release_num = builder.release_num("miri"); let name = pkgname(builder, "miri"); @@ -1388,6 +1402,8 @@ impl Step for Miri { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=miri-preview"); + builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1422,7 +1438,6 @@ impl Step for Rustfmt { let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rustfmt"); let release_num = builder.release_num("rustfmt"); let name = pkgname(builder, "rustfmt"); @@ -1475,6 +1490,8 @@ impl Step for Rustfmt { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rustfmt-preview"); + builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1575,6 +1592,7 @@ impl Step for Extended { input_tarballs.push(tarball); } + builder.info("building combined installer"); let mut cmd = rust_installer(builder); cmd.arg("combine") .arg("--product-name=Rust") @@ -1586,7 +1604,9 @@ impl Step for Extended { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--input-tarballs").arg(input_tarballs) .arg("--non-installed-overlay").arg(&overlay); + let time = timeit(&builder); builder.run(&mut cmd); + drop(time); let mut license = String::new(); license += &builder.read(&builder.src.join("COPYRIGHT")); @@ -1642,6 +1662,7 @@ impl Step for Extended { }; if target.contains("apple-darwin") { + builder.info("building pkg installer"); let pkg = tmp.join("pkg"); let _ = fs::remove_dir_all(&pkg); @@ -1691,6 +1712,7 @@ impl Step for Extended { pkgname(builder, "rust"), target))) .arg("--package-path").arg(&pkg); + let _time = timeit(builder); builder.run(&mut cmd); } @@ -1741,14 +1763,18 @@ impl Step for Extended { builder.create(&exe.join("LICENSE.txt"), &license); // Generate exe installer + builder.info("building `exe` installer with `iscc`"); let mut cmd = Command::new("iscc"); cmd.arg("rust.iss") + .arg("/Q") .current_dir(&exe); if target.contains("windows-gnu") { cmd.arg("/dMINGW"); } add_env(builder, &mut cmd, target); + let time = timeit(builder); builder.run(&mut cmd); + drop(time); builder.install(&exe.join(format!("{}-{}.exe", pkgname(builder, "rust"), target)), &distdir(builder), 0o755); @@ -1913,6 +1939,7 @@ impl Step for Extended { builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644); builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + builder.info(&format!("building `msi` installer with {:?}", light)); let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target); let mut cmd = Command::new(&light); cmd.arg("-nologo") @@ -1945,6 +1972,7 @@ impl Step for Extended { // ICE57 wrongly complains about the shortcuts cmd.arg("-sice:ICE57"); + let _time = timeit(builder); builder.run(&mut cmd); if !builder.config.dry_run { @@ -1999,6 +2027,8 @@ impl Step for HashSign { } fn run(self, builder: &Builder<'_>) { + // This gets called by `promote-release` + // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release). let mut cmd = builder.tool_cmd(Tool::BuildManifest); if builder.config.dry_run { return; @@ -2009,10 +2039,14 @@ impl Step for HashSign { let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") }); - let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") - }); - let pass = t!(fs::read_to_string(&file)); + let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() { + let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") + }); + t!(fs::read_to_string(&file)) + } else { + String::new() + }; let today = output(Command::new("date").arg("+%Y-%m-%d")); @@ -2107,6 +2141,7 @@ impl Step for LlvmTools { } builder.info(&format!("Dist LlvmTools ({})", target)); + let _time = timeit(builder); let src = builder.src.join("src/llvm-project/llvm"); let name = pkgname(builder, "llvm-tools"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 36229720e4..4ee8cd2485 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -375,7 +375,7 @@ impl Step for Standalone { up_to_date(&footer, &html) && up_to_date(&favicon, &html) && up_to_date(&full_toc, &html) && - up_to_date(&version_info, &html) && + (builder.config.dry_run || up_to_date(&version_info, &html)) && (builder.config.dry_run || up_to_date(&rustdoc, &html)) { continue } @@ -413,7 +413,7 @@ impl Step for Std { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.all_krates("std").default_condition(builder.config.docs) + run.all_krates("test").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { @@ -475,137 +475,11 @@ impl Step for Std { .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page").arg(&builder.src.join("src/doc/index.md")); - builder.run(&mut cargo); - builder.cp_r(&my_out, &out); + builder.run(&mut cargo.into()); }; - for krate in &["alloc", "core", "std"] { + for krate in &["alloc", "core", "std", "proc_macro", "test"] { run_cargo_rustdoc_for(krate); } - } -} - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Test { - stage: u32, - target: Interned, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.krate("test").default_condition(builder.config.docs) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - stage: run.builder.top_stage, - target: run.target, - }); - } - - /// Compile all libtest documentation. - /// - /// This will generate all documentation for libtest and its dependencies. This - /// is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} test ({})", stage, target)); - let out = builder.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); - - // Build libstd docs so that we generate relative links - builder.ensure(Std { stage, target }); - - builder.ensure(compile::Test { compiler, target }); - let out_dir = builder.stage_out(compiler, Mode::Test) - .join(target).join("doc"); - - // See docs in std above for why we symlink - let my_out = builder.crate_doc_out(target); - t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); - - let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc"); - compile::test_cargo(builder, &compiler, target, &mut cargo); - - cargo.arg("--no-deps") - .arg("-p").arg("test") - .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) - .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); - - builder.run(&mut cargo); - builder.cp_r(&my_out, &out); - } -} - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct WhitelistedRustc { - stage: u32, - target: Interned, -} - -impl Step for WhitelistedRustc { - type Output = (); - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.krate("rustc-main").default_condition(builder.config.docs) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(WhitelistedRustc { - stage: run.builder.top_stage, - target: run.target, - }); - } - - /// Generates whitelisted compiler crate documentation. - /// - /// This will generate all documentation for crates that are whitelisted - /// to be included in the standard documentation. This documentation is - /// included in the standard Rust documentation, so we should always - /// document it and symlink to merge with the rest of the std and test - /// documentation. We don't build other compiler documentation - /// here as we want to be able to keep it separate from the standard - /// documentation. This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target)); - let out = builder.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); - - // Build libstd docs so that we generate relative links - builder.ensure(Std { stage, target }); - - builder.ensure(compile::Rustc { compiler, target }); - let out_dir = builder.stage_out(compiler, Mode::Rustc) - .join(target).join("doc"); - - // See docs in std above for why we symlink - let my_out = builder.crate_doc_out(target); - t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); - - let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); - compile::rustc_cargo(builder, &mut cargo); - - // We don't want to build docs for internal compiler dependencies in this - // step (there is another step for that). Therefore, we whitelist the crates - // for which docs must be built. - for krate in &["proc_macro"] { - cargo.arg("-p").arg(krate) - .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) - .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); - } - - builder.run(&mut cargo); builder.cp_r(&my_out, &out); } } @@ -687,7 +561,7 @@ impl Step for Rustc { cargo.arg("-p").arg(krate); } - builder.run(&mut cargo); + builder.run(&mut cargo.into()); } } @@ -782,7 +656,7 @@ impl Step for Rustdoc { cargo.arg("-p").arg("rustdoc"); cargo.env("RUSTDOCFLAGS", "--document-private-items"); - builder.run(&mut cargo); + builder.run(&mut cargo.into()); } } @@ -825,8 +699,7 @@ impl Step for ErrorIndex { index.arg(crate::channel::CFG_RELEASE_NUM); // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &builder.config.build) - .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir()); + index.env("CFG_BUILD", &builder.config.build); builder.run(&mut index); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 828865f10f..d9580b5981 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -36,7 +36,7 @@ pub struct Flags { // This overrides the deny-warnings configuation option, // which passes -Dwarnings to the compiler invocations. // - // true => deny, false => allow + // true => deny, false => warn pub deny_warnings: Option, } @@ -556,10 +556,10 @@ fn split(s: &[String]) -> Vec { fn parse_deny_warnings(matches: &getopts::Matches) -> Option { match matches.opt_str("warnings").as_ref().map(|v| v.as_str()) { Some("deny") => Some(true), - Some("allow") => Some(false), + Some("warn") => Some(false), Some(value) => { eprintln!( - r#"invalid value for --warnings: {:?}, expected "allow" or "deny""#, + r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value, ); process::exit(1); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 557586709c..384219c38f 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -67,7 +67,6 @@ fn install_sh( let sysconfdir_default = PathBuf::from("/etc"); let datadir_default = PathBuf::from("share"); let docdir_default = datadir_default.join("doc/rust"); - let bindir_default = PathBuf::from("bin"); let libdir_default = PathBuf::from("lib"); let mandir_default = datadir_default.join("man"); let prefix = builder.config.prefix.as_ref().map_or(prefix_default, |p| { @@ -76,7 +75,7 @@ fn install_sh( let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default); let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default); let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default); - let bindir = builder.config.bindir.as_ref().unwrap_or(&bindir_default); + let bindir = &builder.config.bindir; let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default); let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b72aa78f3d..9203a558f6 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -103,9 +103,6 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - #![feature(core_intrinsics)] #![feature(drain_filter)] @@ -297,9 +294,6 @@ pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Std, - /// Build libtest, placing output in the "stageN-test" directory. - Test, - /// Build librustc, and compiler libraries, placing output in the "stageN-rustc" directory. Rustc, @@ -315,7 +309,6 @@ pub enum Mode { /// Compile a tool which uses all libraries we compile (up to rustc). /// Doesn't use the stage0 compiler libraries like "other", and includes /// tools like rustdoc, cargo, rls, etc. - ToolTest, ToolStd, ToolRustc, } @@ -502,9 +495,6 @@ impl Build { if self.config.profiler { features.push_str(" profiler"); } - if self.config.wasm_syscall { - features.push_str(" wasm_syscall"); - } features } @@ -536,11 +526,10 @@ impl Build { fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf { let suffix = match mode { Mode::Std => "-std", - Mode::Test => "-test", Mode::Rustc => "-rustc", Mode::Codegen => "-codegen", Mode::ToolBootstrap => "-bootstrap-tools", - Mode::ToolStd | Mode::ToolTest | Mode::ToolRustc => "-tools", + Mode::ToolStd | Mode::ToolRustc => "-tools", }; self.out.join(&*compiler.host) .join(format!("stage{}{}", compiler.stage, suffix)) @@ -1331,3 +1320,13 @@ impl Compiler { self.stage >= final_stage } } + +fn envify(s: &str) -> String { + s.chars() + .map(|c| match c { + '-' => '_', + c => c, + }) + .flat_map(|c| c.to_uppercase()) + .collect() +} diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 73d6fe532c..e0a1f46078 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -81,5 +81,14 @@ ci-subset-1: ci-subset-2: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) +TESTS_IN_MINGW_2 := \ + src/test/ui \ + src/test/compile-fail + +ci-mingw-subset-1: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %) +ci-mingw-subset-2: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2) + .PHONY: dist diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f02def3e1b..7bf9ea2688 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,26 +81,29 @@ impl Step for Llvm { (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) }; - if !llvm_info.is_git() { - println!( - "git could not determine the LLVM submodule commit hash. \ - Assuming that an LLVM build is necessary.", - ); - } - let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); let done_stamp = out_dir.join("llvm-finished-building"); - if let Some(llvm_commit) = llvm_info.sha() { - if done_stamp.exists() { + if done_stamp.exists() { + if let Some(llvm_commit) = llvm_info.sha() { let done_contents = t!(fs::read(&done_stamp)); // If LLVM was already built previously and the submodule's commit didn't change // from the previous build, then no action is required. if done_contents == llvm_commit.as_bytes() { - return build_llvm_config + return build_llvm_config; } + } else { + builder.info( + "Could not determine the LLVM submodule commit hash. \ + Assuming that an LLVM rebuild is not necessary.", + ); + builder.info(&format!( + "To force LLVM to rebuild, remove the file `{}`", + done_stamp.display() + )); + return build_llvm_config; } } @@ -303,9 +306,7 @@ impl Step for Llvm { cfg.build(); - if let Some(llvm_commit) = llvm_info.sha() { - t!(fs::write(&done_stamp, llvm_commit)); - } + t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or(""))); build_llvm_config } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 4e3930c8da..bffe748f37 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -202,10 +202,6 @@ pub fn check(build: &mut Build) { panic!("couldn't find libc.a in musl dir: {}", root.join("lib").display()); } - if fs::metadata(root.join("lib/libunwind.a")).is_err() { - panic!("couldn't find libunwind.a in musl dir: {}", - root.join("lib").display()); - } } None => { panic!("when targeting MUSL either the rust.musl-root \ diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c2c134bfd1..b7ce9c7b39 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -23,7 +23,7 @@ use crate::tool::{self, Tool, SourceType}; use crate::toolstate::ToolState; use crate::util::{self, dylib_path, dylib_path_var}; use crate::Crate as CargoCrate; -use crate::{DocTests, Mode, GitRepo}; +use crate::{DocTests, Mode, GitRepo, envify}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -233,10 +233,9 @@ impl Step for Cargo { // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); - try_run( - builder, - cargo.env("PATH", &path_for_cargo(builder, compiler)), - ); + cargo.env("PATH", &path_for_cargo(builder, compiler)); + + try_run(builder, &mut cargo.into()); } } @@ -290,7 +289,7 @@ impl Step for Rls { cargo.arg("--") .args(builder.config.cmd.test_args()); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("rls", ToolState::TestPass); } } @@ -348,7 +347,7 @@ impl Step for Rustfmt { builder.add_rustc_lib_path(compiler, &mut cargo); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("rustfmt", ToolState::TestPass); } } @@ -418,6 +417,7 @@ impl Step for Miri { cargo.env("CARGO_INSTALL_ROOT", &builder.out); // cargo adds a `bin/` cargo.env("XARGO", builder.out.join("bin").join("xargo")); + let mut cargo = Command::from(cargo); if !try_run(builder, &mut cargo) { return; } @@ -467,7 +467,7 @@ impl Step for Miri { builder.add_rustc_lib_path(compiler, &mut cargo); - if !try_run(builder, &mut cargo) { + if !try_run(builder, &mut cargo.into()) { return; } @@ -502,16 +502,16 @@ impl Step for CompiletestTest { let host = self.host; let compiler = builder.compiler(0, host); - let mut cargo = tool::prepare_tool_cargo(builder, - compiler, - Mode::ToolBootstrap, - host, - "test", - "src/tools/compiletest", - SourceType::InTree, - &[]); + let cargo = tool::prepare_tool_cargo(builder, + compiler, + Mode::ToolBootstrap, + host, + "test", + "src/tools/compiletest", + SourceType::InTree, + &[]); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } @@ -571,7 +571,7 @@ impl Step for Clippy { builder.add_rustc_lib_path(compiler, &mut cargo); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("clippy-driver", ToolState::TestPass); } } else { @@ -1040,21 +1040,10 @@ impl Step for Compiletest { builder.ensure(compile::Rustc { compiler, target }); } - if builder.no_std(target) == Some(true) { - // the `test` doesn't compile for no-std targets - builder.ensure(compile::Std { compiler, target }); - } else { - builder.ensure(compile::Test { compiler, target }); - } - - if builder.no_std(target) == Some(true) { - // for no_std run-make (e.g., thumb*), - // we need a host compiler which is called by cargo. - builder.ensure(compile::Std { compiler, target: compiler.host }); - } + builder.ensure(compile::Std { compiler, target }); + // ensure that `libproc_macro` is available on the host. + builder.ensure(compile::Std { compiler, target: compiler.host }); - // HACK(eddyb) ensure that `libproc_macro` is available on the host. - builder.ensure(compile::Test { compiler, target: compiler.host }); // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); @@ -1338,7 +1327,10 @@ impl Step for Compiletest { cmd.env("RUSTC_PROFILER_SUPPORT", "1"); } - cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp")); + let tmp = builder.out.join("tmp"); + std::fs::create_dir_all(&tmp).unwrap(); + cmd.env("RUST_TEST_TMPDIR", tmp); + cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); @@ -1399,7 +1391,7 @@ impl Step for DocTest { fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; - builder.ensure(compile::Test { + builder.ensure(compile::Std { compiler, target: compiler.host, }); @@ -1535,8 +1527,7 @@ impl Step for ErrorIndex { ); tool.arg("markdown") .arg(&output) - .env("CFG_BUILD", &builder.config.build) - .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir()); + .env("CFG_BUILD", &builder.config.build); builder.info(&format!("Testing error-index stage{}", compiler.stage)); let _time = util::timeit(&builder); @@ -1710,8 +1701,7 @@ impl Step for Crate { fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run = run.krate("test"); - for krate in run.builder.in_tree_crates("std") { + for krate in run.builder.in_tree_crates("test") { if !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) { run = run.path(krate.local_path(&builder).to_str().unwrap()); } @@ -1735,14 +1725,9 @@ impl Step for Crate { }); }; - for krate in builder.in_tree_crates("std") { - if run.path.ends_with(&krate.local_path(&builder)) { - make(Mode::Std, krate); - } - } for krate in builder.in_tree_crates("test") { if run.path.ends_with(&krate.local_path(&builder)) { - make(Mode::Test, krate); + make(Mode::Std, krate); } } } @@ -1762,7 +1747,7 @@ impl Step for Crate { let test_kind = self.test_kind; let krate = self.krate; - builder.ensure(compile::Test { compiler, target }); + builder.ensure(compile::Std { compiler, target }); builder.ensure(RemoteCopyLibs { compiler, target }); // If we're not doing a full bootstrap but we're testing a stage2 @@ -1776,9 +1761,6 @@ impl Step for Crate { Mode::Std => { compile::std_cargo(builder, &compiler, target, &mut cargo); } - Mode::Test => { - compile::test_cargo(builder, &compiler, target, &mut cargo); - } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); compile::rustc_cargo(builder, &mut cargo); @@ -1832,20 +1814,6 @@ impl Step for Crate { .expect("nodejs not configured"), ); } else if target.starts_with("wasm32") { - // Warn about running tests without the `wasm_syscall` feature enabled. - // The javascript shim implements the syscall interface so that test - // output can be correctly reported. - if !builder.config.wasm_syscall { - builder.info( - "Libstd was built without `wasm_syscall` feature enabled: \ - test output may not be visible." - ); - } - - // On the wasm32-unknown-unknown target we're using LTO which is - // incompatible with `-C prefer-dynamic`, so disable that here - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - let node = builder .config .nodejs @@ -1869,7 +1837,7 @@ impl Step for Crate { test_kind, krate, compiler.stage, &compiler.host, target )); let _time = util::timeit(&builder); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } @@ -1937,20 +1905,10 @@ impl Step for CrateRustdoc { )); let _time = util::timeit(&builder); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } -fn envify(s: &str) -> String { - s.chars() - .map(|c| match c { - '-' => '_', - c => c, - }) - .flat_map(|c| c.to_uppercase()) - .collect() -} - /// Some test suites are run inside emulators or on remote devices, and most /// of our test binaries are linked dynamically which means we need to ship /// the standard library and such to the emulator ahead of time. This step @@ -1980,7 +1938,7 @@ impl Step for RemoteCopyLibs { return; } - builder.ensure(compile::Test { compiler, target }); + builder.ensure(compile::Std { compiler, target }); builder.info(&format!("REMOTE copy libs to emulator ({})", target)); t!(fs::create_dir_all(builder.out.join("tmp"))); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index df7eb7c455..f1baeafe26 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -8,7 +8,7 @@ use build_helper::t; use crate::Mode; use crate::Compiler; -use crate::builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::builder::{Step, RunConfig, ShouldRun, Builder, Cargo as CargoCommand}; use crate::util::{exe, add_lib_path, CiEnv}; use crate::compile; use crate::channel::GitInfo; @@ -63,7 +63,7 @@ impl Step for ToolBuild { _ => panic!("unexpected Mode for tool build") } - let mut cargo = prepare_tool_cargo( + let cargo = prepare_tool_cargo( builder, compiler, self.mode, @@ -76,7 +76,7 @@ impl Step for ToolBuild { builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { + let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" @@ -229,15 +229,11 @@ pub fn prepare_tool_cargo( path: &'static str, source_type: SourceType, extra_features: &[String], -) -> Command { +) -> CargoCommand { let mut cargo = builder.cargo(compiler, mode, target, command); let dir = builder.src.join(path); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); - // We don't want to build tools dynamically as they'll be running across - // stages and such and it's just easier if they're not dynamically linked. - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - if source_type == SourceType::Submodule { cargo.env("RUSTC_EXTERNAL_TOOL", "1"); } @@ -517,7 +513,7 @@ impl Step for Rustdoc { // libraries here. The intuition here is that If we've built a compiler, we should be able // to build rustdoc. - let mut cargo = prepare_tool_cargo( + let cargo = prepare_tool_cargo( builder, build_compiler, Mode::ToolRustc, @@ -530,7 +526,7 @@ impl Step for Rustdoc { builder.info(&format!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host)); - builder.run(&mut cargo); + builder.run(&mut cargo.into()); // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" @@ -577,12 +573,6 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - // Cargo depends on procedural macros, so make sure the host - // libstd/libproc_macro is available. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, @@ -650,31 +640,10 @@ macro_rules! tool_extended { tool_extended!((self, builder), Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {}; - CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", { - // Clippy depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; - Clippy, clippy, "src/tools/clippy", "clippy-driver", { - // Clippy depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; + CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", {}; + Clippy, clippy, "src/tools/clippy", "clippy-driver", {}; Miri, miri, "src/tools/miri", "miri", {}; - CargoMiri, miri, "src/tools/miri", "cargo-miri", { - // Miri depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; + CargoMiri, miri, "src/tools/miri", "cargo-miri", {}; Rls, rls, "src/tools/rls", "rls", { let clippy = builder.ensure(Clippy { compiler: self.compiler, @@ -684,12 +653,6 @@ tool_extended!((self, builder), if clippy.is_some() { self.extra_features.push("clippy".to_owned()); } - // RLS depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); }; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", {}; ); diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index a1aa18922b..f035a71191 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,6 +1,3 @@ -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -262,7 +259,7 @@ pub fn native_lib_boilerplate( if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) { Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), - out_dir: out_dir, + out_dir, }) } else { Err(()) diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 0c7c734e58..e81b7ef598 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -124,8 +124,6 @@ jobs: IMAGE: dist-x86_64-netbsd DEPLOY: 1 - asmjs: - IMAGE: asmjs i686-gnu: IMAGE: i686-gnu i686-gnu-nopt: @@ -236,10 +234,16 @@ jobs: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 i686-msvc-2: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-2 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 # MSVC aux tests x86_64-msvc-aux: MSYS_BITS: 64 @@ -250,6 +254,9 @@ jobs: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc VCVARS_BAT: vcvars64.bat + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 # MSVC tools tests x86_64-msvc-tools: MSYS_BITS: 64 @@ -272,7 +279,7 @@ jobs: i686-mingw-1: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 + SCRIPT: make ci-mingw-subset-1 MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 @@ -282,13 +289,13 @@ jobs: i686-mingw-2: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 + SCRIPT: make ci-mingw-subset-2 MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 x86_64-mingw-1: MSYS_BITS: 64 - SCRIPT: make ci-subset-1 + SCRIPT: make ci-mingw-subset-1 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z @@ -298,7 +305,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 x86_64-mingw-2: MSYS_BITS: 64 - SCRIPT: make ci-subset-2 + SCRIPT: make ci-mingw-subset-2 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z diff --git a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml index 9aaeb4b79d..bd4f1ed0ce 100644 --- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml +++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml @@ -18,9 +18,9 @@ steps: # one is MSI installers and one is EXE, but they're not used so frequently at # this point anyway so perhaps it's a wash! - script: | - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-08-22-is.exe" - is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- echo ##vso[task.prependpath]C:\Program Files (x86)\Inno Setup 5 + curl.exe -o is-install.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-08-22-is.exe + is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- displayName: Install InnoSetup condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) @@ -43,24 +43,18 @@ steps: # FIXME: we should probe the default azure image and see if we can use the MSYS2 # toolchain there. (if there's even one there). For now though this gets the job # done. -- script: | - set MSYS_PATH=%CD%\citools\msys64 - choco install msys2 --params="/InstallDir:%MSYS_PATH% /NoPath" -y - set PATH=%MSYS_PATH%\usr\bin;%PATH% - pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar - IF "%MINGW_URL%"=="" ( - IF "%MSYS_BITS%"=="32" pacman -S --noconfirm --needed mingw-w64-i686-toolchain mingw-w64-i686-cmake mingw-w64-i686-gcc mingw-w64-i686-python2 - IF "%MSYS_BITS%"=="64" pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-python2 - ) - where rev - rev --help - where make - - echo ##vso[task.setvariable variable=MSYS_PATH]%MSYS_PATH% - echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin +- bash: | + set -e + choco install msys2 --params="/InstallDir:$(System.Workfolder)/msys2 /NoPath" -y --no-progress + echo "##vso[task.prependpath]$(System.Workfolder)/msys2/usr/bin" + mkdir -p "$(System.Workfolder)/msys2/home/$USERNAME" displayName: Install msys2 condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) +- bash: pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar + displayName: Install msys2 base deps + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + # If we need to download a custom MinGW, do so here and set the path # appropriately. # @@ -81,39 +75,46 @@ steps: # # Note that we don't literally overwrite the gdb.exe binary because it appears # to just use gdborig.exe, so that's the binary we deal with instead. -- script: | - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" - 7z x -y %MINGW_ARCHIVE% > nul - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" - mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe - echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin +- bash: | + set -e + curl -o mingw.7z $MINGW_URL/$MINGW_ARCHIVE + 7z x -y mingw.7z > /dev/null + curl -o $MINGW_DIR/bin/gdborig.exe $MINGW_URL/2017-04-20-${MSYS_BITS}bit-gdborig.exe + echo "##vso[task.prependpath]`pwd`/$MINGW_DIR/bin" condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) displayName: Download custom MinGW -# Otherwise pull in the MinGW installed on appveyor -- script: | - echo ##vso[task.prependpath]%MSYS_PATH%\mingw%MSYS_BITS%\bin +# Otherwise install MinGW through `pacman` +- bash: | + set -e + arch=i686 + if [ "$MSYS_BITS" = "64" ]; then + arch=x86_64 + fi + pacman -S --noconfirm --needed mingw-w64-$arch-toolchain mingw-w64-$arch-cmake mingw-w64-$arch-gcc mingw-w64-$arch-python2 + echo "##vso[task.prependpath]$(System.Workfolder)/msys2/mingw$MSYS_BITS/bin" condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) - displayName: Add MinGW to path + displayName: Download standard MinGW # Make sure we use the native python interpreter instead of some msys equivalent # one way or another. The msys interpreters seem to have weird path conversions # baked in which break LLVM's build system one way or another, so let's use the # native version which keeps everything as native as possible. -- script: | - copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe - echo ##vso[task.prependpath]C:\Python27amd64 +- bash: | + set -e + cp C:/Python27amd64/python.exe C:/Python27amd64/python2.7.exe + echo "##vso[task.prependpath]C:/Python27amd64" displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) # Note that this is originally from the github releases patch of Ninja -- script: | - md ninja - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-03-15-ninja-win.zip" - 7z x -oninja 2017-03-15-ninja-win.zip - del 2017-03-15-ninja-win.zip - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja - echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - echo ##vso[task.prependpath]%CD%\ninja +- bash: | + set -e + mkdir ninja + curl -o ninja.zip https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-03-15-ninja-win.zip + 7z x -oninja ninja.zip + rm ninja.zip + echo "##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]$RUST_CONFIGURE_ARGS --enable-ninja" + echo "##vso[task.prependpath]`pwd`/ninja" displayName: Download and install ninja condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index a8791b4b3d..15a2499e46 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -147,8 +147,15 @@ steps: git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git cd rust-toolstate python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" + # Only check maintainers if this build is supposed to publish toolstate. + # Builds that are not supposed to publish don't have the access token. + if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then + TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 "${BUILD_SOURCESDIRECTORY}/src/tools/publish_toolstate.py" + fi cd .. rm -rf rust-toolstate + env: + TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['IMAGE'], 'mingw-check')) displayName: Verify the publish_toolstate script works @@ -201,7 +208,7 @@ steps: # Upload CPU usage statistics that we've been gathering this whole time. Always # execute this step in case we want to inspect failed builds, but don't let # errors here ever fail the build since this is just informational. -- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv +- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv env: AWS_ACCESS_KEY_ID: $(UPLOAD_AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY: $(UPLOAD_AWS_SECRET_ACCESS_KEY) diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 367e438499..a2d83eca24 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -165,8 +165,7 @@ For targets: `arm-unknown-linux-gnueabihf` For targets: `armv7-unknown-linux-gnueabihf` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches +- Path and misc options > Patches origin = Bundled only - Target options > Target Architecture = arm - Target options > Suffix to the arch-part = v7 - Target options > Architecture level = armv7-a -- (+) @@ -174,9 +173,9 @@ For targets: `armv7-unknown-linux-gnueabihf` - Target options > Floating point = hardware (FPU) -- (\*) - Target options > Default instruction set mode = thumb -- (\*) - Operating System > Target OS = linux -- Operating System > Linux kernel version = 3.2.72 -- Precise kernel -- C-library > glibc version = 2.16.0 -- C compiler > gcc version = 5.2.0 +- Operating System > Linux kernel version = 3.2.101 +- C-library > glibc version = 2.17.0 +- C compiler > gcc version = 8.3.0 - C compiler > C++ = ENABLE -- to cross compile LLVM (\*) These options have been selected to match the configuration of the arm diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 170b8134d3..417171a861 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -3,12 +3,7 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -# Ubuntu 16.04 (this container) ships with make 4, but something in the -# toolchains we build below chokes on that, so go back to make 3 -COPY scripts/make3.sh /scripts/ -RUN sh /scripts/make3.sh - -COPY scripts/crosstool-ng.sh /scripts/ +COPY dist-armv7-linux/crosstool-ng.sh /scripts/ RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ @@ -16,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp -COPY dist-armv7-linux/patches/ /tmp/patches/ COPY dist-armv7-linux/build-toolchains.sh dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/ RUN ./build-toolchains.sh diff --git a/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config b/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config index 5cccfd8444..81b3d7477e 100644 --- a/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config +++ b/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config @@ -1,9 +1,32 @@ # # Automatically generated file; DO NOT EDIT. -# Crosstool-NG Configuration -# -CT_CONFIGURE_has_make381=y -CT_CONFIGURE_has_xz=y +# crosstool-NG Configuration +# +CT_CONFIGURE_has_static_link=y +CT_CONFIGURE_has_cxx11=y +CT_CONFIGURE_has_wget=y +CT_CONFIGURE_has_curl=y +CT_CONFIGURE_has_make_3_81_or_newer=y +CT_CONFIGURE_has_make_4_0_or_newer=y +CT_CONFIGURE_has_libtool_2_4_or_newer=y +CT_CONFIGURE_has_libtoolize_2_4_or_newer=y +CT_CONFIGURE_has_autoconf_2_65_or_newer=y +CT_CONFIGURE_has_autoreconf_2_65_or_newer=y +CT_CONFIGURE_has_automake_1_15_or_newer=y +CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y +CT_CONFIGURE_has_python_3_4_or_newer=y +CT_CONFIGURE_has_bison_2_7_or_newer=y +CT_CONFIGURE_has_python=y +CT_CONFIGURE_has_dtc=y +CT_CONFIGURE_has_svn=y +CT_CONFIGURE_has_git=y +CT_CONFIGURE_has_md5sum=y +CT_CONFIGURE_has_sha1sum=y +CT_CONFIGURE_has_sha256sum=y +CT_CONFIGURE_has_sha512sum=y +CT_CONFIGURE_has_install_with_strip_program=y +CT_CONFIG_VERSION_CURRENT="3" +CT_CONFIG_VERSION="3" CT_MODULES=y # @@ -21,40 +44,46 @@ CT_MODULES=y # Paths # CT_LOCAL_TARBALLS_DIR="" +# CT_TARBALLS_BUILDROOT_LAYOUT is not set CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" -CT_INSTALL_DIR="${CT_PREFIX_DIR}" CT_RM_RF_PREFIX_DIR=y CT_REMOVE_DOCS=y -CT_INSTALL_DIR_RO=y +CT_INSTALL_LICENSES=y +CT_PREFIX_DIR_RO=y CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set # # Downloading # +CT_DOWNLOAD_AGENT_WGET=y +# CT_DOWNLOAD_AGENT_CURL is not set +# CT_DOWNLOAD_AGENT_NONE is not set # CT_FORBID_DOWNLOAD is not set # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 +CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary" # CT_ONLY_DOWNLOAD is not set # CT_USE_MIRROR is not set +CT_VERIFY_DOWNLOAD_DIGEST=y +CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y +# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set +CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512" +# CT_VERIFY_DOWNLOAD_SIGNATURE is not set # # Extracting # # CT_FORCE_EXTRACT is not set -CT_OVERIDE_CONFIG_GUESS_SUB=y +CT_OVERRIDE_CONFIG_GUESS_SUB=y # CT_ONLY_EXTRACT is not set -# CT_PATCH_BUNDLED is not set -# CT_PATCH_LOCAL is not set -CT_PATCH_BUNDLED_LOCAL=y -# CT_PATCH_LOCAL_BUNDLED is not set -# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set -# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set -# CT_PATCH_NONE is not set -CT_PATCH_ORDER="bundled,local" -CT_PATCH_USE_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" +CT_PATCH_BUNDLED=y +# CT_PATCH_BUNDLED_LOCAL is not set +CT_PATCH_ORDER="bundled" # # Build behavior @@ -90,86 +119,81 @@ CT_LOG_FILE_COMPRESS=y # # Target options # +# CT_ARCH_ALPHA is not set +# CT_ARCH_ARC is not set +CT_ARCH_ARM=y +# CT_ARCH_AVR is not set +# CT_ARCH_M68K is not set +# CT_ARCH_MIPS is not set +# CT_ARCH_NIOS2 is not set +# CT_ARCH_POWERPC is not set +# CT_ARCH_S390 is not set +# CT_ARCH_SH is not set +# CT_ARCH_SPARC is not set +# CT_ARCH_X86 is not set +# CT_ARCH_XTENSA is not set CT_ARCH="arm" -CT_ARCH_SUPPORTS_BOTH_MMU=y -CT_ARCH_SUPPORTS_BOTH_ENDIAN=y -CT_ARCH_SUPPORTS_32=y -CT_ARCH_SUPPORTS_64=y -CT_ARCH_SUPPORTS_WITH_ARCH=y -CT_ARCH_SUPPORTS_WITH_CPU=y -CT_ARCH_SUPPORTS_WITH_TUNE=y -CT_ARCH_SUPPORTS_WITH_FLOAT=y -CT_ARCH_SUPPORTS_WITH_FPU=y -CT_ARCH_SUPPORTS_SOFTFP=y -CT_ARCH_DEFAULT_HAS_MMU=y -CT_ARCH_DEFAULT_LE=y -CT_ARCH_DEFAULT_32=y -CT_ARCH_ARCH="armv7-a" +CT_ARCH_CHOICE_KSYM="ARM" CT_ARCH_CPU="" CT_ARCH_TUNE="" -CT_ARCH_FPU="vfpv3-d16" -# CT_ARCH_BE is not set -CT_ARCH_LE=y -CT_ARCH_32=y -# CT_ARCH_64 is not set -CT_ARCH_BITNESS=32 -CT_ARCH_FLOAT_HW=y -# CT_ARCH_FLOAT_SW is not set -CT_TARGET_CFLAGS="" -CT_TARGET_LDFLAGS="" -# CT_ARCH_alpha is not set -CT_ARCH_arm=y -# CT_ARCH_avr is not set -# CT_ARCH_m68k is not set -# CT_ARCH_mips is not set -# CT_ARCH_nios2 is not set -# CT_ARCH_powerpc is not set -# CT_ARCH_s390 is not set -# CT_ARCH_sh is not set -# CT_ARCH_sparc is not set -# CT_ARCH_x86 is not set -# CT_ARCH_xtensa is not set -CT_ARCH_alpha_AVAILABLE=y -CT_ARCH_arm_AVAILABLE=y -CT_ARCH_avr_AVAILABLE=y -CT_ARCH_m68k_AVAILABLE=y -CT_ARCH_microblaze_AVAILABLE=y -CT_ARCH_mips_AVAILABLE=y -CT_ARCH_nios2_AVAILABLE=y -CT_ARCH_powerpc_AVAILABLE=y -CT_ARCH_s390_AVAILABLE=y -CT_ARCH_sh_AVAILABLE=y -CT_ARCH_sparc_AVAILABLE=y -CT_ARCH_x86_AVAILABLE=y -CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_ARM_SHOW=y + +# +# Options for arm +# +CT_ARCH_ARM_PKG_KSYM="" +CT_ARCH_ARM_MODE="thumb" +# CT_ARCH_ARM_MODE_ARM is not set +CT_ARCH_ARM_MODE_THUMB=y +# CT_ARCH_ARM_INTERWORKING is not set +CT_ARCH_ARM_EABI_FORCE=y +CT_ARCH_ARM_EABI=y +CT_ARCH_ARM_TUPLE_USE_EABIHF=y +CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA" CT_ARCH_SUFFIX="v7" +# CT_OMIT_TARGET_VENDOR is not set # # Generic target options # # CT_MULTILIB is not set +CT_DEMULTILIB=y +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_DEFAULT_HAS_MMU=y CT_ARCH_USE_MMU=y +CT_ARCH_SUPPORTS_FLAT_FORMAT=y +CT_ARCH_SUPPORTS_EITHER_ENDIAN=y +CT_ARCH_DEFAULT_LE=y +# CT_ARCH_BE is not set +CT_ARCH_LE=y CT_ARCH_ENDIAN="little" +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_BITNESS=32 +CT_ARCH_32=y +# CT_ARCH_64 is not set # # Target optimisations # +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_SUPPORTS_SOFTFP=y CT_ARCH_EXCLUSIVE_WITH_CPU=y +CT_ARCH_ARCH="armv7-a" +CT_ARCH_FPU="vfpv3-d16" # CT_ARCH_FLOAT_AUTO is not set +CT_ARCH_FLOAT_HW=y # CT_ARCH_FLOAT_SOFTFP is not set +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" CT_ARCH_FLOAT="hard" -# -# arm other options -# -CT_ARCH_ARM_MODE="thumb" -# CT_ARCH_ARM_MODE_ARM is not set -CT_ARCH_ARM_MODE_THUMB=y -# CT_ARCH_ARM_INTERWORKING is not set -CT_ARCH_ARM_EABI_FORCE=y -CT_ARCH_ARM_EABI=y -CT_ARCH_ARM_TUPLE_USE_EABIHF=y - # # Toolchain options # @@ -182,7 +206,9 @@ CT_USE_SYSROOT=y CT_SYSROOT_NAME="sysroot" CT_SYSROOT_DIR_PREFIX="" CT_WANTS_STATIC_LINK=y +CT_WANTS_STATIC_LINK_CXX=y # CT_STATIC_TOOLCHAIN is not set +CT_SHOW_CT_VERSION=y CT_TOOLCHAIN_PKGVERSION="" CT_TOOLCHAIN_BUGURL="" @@ -216,126 +242,207 @@ CT_BUILD_SUFFIX="" # Operating System # CT_KERNEL_SUPPORTS_SHARED_LIBS=y +# CT_KERNEL_BARE_METAL is not set +CT_KERNEL_LINUX=y CT_KERNEL="linux" -CT_KERNEL_VERSION="3.2.72" -# CT_KERNEL_bare_metal is not set -CT_KERNEL_linux=y -CT_KERNEL_bare_metal_AVAILABLE=y -CT_KERNEL_linux_AVAILABLE=y -# CT_KERNEL_V_4_3 is not set -# CT_KERNEL_V_4_2 is not set -# CT_KERNEL_V_4_1 is not set -# CT_KERNEL_V_3_18 is not set -# CT_KERNEL_V_3_14 is not set -# CT_KERNEL_V_3_12 is not set -# CT_KERNEL_V_3_10 is not set -# CT_KERNEL_V_3_4 is not set -CT_KERNEL_V_3_2=y -# CT_KERNEL_V_2_6_32 is not set -# CT_KERNEL_LINUX_CUSTOM is not set -CT_KERNEL_windows_AVAILABLE=y - -# -# Common kernel options -# -CT_SHARED_LIBS=y - -# -# linux other options -# +CT_KERNEL_CHOICE_KSYM="LINUX" +CT_KERNEL_LINUX_SHOW=y + +# +# Options for linux +# +CT_KERNEL_LINUX_PKG_KSYM="LINUX" +CT_LINUX_DIR_NAME="linux" +CT_LINUX_PKG_NAME="linux" +CT_LINUX_SRC_RELEASE=y +CT_LINUX_PATCH_ORDER="global" +# CT_LINUX_V_4_20 is not set +# CT_LINUX_V_4_19 is not set +# CT_LINUX_V_4_18 is not set +# CT_LINUX_V_4_17 is not set +# CT_LINUX_V_4_16 is not set +# CT_LINUX_V_4_15 is not set +# CT_LINUX_V_4_14 is not set +# CT_LINUX_V_4_13 is not set +# CT_LINUX_V_4_12 is not set +# CT_LINUX_V_4_11 is not set +# CT_LINUX_V_4_10 is not set +# CT_LINUX_V_4_9 is not set +# CT_LINUX_V_4_4 is not set +# CT_LINUX_V_4_1 is not set +# CT_LINUX_V_3_16 is not set +# CT_LINUX_V_3_13 is not set +# CT_LINUX_V_3_12 is not set +# CT_LINUX_V_3_10 is not set +# CT_LINUX_V_3_4 is not set +CT_LINUX_V_3_2=y +# CT_LINUX_V_2_6_32 is not set +# CT_LINUX_NO_VERSIONS is not set +CT_LINUX_VERSION="3.2.101" +CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})" +CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign" +CT_LINUX_4_8_or_older=y +CT_LINUX_older_than_4_8=y +CT_LINUX_3_7_or_older=y +CT_LINUX_older_than_3_7=y +CT_LINUX_later_than_3_2=y +CT_LINUX_3_2_or_later=y CT_KERNEL_LINUX_VERBOSITY_0=y # CT_KERNEL_LINUX_VERBOSITY_1 is not set # CT_KERNEL_LINUX_VERBOSITY_2 is not set CT_KERNEL_LINUX_VERBOSE_LEVEL=0 CT_KERNEL_LINUX_INSTALL_CHECK=y +CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS" + +# +# Common kernel options +# +CT_SHARED_LIBS=y # # Binary utilities # CT_ARCH_BINFMT_ELF=y +CT_BINUTILS_BINUTILS=y CT_BINUTILS="binutils" -CT_BINUTILS_binutils=y +CT_BINUTILS_CHOICE_KSYM="BINUTILS" +CT_BINUTILS_BINUTILS_SHOW=y + +# +# Options for binutils +# +CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS" +CT_BINUTILS_DIR_NAME="binutils" +CT_BINUTILS_USE_GNU=y +CT_BINUTILS_USE="BINUTILS" +CT_BINUTILS_PKG_NAME="binutils" +CT_BINUTILS_SRC_RELEASE=y +CT_BINUTILS_PATCH_ORDER="global" +CT_BINUTILS_V_2_32=y +# CT_BINUTILS_V_2_31 is not set +# CT_BINUTILS_V_2_30 is not set +# CT_BINUTILS_V_2_29 is not set +# CT_BINUTILS_V_2_28 is not set +# CT_BINUTILS_V_2_27 is not set +# CT_BINUTILS_V_2_26 is not set +# CT_BINUTILS_NO_VERSIONS is not set +CT_BINUTILS_VERSION="2.32" +CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)" +CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig" +CT_BINUTILS_later_than_2_30=y +CT_BINUTILS_2_30_or_later=y +CT_BINUTILS_later_than_2_27=y +CT_BINUTILS_2_27_or_later=y +CT_BINUTILS_later_than_2_25=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_later_than_2_23=y +CT_BINUTILS_2_23_or_later=y # # GNU binutils # -# CT_CC_BINUTILS_SHOW_LINARO is not set -CT_BINUTILS_V_2_25_1=y -# CT_BINUTILS_V_2_25 is not set -# CT_BINUTILS_V_2_24 is not set -# CT_BINUTILS_V_2_23_2 is not set -# CT_BINUTILS_V_2_23_1 is not set -# CT_BINUTILS_V_2_22 is not set -# CT_BINUTILS_V_2_21_53 is not set -# CT_BINUTILS_V_2_21_1a is not set -# CT_BINUTILS_V_2_20_1a is not set -# CT_BINUTILS_V_2_19_1a is not set -# CT_BINUTILS_V_2_18a is not set -CT_BINUTILS_VERSION="2.25.1" -CT_BINUTILS_2_25_1_or_later=y -CT_BINUTILS_2_25_or_later=y -CT_BINUTILS_2_24_or_later=y -CT_BINUTILS_2_23_or_later=y -CT_BINUTILS_2_22_or_later=y -CT_BINUTILS_2_21_or_later=y -CT_BINUTILS_2_20_or_later=y -CT_BINUTILS_2_19_or_later=y -CT_BINUTILS_2_18_or_later=y CT_BINUTILS_HAS_HASH_STYLE=y CT_BINUTILS_HAS_GOLD=y -CT_BINUTILS_GOLD_SUPPORTS_ARCH=y -CT_BINUTILS_GOLD_SUPPORT=y CT_BINUTILS_HAS_PLUGINS=y CT_BINUTILS_HAS_PKGVERSION_BUGURL=y -CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y CT_BINUTILS_LINKER_LD=y # CT_BINUTILS_LINKER_LD_GOLD is not set -# CT_BINUTILS_LINKER_GOLD_LD is not set CT_BINUTILS_LINKERS_LIST="ld" CT_BINUTILS_LINKER_DEFAULT="bfd" # CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_RELRO=m CT_BINUTILS_EXTRA_CONFIG_ARRAY="" # CT_BINUTILS_FOR_TARGET is not set - -# -# binutils other options -# +CT_ALL_BINUTILS_CHOICES="BINUTILS" # # C-library # +CT_LIBC_GLIBC=y +# CT_LIBC_UCLIBC is not set CT_LIBC="glibc" -CT_LIBC_VERSION="2.16.0" -CT_LIBC_glibc=y -# CT_LIBC_musl is not set -# CT_LIBC_uClibc is not set -CT_LIBC_avr_libc_AVAILABLE=y -CT_LIBC_glibc_AVAILABLE=y +CT_LIBC_CHOICE_KSYM="GLIBC" CT_THREADS="nptl" -# CT_CC_GLIBC_SHOW_LINARO is not set -# CT_LIBC_GLIBC_V_2_22 is not set -# CT_LIBC_GLIBC_V_2_21 is not set -# CT_LIBC_GLIBC_V_2_20 is not set -# CT_LIBC_GLIBC_V_2_19 is not set -# CT_LIBC_GLIBC_V_2_18 is not set -# CT_LIBC_GLIBC_V_2_17 is not set -CT_LIBC_GLIBC_V_2_16_0=y -# CT_LIBC_GLIBC_V_2_15 is not set -# CT_LIBC_GLIBC_V_2_14_1 is not set -# CT_LIBC_GLIBC_V_2_14 is not set -# CT_LIBC_GLIBC_V_2_13 is not set -# CT_LIBC_GLIBC_V_2_12_2 is not set -# CT_LIBC_GLIBC_V_2_12_1 is not set -# CT_LIBC_GLIBC_V_2_11_1 is not set -# CT_LIBC_GLIBC_V_2_11 is not set -# CT_LIBC_GLIBC_V_2_10_1 is not set -# CT_LIBC_GLIBC_V_2_9 is not set -# CT_LIBC_GLIBC_V_2_8 is not set -CT_LIBC_mingw_AVAILABLE=y -CT_LIBC_musl_AVAILABLE=y -CT_LIBC_newlib_AVAILABLE=y -CT_LIBC_none_AVAILABLE=y -CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_GLIBC_SHOW=y + +# +# Options for glibc +# +CT_LIBC_GLIBC_PKG_KSYM="GLIBC" +CT_GLIBC_DIR_NAME="glibc" +CT_GLIBC_USE_GNU=y +CT_GLIBC_USE="GLIBC" +CT_GLIBC_PKG_NAME="glibc" +CT_GLIBC_SRC_RELEASE=y +CT_GLIBC_PATCH_ORDER="global" +# CT_GLIBC_V_2_29 is not set +# CT_GLIBC_V_2_28 is not set +# CT_GLIBC_V_2_27 is not set +# CT_GLIBC_V_2_26 is not set +# CT_GLIBC_V_2_25 is not set +# CT_GLIBC_V_2_24 is not set +# CT_GLIBC_V_2_23 is not set +# CT_GLIBC_V_2_19 is not set +CT_GLIBC_V_2_17=y +# CT_GLIBC_V_2_12_1 is not set +# CT_GLIBC_NO_VERSIONS is not set +CT_GLIBC_VERSION="2.17" +CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)" +CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_GLIBC_SIGNATURE_FORMAT="packed/.sig" +CT_GLIBC_2_29_or_older=y +CT_GLIBC_older_than_2_29=y +CT_GLIBC_2_27_or_older=y +CT_GLIBC_older_than_2_27=y +CT_GLIBC_2_26_or_older=y +CT_GLIBC_older_than_2_26=y +CT_GLIBC_2_25_or_older=y +CT_GLIBC_older_than_2_25=y +CT_GLIBC_2_24_or_older=y +CT_GLIBC_older_than_2_24=y +CT_GLIBC_2_23_or_older=y +CT_GLIBC_older_than_2_23=y +CT_GLIBC_2_20_or_older=y +CT_GLIBC_older_than_2_20=y +CT_GLIBC_2_17_or_later=y +CT_GLIBC_2_17_or_older=y +CT_GLIBC_later_than_2_14=y +CT_GLIBC_2_14_or_later=y +CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y +CT_GLIBC_DEP_BINUTILS=y +CT_GLIBC_DEP_GCC=y +CT_GLIBC_DEP_PYTHON=y +CT_GLIBC_HAS_NPTL_ADDON=y +CT_GLIBC_HAS_PORTS_ADDON=y +CT_GLIBC_HAS_LIBIDN_ADDON=y +CT_GLIBC_USE_PORTS_ADDON=y +CT_GLIBC_USE_NPTL_ADDON=y +# CT_GLIBC_USE_LIBIDN_ADDON is not set +CT_GLIBC_HAS_OBSOLETE_RPC=y +CT_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_GLIBC_CONFIGPARMS="" +CT_GLIBC_EXTRA_CFLAGS="" +CT_GLIBC_ENABLE_OBSOLETE_RPC=y +# CT_GLIBC_DISABLE_VERSIONING is not set +CT_GLIBC_OLDEST_ABI="" +CT_GLIBC_FORCE_UNWIND=y +# CT_GLIBC_LOCALES is not set +# CT_GLIBC_KERNEL_VERSION_NONE is not set +CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_GLIBC_MIN_KERNEL="3.2.101" +CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC" CT_LIBC_SUPPORT_THREADS_ANY=y CT_LIBC_SUPPORT_THREADS_NATIVE=y @@ -343,100 +450,71 @@ CT_LIBC_SUPPORT_THREADS_NATIVE=y # Common C library options # CT_THREADS_NATIVE=y +# CT_CREATE_LDSO_CONF is not set CT_LIBC_XLDD=y -# -# glibc other options -# -CT_LIBC_GLIBC_PORTS_EXTERNAL=y -CT_LIBC_GLIBC_MAY_FORCE_PORTS=y -CT_LIBC_glibc_familly=y -CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" -CT_LIBC_GLIBC_CONFIGPARMS="" -CT_LIBC_GLIBC_EXTRA_CFLAGS="" -CT_LIBC_EXTRA_CC_ARGS="" -# CT_LIBC_DISABLE_VERSIONING is not set -CT_LIBC_OLDEST_ABI="" -CT_LIBC_GLIBC_FORCE_UNWIND=y -CT_LIBC_GLIBC_USE_PORTS=y -CT_LIBC_ADDONS_LIST="" - -# -# WARNING !!! -# - -# -# For glibc >= 2.8, it can happen that the tarballs -# - -# -# for the addons are not available for download. -# - -# -# If that happens, bad luck... Try a previous version -# - -# -# or try again later... :-( -# -# CT_LIBC_LOCALES is not set -# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set -CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y -# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set -CT_LIBC_GLIBC_MIN_KERNEL="3.2.72" - # # C compiler # -CT_CC="gcc" CT_CC_CORE_PASSES_NEEDED=y CT_CC_CORE_PASS_1_NEEDED=y CT_CC_CORE_PASS_2_NEEDED=y -CT_CC_gcc=y -# CT_CC_GCC_SHOW_LINARO is not set -CT_CC_GCC_V_5_2_0=y -# CT_CC_GCC_V_4_9_3 is not set -# CT_CC_GCC_V_4_8_5 is not set -# CT_CC_GCC_V_4_7_4 is not set -# CT_CC_GCC_V_4_6_4 is not set -# CT_CC_GCC_V_4_5_4 is not set -# CT_CC_GCC_V_4_4_7 is not set -# CT_CC_GCC_V_4_3_6 is not set -# CT_CC_GCC_V_4_2_4 is not set -CT_CC_GCC_4_2_or_later=y -CT_CC_GCC_4_3_or_later=y -CT_CC_GCC_4_4_or_later=y -CT_CC_GCC_4_5_or_later=y -CT_CC_GCC_4_6_or_later=y -CT_CC_GCC_4_7_or_later=y -CT_CC_GCC_4_8_or_later=y -CT_CC_GCC_4_9_or_later=y -CT_CC_GCC_5=y -CT_CC_GCC_5_or_later=y -CT_CC_GCC_HAS_GRAPHITE=y -CT_CC_GCC_USE_GRAPHITE=y -CT_CC_GCC_HAS_LTO=y -CT_CC_GCC_USE_LTO=y -CT_CC_GCC_HAS_PKGVERSION_BUGURL=y -CT_CC_GCC_HAS_BUILD_ID=y -CT_CC_GCC_HAS_LNK_HASH_STYLE=y -CT_CC_GCC_USE_GMP_MPFR=y -CT_CC_GCC_USE_MPC=y -CT_CC_GCC_HAS_LIBQUADMATH=y -CT_CC_GCC_HAS_LIBSANITIZER=y -CT_CC_GCC_VERSION="5.2.0" -# CT_CC_LANG_FORTRAN is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y +CT_CC_GCC=y +CT_CC="gcc" +CT_CC_CHOICE_KSYM="GCC" +CT_CC_GCC_SHOW=y + +# +# Options for gcc +# +CT_CC_GCC_PKG_KSYM="GCC" +CT_GCC_DIR_NAME="gcc" +CT_GCC_USE_GNU=y +CT_GCC_USE="GCC" +CT_GCC_PKG_NAME="gcc" +CT_GCC_SRC_RELEASE=y +CT_GCC_PATCH_ORDER="global" +CT_GCC_V_8=y +# CT_GCC_V_7 is not set +# CT_GCC_V_6 is not set +# CT_GCC_V_5 is not set +# CT_GCC_V_4_9 is not set +# CT_GCC_NO_VERSIONS is not set +CT_GCC_VERSION="8.3.0" +CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})" +CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_GCC_SIGNATURE_FORMAT="" +CT_GCC_later_than_7=y +CT_GCC_7_or_later=y +CT_GCC_later_than_6=y +CT_GCC_6_or_later=y +CT_GCC_later_than_5=y +CT_GCC_5_or_later=y +CT_GCC_later_than_4_9=y +CT_GCC_4_9_or_later=y +CT_GCC_later_than_4_8=y +CT_GCC_4_8_or_later=y +CT_CC_GCC_HAS_LIBMPX=y CT_CC_GCC_ENABLE_CXX_FLAGS="" CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" CT_CC_GCC_EXTRA_CONFIG_ARRAY="" -CT_CC_GCC_EXTRA_ENV_ARRAY="" CT_CC_GCC_STATIC_LIBSTDCXX=y # CT_CC_GCC_SYSTEM_ZLIB is not set +CT_CC_GCC_CONFIG_TLS=m # # Optimisation features # +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_USE_LTO=y # # Settings for libraries running on target @@ -465,97 +543,206 @@ CT_CC_GCC_DEC_FLOAT_AUTO=y # CT_CC_GCC_DEC_FLOAT_BID is not set # CT_CC_GCC_DEC_FLOAT_DPD is not set # CT_CC_GCC_DEC_FLOATS_NO is not set -CT_CC_SUPPORT_CXX=y -CT_CC_SUPPORT_FORTRAN=y -CT_CC_SUPPORT_JAVA=y -CT_CC_SUPPORT_ADA=y -CT_CC_SUPPORT_OBJC=y -CT_CC_SUPPORT_OBJCXX=y -CT_CC_SUPPORT_GOLANG=y +CT_ALL_CC_CHOICES="GCC" # # Additional supported languages: # CT_CC_LANG_CXX=y -# CT_CC_LANG_JAVA is not set +# CT_CC_LANG_FORTRAN is not set # # Debug facilities # -# CT_DEBUG_dmalloc is not set -# CT_DEBUG_duma is not set -# CT_DEBUG_gdb is not set -# CT_DEBUG_ltrace is not set -# CT_DEBUG_strace is not set +# CT_DEBUG_DUMA is not set +# CT_DEBUG_GDB is not set +# CT_DEBUG_LTRACE is not set +# CT_DEBUG_STRACE is not set +CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE" # # Companion libraries # -CT_COMPLIBS_NEEDED=y +# CT_COMPLIBS_CHECK is not set +# CT_COMP_LIBS_CLOOG is not set +# CT_COMP_LIBS_EXPAT is not set +CT_COMP_LIBS_GETTEXT=y +CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT" +CT_GETTEXT_DIR_NAME="gettext" +CT_GETTEXT_PKG_NAME="gettext" +CT_GETTEXT_SRC_RELEASE=y +CT_GETTEXT_PATCH_ORDER="global" +CT_GETTEXT_V_0_19_8_1=y +# CT_GETTEXT_NO_VERSIONS is not set +CT_GETTEXT_VERSION="0.19.8.1" +CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)" +CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz" +CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_GMP=y +CT_COMP_LIBS_GMP_PKG_KSYM="GMP" +CT_GMP_DIR_NAME="gmp" +CT_GMP_PKG_NAME="gmp" +CT_GMP_SRC_RELEASE=y +CT_GMP_PATCH_ORDER="global" +CT_GMP_V_6_1=y +# CT_GMP_NO_VERSIONS is not set +CT_GMP_VERSION="6.1.2" +CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)" +CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2" +CT_GMP_SIGNATURE_FORMAT="packed/.sig" +CT_GMP_later_than_5_1_0=y +CT_GMP_5_1_0_or_later=y +CT_GMP_later_than_5_0_0=y +CT_GMP_5_0_0_or_later=y +CT_COMP_LIBS_ISL=y +CT_COMP_LIBS_ISL_PKG_KSYM="ISL" +CT_ISL_DIR_NAME="isl" +CT_ISL_PKG_NAME="isl" +CT_ISL_SRC_RELEASE=y +CT_ISL_PATCH_ORDER="global" +CT_ISL_V_0_20=y +# CT_ISL_V_0_19 is not set +# CT_ISL_V_0_18 is not set +# CT_ISL_V_0_17 is not set +# CT_ISL_V_0_16 is not set +# CT_ISL_V_0_15 is not set +# CT_ISL_NO_VERSIONS is not set +CT_ISL_VERSION="0.20" +CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_ISL_SIGNATURE_FORMAT="" +CT_ISL_later_than_0_18=y +CT_ISL_0_18_or_later=y +CT_ISL_later_than_0_15=y +CT_ISL_0_15_or_later=y +CT_ISL_REQUIRE_0_15_or_later=y +CT_ISL_later_than_0_14=y +CT_ISL_0_14_or_later=y +CT_ISL_REQUIRE_0_14_or_later=y +CT_ISL_later_than_0_13=y +CT_ISL_0_13_or_later=y +CT_ISL_later_than_0_12=y +CT_ISL_0_12_or_later=y +CT_ISL_REQUIRE_0_12_or_later=y +# CT_COMP_LIBS_LIBELF is not set +CT_COMP_LIBS_LIBICONV=y +CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV" +CT_LIBICONV_DIR_NAME="libiconv" +CT_LIBICONV_PKG_NAME="libiconv" +CT_LIBICONV_SRC_RELEASE=y +CT_LIBICONV_PATCH_ORDER="global" +CT_LIBICONV_V_1_15=y +# CT_LIBICONV_NO_VERSIONS is not set +CT_LIBICONV_VERSION="1.15" +CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)" +CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz" +CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_MPC=y +CT_COMP_LIBS_MPC_PKG_KSYM="MPC" +CT_MPC_DIR_NAME="mpc" +CT_MPC_PKG_NAME="mpc" +CT_MPC_SRC_RELEASE=y +CT_MPC_PATCH_ORDER="global" +# CT_MPC_V_1_1 is not set +CT_MPC_V_1_0=y +# CT_MPC_NO_VERSIONS is not set +CT_MPC_VERSION="1.0.3" +CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)" +CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_FORMATS=".tar.gz" +CT_MPC_SIGNATURE_FORMAT="packed/.sig" +CT_MPC_1_1_0_or_older=y +CT_MPC_older_than_1_1_0=y +CT_COMP_LIBS_MPFR=y +CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR" +CT_MPFR_DIR_NAME="mpfr" +CT_MPFR_PKG_NAME="mpfr" +CT_MPFR_SRC_RELEASE=y +CT_MPFR_PATCH_ORDER="global" +CT_MPFR_V_3_1=y +# CT_MPFR_NO_VERSIONS is not set +CT_MPFR_VERSION="3.1.6" +CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)" +CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip" +CT_MPFR_SIGNATURE_FORMAT="packed/.asc" +CT_MPFR_4_0_0_or_older=y +CT_MPFR_older_than_4_0_0=y +CT_MPFR_REQUIRE_older_than_4_0_0=y +CT_MPFR_later_than_3_0_0=y +CT_MPFR_3_0_0_or_later=y +CT_COMP_LIBS_NCURSES=y +CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES" +CT_NCURSES_DIR_NAME="ncurses" +CT_NCURSES_PKG_NAME="ncurses" +CT_NCURSES_SRC_RELEASE=y +CT_NCURSES_PATCH_ORDER="global" +CT_NCURSES_V_6_1=y +# CT_NCURSES_V_6_0 is not set +# CT_NCURSES_NO_VERSIONS is not set +CT_NCURSES_VERSION="6.1" +CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)" +CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_FORMATS=".tar.gz" +CT_NCURSES_SIGNATURE_FORMAT="packed/.sig" +CT_NCURSES_HOST_CONFIG_ARGS="" +CT_NCURSES_HOST_DISABLE_DB=y +CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100" +CT_NCURSES_TARGET_CONFIG_ARGS="" +# CT_NCURSES_TARGET_DISABLE_DB is not set +CT_NCURSES_TARGET_FALLBACKS="" +CT_COMP_LIBS_ZLIB=y +CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB" +CT_ZLIB_DIR_NAME="zlib" +CT_ZLIB_PKG_NAME="zlib" +CT_ZLIB_SRC_RELEASE=y +CT_ZLIB_PATCH_ORDER="global" +CT_ZLIB_V_1_2_11=y +# CT_ZLIB_NO_VERSIONS is not set +CT_ZLIB_VERSION="1.2.11" +CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}" +CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_ZLIB_SIGNATURE_FORMAT="packed/.asc" +CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB" CT_LIBICONV_NEEDED=y CT_GETTEXT_NEEDED=y CT_GMP_NEEDED=y CT_MPFR_NEEDED=y CT_ISL_NEEDED=y CT_MPC_NEEDED=y -CT_COMPLIBS=y +CT_NCURSES_NEEDED=y +CT_ZLIB_NEEDED=y CT_LIBICONV=y CT_GETTEXT=y CT_GMP=y CT_MPFR=y CT_ISL=y CT_MPC=y -CT_LIBICONV_V_1_14=y -CT_LIBICONV_VERSION="1.14" -CT_GETTEXT_V_0_19_6=y -CT_GETTEXT_VERSION="0.19.6" -CT_GMP_V_6_0_0=y -# CT_GMP_V_5_1_3 is not set -# CT_GMP_V_5_1_1 is not set -# CT_GMP_V_5_0_2 is not set -# CT_GMP_V_5_0_1 is not set -# CT_GMP_V_4_3_2 is not set -# CT_GMP_V_4_3_1 is not set -# CT_GMP_V_4_3_0 is not set -CT_GMP_5_0_2_or_later=y -CT_GMP_VERSION="6.0.0a" -CT_MPFR_V_3_1_3=y -# CT_MPFR_V_3_1_2 is not set -# CT_MPFR_V_3_1_0 is not set -# CT_MPFR_V_3_0_1 is not set -# CT_MPFR_V_3_0_0 is not set -# CT_MPFR_V_2_4_2 is not set -# CT_MPFR_V_2_4_1 is not set -# CT_MPFR_V_2_4_0 is not set -CT_MPFR_VERSION="3.1.3" -CT_ISL_V_0_14=y -# CT_ISL_V_0_12_2 is not set -CT_ISL_V_0_14_or_later=y -CT_ISL_V_0_12_or_later=y -CT_ISL_VERSION="0.14" -# CT_CLOOG_V_0_18_4 is not set -# CT_CLOOG_V_0_18_1 is not set -# CT_CLOOG_V_0_18_0 is not set -CT_MPC_V_1_0_3=y -# CT_MPC_V_1_0_2 is not set -# CT_MPC_V_1_0_1 is not set -# CT_MPC_V_1_0 is not set -# CT_MPC_V_0_9 is not set -# CT_MPC_V_0_8_2 is not set -# CT_MPC_V_0_8_1 is not set -# CT_MPC_V_0_7 is not set -CT_MPC_VERSION="1.0.3" - -# -# Companion libraries common options -# -# CT_COMPLIBS_CHECK is not set +CT_NCURSES=y +CT_ZLIB=y # # Companion tools # - -# -# READ HELP before you say 'Y' below !!! -# -# CT_COMP_TOOLS is not set +# CT_COMP_TOOLS_FOR_HOST is not set +# CT_COMP_TOOLS_AUTOCONF is not set +# CT_COMP_TOOLS_AUTOMAKE is not set +# CT_COMP_TOOLS_BISON is not set +# CT_COMP_TOOLS_DTC is not set +# CT_COMP_TOOLS_LIBTOOL is not set +# CT_COMP_TOOLS_M4 is not set +# CT_COMP_TOOLS_MAKE is not set +CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE" diff --git a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh new file mode 100644 index 0000000000..ae737d9677 --- /dev/null +++ b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh @@ -0,0 +1,12 @@ +set -ex + +# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz +url="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/crosstool-ng-1.24.0.tar.gz" +curl -Lf $url | tar xzf - +cd crosstool-ng-crosstool-ng-1.24.0 +./bootstrap +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng-crosstool-ng-1.24.0 diff --git a/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch b/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch deleted file mode 100644 index 871d5225c0..0000000000 --- a/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch +++ /dev/null @@ -1,48 +0,0 @@ -commit bdb24c2851fd5f0ad9b82d7ea1db911d334b02d2 -Author: Joseph Myers -Date: Tue May 20 21:27:13 2014 +0000 - - Fix ARM build with GCC trunk. - - sysdeps/unix/sysv/linux/arm/unwind-resume.c and - sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c have static - variables that are written in C code but only read from toplevel asms. - Current GCC trunk now optimizes away such apparently write-only static - variables, so causing a build failure. This patch marks those - variables with __attribute_used__ to avoid that optimization. - - Tested that this fixes the build for ARM. - - * sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c - (libgcc_s_resume): Use __attribute_used__. - * sysdeps/unix/sysv/linux/arm/unwind-resume.c (libgcc_s_resume): - Likewise. - -diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -index 29e2c2b00b04..e848bfeffdcb 100644 ---- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -@@ -22,7 +22,8 @@ - #include - - static void *libgcc_s_handle; --static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); -+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc) -+ __attribute_used__; - static _Unwind_Reason_Code (*libgcc_s_personality) - (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); - static _Unwind_Reason_Code (*libgcc_s_forcedunwind) -diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -index 285b99b5ed0d..48d00fc83641 100644 ---- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -@@ -20,7 +20,8 @@ - #include - #include - --static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); -+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc) -+ __attribute_used__; - static _Unwind_Reason_Code (*libgcc_s_personality) - (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); - diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile index ba2d32a929..61c363fbfd 100644 --- a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile @@ -32,7 +32,6 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-i586=/musl-i586 \ --musl-root-i686=/musl-i686 \ - --enable-extended \ --disable-docs # Newer binutils broke things on some vms/distros (i.e., linking against diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index ae2ea8ef95..1057911946 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -104,9 +104,7 @@ ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu -# FIXME: temporarily disable the redox builder, -# see: https://github.com/rust-lang/rust/issues/63160 -# ENV TARGETS=$TARGETS,x86_64-unknown-redox +ENV TARGETS=$TARGETS,x86_64-unknown-redox ENV TARGETS=$TARGETS,thumbv6m-none-eabi ENV TARGETS=$TARGETS,thumbv7m-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabi @@ -132,7 +130,7 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ - + ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ --musl-root-arm=/musl-arm \ diff --git a/src/ci/docker/dist-x86_64-linux/build-curl.sh b/src/ci/docker/dist-x86_64-linux/build-curl.sh index fb8b63d792..8200bbe2fd 100755 --- a/src/ci/docker/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-curl.sh @@ -3,9 +3,11 @@ set -ex source shared.sh -VERSION=7.51.0 +VERSION=7.66.0 -curl http://cool.haxx.se/download/curl-$VERSION.tar.bz2 | tar xjf - +curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \ + | xz --decompress \ + | tar xf - mkdir curl-build cd curl-build diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 2041ba50bc..517b59c38d 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -19,3 +19,6 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ENV SCRIPT python2.7 ../x.py test + +# FIXME(#59637) takes too long on CI right now +ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 17441ddb45..03db3ba099 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -25,3 +25,6 @@ ENV SCRIPT python2.7 ../x.py test \ --exclude src/test/rustdoc-js \ --exclude src/tools/error_index_generator \ --exclude src/tools/linkchecker + +# FIXME(#59637) takes too long on CI right now +ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh index 51945fd72a..bb72e33def 100644 --- a/src/ci/docker/scripts/cross-apt-packages.sh +++ b/src/ci/docker/scripts/cross-apt-packages.sh @@ -22,5 +22,6 @@ apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ sudo \ texinfo \ + unzip \ wget \ xz-utils diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index 55899fa6c3..74ba2f0ead 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -54,29 +54,3 @@ if [ "$REPLACE_CC" = "1" ]; then ln -s $TARGET-g++ /usr/local/bin/$exec done fi - -export CC=$TARGET-gcc -export CXX=$TARGET-g++ - -LLVM=70 - -# may have been downloaded in a previous run -if [ ! -d libunwind-release_$LLVM ]; then - curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf - - curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf - -fi - -# fixme(mati865): Replace it with https://github.com/rust-lang/rust/pull/59089 -mkdir libunwind-build -cd libunwind-build -cmake ../libunwind-release_$LLVM \ - -DLLVM_PATH=/build/llvm-release_$LLVM \ - -DLIBUNWIND_ENABLE_SHARED=0 \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" - -hide_output make -j$(nproc) -cp lib/libunwind.a $OUTPUT/$TARGET/lib -cd - && rm -rf libunwind-build diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index c2cf77d56c..d847c407ab 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -20,6 +20,8 @@ exit 1 TAG=$1 shift +# Ancient binutils versions don't understand debug symbols produced by more recent tools. +# Apparently applying `-fPIC` everywhere allows them to link successfully. export CFLAGS="-fPIC $CFLAGS" MUSL=musl-1.1.22 @@ -38,27 +40,3 @@ else fi hide_output make install hide_output make clean - -cd .. - -LLVM=70 - -# may have been downloaded in a previous run -if [ ! -d libunwind-release_$LLVM ]; then - curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf - - curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf - -fi - -mkdir libunwind-build -cd libunwind-build -cmake ../libunwind-release_$LLVM \ - -DLLVM_PATH=/build/llvm-release_$LLVM \ - -DLIBUNWIND_ENABLE_SHARED=0 \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" - -hide_output make -j$(nproc) -cp lib/libunwind.a /musl-$TAG/lib -cd ../ && rm -rf libunwind-build diff --git a/src/ci/run.sh b/src/ci/run.sh index a61e90b0af..c3f8e4c270 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -78,6 +78,21 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ] RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools" fi +# Print the date from the local machine and the date from an external source to +# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure +# Pipelines it happened that the certificates were marked as expired. +datecheck() { + echo "== clock drift check ==" + echo -n " local time: " + date + echo -n " network time: " + curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \ + | sed 's/Date: //g' || true + echo "== end clock drift check ==" +} +datecheck +trap datecheck EXIT + # We've had problems in the past of shell scripts leaking fds into the sccache # server (#48192) which causes Cargo to erroneously think that a build script # hasn't finished yet. Try to solve that problem by starting a very long-lived diff --git a/src/doc/book/.travis.yml b/src/doc/book/.travis.yml index be8ed09bda..d8247288d4 100644 --- a/src/doc/book/.travis.yml +++ b/src/doc/book/.travis.yml @@ -3,7 +3,7 @@ dist: trusty language: rust cache: cargo rust: - - 1.31.1 + - 1.37.0 branches: only: - master diff --git a/src/doc/book/README.md b/src/doc/book/README.md index c47820b795..6dd1d9f373 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -19,7 +19,7 @@ releases are updated less frequently. ## Requirements -Building the book requires [mdBook], ideally the same 0.2.x version that +Building the book requires [mdBook], ideally the same 0.3.x version that rust-lang/rust uses in [this file][rust-mdbook]. To get it: [mdBook]: https://github.com/rust-lang-nursery/mdBook diff --git a/src/doc/book/src/appendix-01-keywords.md b/src/doc/book/src/appendix-01-keywords.md index 85e675d8a7..6a129e2903 100644 --- a/src/doc/book/src/appendix-01-keywords.md +++ b/src/doc/book/src/appendix-01-keywords.md @@ -60,6 +60,7 @@ for potential future use. * `abstract` * `async` +* `await` * `become` * `box` * `do` diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md index e30316fd58..5651b68bd3 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -668,7 +668,7 @@ error[E0308]: mismatched types --> src/main.rs:23:21 | 23 | match guess.cmp(&secret_number) { - | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integral variable + | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integer | = note: expected type `&std::string::String` = note: found type `&{integer}` diff --git a/src/doc/book/src/ch03-01-variables-and-mutability.md b/src/doc/book/src/ch03-01-variables-and-mutability.md index 6f5e6c7b15..b14bba5244 100644 --- a/src/doc/book/src/ch03-01-variables-and-mutability.md +++ b/src/doc/book/src/ch03-01-variables-and-mutability.md @@ -65,7 +65,7 @@ But mutability can be very useful. Variables are immutable only by default; as you did in Chapter 2, you can make them mutable by adding `mut` in front of the variable name. In addition to allowing this value to change, `mut` conveys intent to future readers of the code by indicating that other parts of the code -will be changing this variable value. +will be changing this variable's value. For example, let’s change *src/main.rs* to the following: diff --git a/src/doc/book/src/ch03-05-control-flow.md b/src/doc/book/src/ch03-05-control-flow.md index 52ce3d5a9f..ac529d926d 100644 --- a/src/doc/book/src/ch03-05-control-flow.md +++ b/src/doc/book/src/ch03-05-control-flow.md @@ -96,7 +96,7 @@ error[E0308]: mismatched types --> src/main.rs:4:8 | 4 | if number { - | ^^^^^^ expected bool, found integral variable + | ^^^^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -240,7 +240,7 @@ error[E0308]: if and else have incompatible types 6 | | } else { 7 | | "six" 8 | | }; - | |_____^ expected integral variable, found &str + | |_____^ expected integer, found &str | = note: expected type `{integer}` found type `&str` diff --git a/src/doc/book/src/ch04-01-what-is-ownership.md b/src/doc/book/src/ch04-01-what-is-ownership.md index 5012d8614b..cf8fd209b4 100644 --- a/src/doc/book/src/ch04-01-what-is-ownership.md +++ b/src/doc/book/src/ch04-01-what-is-ownership.md @@ -146,9 +146,9 @@ that is stored on the heap and explore how Rust knows when to clean up that data. We’ll use `String` as the example here and concentrate on the parts of `String` -that relate to ownership. These aspects also apply to other complex data types -provided by the standard library and that you create. We’ll discuss `String` in -more depth in Chapter 8. +that relate to ownership. These aspects also apply to other complex data types, +whether they are provided by the standard library or created by you. We’ll +discuss `String` in more depth in Chapter 8. We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t suitable for every diff --git a/src/doc/book/src/ch04-02-references-and-borrowing.md b/src/doc/book/src/ch04-02-references-and-borrowing.md index 27290fcf04..f75d5c91b8 100644 --- a/src/doc/book/src/ch04-02-references-and-borrowing.md +++ b/src/doc/book/src/ch04-02-references-and-borrowing.md @@ -314,7 +314,7 @@ Let’s take a closer look at exactly what’s happening at each stage of our Filename: src/main.rs -```rust,ignore +```rust,ignore,does_not_compile fn dangle() -> &String { // dangle returns a reference to a String let s = String::from("hello"); // s is a new String diff --git a/src/doc/book/src/ch05-02-example-structs.md b/src/doc/book/src/ch05-02-example-structs.md index 4aeb816fe6..46f88f1b8a 100644 --- a/src/doc/book/src/ch05-02-example-structs.md +++ b/src/doc/book/src/ch05-02-example-structs.md @@ -165,7 +165,7 @@ fn main() { Listing 5-11: Attempting to print a `Rectangle` instance -When we run this code, we get an error with this core message: +When we compile this code, we get an error with this core message: ```text error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` @@ -195,7 +195,7 @@ Let’s try it! The `println!` macro call will now look like `println!("rect1 is enables us to print our struct in a way that is useful for developers so we can see its value while we’re debugging our code. -Run the code with this change. Drat! We still get an error: +Compile the code with this change. Drat! We still get an error: ```text error[E0277]: `Rectangle` doesn't implement `std::fmt::Debug` diff --git a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index af15ace8b4..ea6e51716b 100644 --- a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -41,10 +41,9 @@ root, `hosting` is now a valid name in that scope, just as though the `hosting` module had been defined in the crate root. Paths brought into scope with `use` also check privacy, like any other paths. -Specifying a relative path with `use` is slightly different. Instead of -starting from a name in the current scope, we must start the path given to -`use` with the keyword `self`. Listing 7-12 shows how to specify a relative -path to get the same behavior as in Listing 7-11. +You can also bring an item into scope with `use` and a relative path. Listing +7-12 shows how to specify a relative path to get the same behavior as in +Listing 7-11. Filename: src/lib.rs @@ -55,7 +54,7 @@ mod front_of_house { } } -use self::front_of_house::hosting; +use front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); @@ -66,10 +65,7 @@ pub fn eat_at_restaurant() { ``` Listing 7-12: Bringing a module into scope with `use` and -a relative path starting with `self` - -Note that using `self` in this way might not be necessary in the future; it’s -an inconsistency in the language that Rust developers are working to eliminate. +a relative path ### Creating Idiomatic `use` Paths diff --git a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md index 85c4192836..7de45284fe 100644 --- a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md +++ b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md @@ -51,7 +51,7 @@ us that the types don’t match. The error message will then tell us what the type of `f` *is*. Let’s try it! We know that the return type of `File::open` isn’t of type `u32`, so let’s change the `let f` statement to this: -```rust,ignore +```rust,ignore,does_not_compile let f: u32 = File::open("hello.txt"); ``` @@ -481,7 +481,7 @@ must be a `Result` to be compatible with this `return`. Let’s look at what happens if we use the `?` operator in the `main` function, which you’ll recall has a return type of `()`: -```rust,ignore +```rust,ignore,does_not_compile use std::fs::File; fn main() { diff --git a/src/doc/book/src/ch10-01-syntax.md b/src/doc/book/src/ch10-01-syntax.md index 6134de7418..f69165e269 100644 --- a/src/doc/book/src/ch10-01-syntax.md +++ b/src/doc/book/src/ch10-01-syntax.md @@ -207,8 +207,8 @@ error[E0308]: mismatched types --> src/main.rs:7:38 | 7 | let wont_work = Point { x: 5, y: 4.0 }; - | ^^^ expected integral variable, found -floating-point variable + | ^^^ expected integer, found +floating-point number | = note: expected type `{integer}` found type `{float}` diff --git a/src/doc/book/src/ch11-03-test-organization.md b/src/doc/book/src/ch11-03-test-organization.md index bc8255e306..2af6a0e0f5 100644 --- a/src/doc/book/src/ch11-03-test-organization.md +++ b/src/doc/book/src/ch11-03-test-organization.md @@ -132,7 +132,7 @@ fn it_adds_two() { `adder` crate We’ve added `use adder` at the top of the code, which we didn’t need in the -unit tests. The reason is that each test in the `tests` directory is a separate +unit tests. The reason is that each file in the `tests` directory is a separate crate, so we need to bring our library into each test crate’s scope. We don’t need to annotate any code in *tests/integration_test.rs* with diff --git a/src/doc/book/src/ch13-01-closures.md b/src/doc/book/src/ch13-01-closures.md index 05c97c7e6f..f679c1431e 100644 --- a/src/doc/book/src/ch13-01-closures.md +++ b/src/doc/book/src/ch13-01-closures.md @@ -402,7 +402,7 @@ error[E0308]: mismatched types | | let n = example_closure(5); | ^ expected struct `std::string::String`, found - integral variable + integer | = note: expected type `std::string::String` found type `{integer}` diff --git a/src/doc/book/src/ch14-01-release-profiles.md b/src/doc/book/src/ch14-01-release-profiles.md index c150f6a073..ab2400511e 100644 --- a/src/doc/book/src/ch14-01-release-profiles.md +++ b/src/doc/book/src/ch14-01-release-profiles.md @@ -66,4 +66,4 @@ Cargo will use the defaults for the `dev` profile plus our customization to optimizations than the default, but not as many as in a release build. For the full list of configuration options and defaults for each profile, see -[Cargo’s documentation](https://doc.rust-lang.org/cargo/). +[Cargo’s documentation](https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections). diff --git a/src/doc/book/src/ch15-02-deref.md b/src/doc/book/src/ch15-02-deref.md index 6520eaf96c..e0fae5b1a9 100644 --- a/src/doc/book/src/ch15-02-deref.md +++ b/src/doc/book/src/ch15-02-deref.md @@ -10,7 +10,7 @@ Let’s first look at how the dereference operator works with regular references Then we’ll try to define a custom type that behaves like `Box`, and see why the dereference operator doesn’t work like a reference on our newly defined type. We’ll explore how implementing the `Deref` trait makes it possible for -smart pointers to work in a similar way as references. Then we’ll look at +smart pointers to work in ways similar to references. Then we’ll look at Rust’s *deref coercion* feature and how it lets us work with either references or smart pointers. diff --git a/src/doc/book/src/ch16-02-message-passing.md b/src/doc/book/src/ch16-02-message-passing.md index 7cb4cfa8d3..56181eaf79 100644 --- a/src/doc/book/src/ch16-02-message-passing.md +++ b/src/doc/book/src/ch16-02-message-passing.md @@ -35,12 +35,11 @@ want to send over the channel. Filename: src/main.rs -```rust +```rust,ignore,does_not_compile use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); -# tx.send(()).unwrap(); } ``` diff --git a/src/doc/book/src/ch16-03-shared-state.md b/src/doc/book/src/ch16-03-shared-state.md index e5491d147c..7050d4db15 100644 --- a/src/doc/book/src/ch16-03-shared-state.md +++ b/src/doc/book/src/ch16-03-shared-state.md @@ -2,7 +2,7 @@ Message passing is a fine way of handling concurrency, but it’s not the only one. Consider this part of the slogan from the Go language documentation again: -“communicate by sharing memory.” +“do not communicate by sharing memory.” What would communicating by sharing memory look like? In addition, why would message-passing enthusiasts not use it and do the opposite instead? diff --git a/src/doc/book/src/ch17-03-oo-design-patterns.md b/src/doc/book/src/ch17-03-oo-design-patterns.md index efe3f43943..4ffb3a0179 100644 --- a/src/doc/book/src/ch17-03-oo-design-patterns.md +++ b/src/doc/book/src/ch17-03-oo-design-patterns.md @@ -380,7 +380,7 @@ otherwise, we want to return an empty string slice, as shown in Listing 17-17: impl Post { // --snip-- pub fn content(&self) -> &str { - self.state.as_ref().unwrap().content(&self) + self.state.as_ref().unwrap().content(self) } // --snip-- } diff --git a/src/doc/book/src/ch18-03-pattern-syntax.md b/src/doc/book/src/ch18-03-pattern-syntax.md index ccdeb6608b..63eab2f7b2 100644 --- a/src/doc/book/src/ch18-03-pattern-syntax.md +++ b/src/doc/book/src/ch18-03-pattern-syntax.md @@ -105,9 +105,9 @@ match x { This code prints `one or two`. -### Matching Ranges of Values with `...` +### Matching Ranges of Values with `..=` -The `...` syntax allows us to match to an inclusive range of values. In the +The `..=` syntax allows us to match to an inclusive range of values. In the following code, when a pattern matches any of the values within the range, that arm will execute: @@ -115,14 +115,14 @@ arm will execute: let x = 5; match x { - 1...5 => println!("one through five"), + 1..=5 => println!("one through five"), _ => println!("something else"), } ``` If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more convenient than using the `|` operator to express the same idea; instead of -`1...5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`. +`1..=5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`. Specifying a range is much shorter, especially if we want to match, say, any number between 1 and 1,000! @@ -136,8 +136,8 @@ Here is an example using ranges of `char` values: let x = 'c'; match x { - 'a'...'j' => println!("early ASCII letter"), - 'k'...'z' => println!("late ASCII letter"), + 'a'..='j' => println!("early ASCII letter"), + 'k'..='z' => println!("late ASCII letter"), _ => println!("something else"), } ``` @@ -783,7 +783,7 @@ were applied only to the final value in the list of values specified using the The *at* operator (`@`) lets us create a variable that holds a value at the same time we’re testing that value to see whether it matches a pattern. Listing 18-29 shows an example where we want to test that a `Message::Hello` `id` field -is within the range `3...7`. But we also want to bind the value to the variable +is within the range `3..=7`. But we also want to bind the value to the variable `id_variable` so we can use it in the code associated with the arm. We could name this variable `id`, the same as the field, but for this example we’ll use a different name. @@ -796,10 +796,10 @@ enum Message { let msg = Message::Hello { id: 5 }; match msg { - Message::Hello { id: id_variable @ 3...7 } => { + Message::Hello { id: id_variable @ 3..=7 } => { println!("Found an id in range: {}", id_variable) }, - Message::Hello { id: 10...12 } => { + Message::Hello { id: 10..=12 } => { println!("Found an id in another range") }, Message::Hello { id } => { @@ -812,7 +812,7 @@ match msg { while also testing it This example will print `Found an id in range: 5`. By specifying `id_variable -@` before the range `3...7`, we’re capturing whatever value matched the range +@` before the range `3..=7`, we’re capturing whatever value matched the range while also testing that the value matched the range pattern. In the second arm, where we only have a range specified in the pattern, the code diff --git a/src/doc/book/src/ch19-01-unsafe-rust.md b/src/doc/book/src/ch19-01-unsafe-rust.md index 8605ede6a2..8c32b3663e 100644 --- a/src/doc/book/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/src/ch19-01-unsafe-rust.md @@ -33,6 +33,7 @@ the ability to: * Call an unsafe function or method * Access or modify a mutable static variable * Implement an unsafe trait +* Access fields of `union`s It’s important to understand that `unsafe` doesn’t turn off the borrow checker or disable any other of Rust’s safety checks: if you use a reference in unsafe diff --git a/src/doc/book/src/ch20-02-multithreaded.md b/src/doc/book/src/ch20-02-multithreaded.md index 2e64463486..5ca9358c70 100644 --- a/src/doc/book/src/ch20-02-multithreaded.md +++ b/src/doc/book/src/ch20-02-multithreaded.md @@ -895,7 +895,7 @@ at Listing 20-19. # use std::sync::mpsc; # struct Worker {} -type Job = Box; +type Job = Box; impl ThreadPool { // --snip-- diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index bc7fb9031b..5e375d31b4 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -2,7 +2,7 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -This version of the text assumes you’re using Rust 1.31.0 or later with +This version of the text assumes you’re using Rust 1.37.0 or later with `edition="2018"` in *Cargo.toml* of all projects to use Rust 2018 Edition idioms. See the [“Installation” section of Chapter 1][install] to install or update Rust, and see the new [Appendix E][editions] Source code can be conditionally compiled -using [attributes], [`cfg`] and [`cfg_attr`], and the built-in [`cfg` macro]. +using the [attributes] [`cfg`] and [`cfg_attr`] and the built-in [`cfg` macro]. These conditions are based on the target architecture of the compiled crate, arbitrary values passed to the compiler, and a few other miscellaneous things further described below in detail. @@ -284,7 +284,7 @@ fn bewitched() {} ``` > **Note**: The `cfg_attr` can expand to another `cfg_attr`. For example, -> `#[cfg_attr(linux, cfg_attr(feature = "multithreaded", some_other_attribute))` +> `#[cfg_attr(linux, cfg_attr(feature = "multithreaded", some_other_attribute))]` > is valid. This example would be equivalent to > `#[cfg_attr(all(linux, feature ="multithreaded"), some_other_attribute)]`. diff --git a/src/doc/reference/src/const_eval.md b/src/doc/reference/src/const_eval.md index 6d9826c1cf..cec0145a3b 100644 --- a/src/doc/reference/src/const_eval.md +++ b/src/doc/reference/src/const_eval.md @@ -37,8 +37,8 @@ to be run. * Index expressions, [array indexing] or [slice] with a `usize`. * [Range expressions]. * [Closure expressions] which don't capture variables from the environment. -* Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean] - operators used on integer and floating point types, `bool` and `char`. +* Built-in [negation], [arithmetic], [logical], [comparison] or [lazy boolean] + operators used on integer and floating point types, `bool`, and `char`. * Shared [borrow]s, except if applied to a type with [interior mutability]. * The [dereference operator]. * [Grouped] expressions. @@ -57,7 +57,7 @@ A _const context_ is one of the following: * [statics] * [enum discriminants] -[arithmetic, logical]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators +[arithmetic]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators [array expressions]: expressions/array-expr.md [array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions [array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions @@ -84,6 +84,7 @@ A _const context_ is one of the following: [lazy boolean]: expressions/operator-expr.md#lazy-boolean-operators [let statements]: statements.md#let-statements [literals]: expressions/literal-expr.md +[logical]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators [negation]: expressions/operator-expr.md#negation-operators [overflow]: expressions/operator-expr.md#overflow [paths]: expressions/path-expr.md diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md index ce35a85fb7..1ab03d4bc1 100644 --- a/src/doc/reference/src/crates-and-source-files.md +++ b/src/doc/reference/src/crates-and-source-files.md @@ -29,7 +29,7 @@ crate in binary form: either an executable or some sort of library.[^cratesourcefile] A _crate_ is a unit of compilation and linking, as well as versioning, -distribution and runtime loading. A crate contains a _tree_ of nested +distribution, and runtime loading. A crate contains a _tree_ of nested [module] scopes. The top level of this tree is a module that is anonymous (from the point of view of paths within the module) and any item within a crate has a canonical [module path] denoting its location diff --git a/src/doc/reference/src/dynamically-sized-types.md b/src/doc/reference/src/dynamically-sized-types.md index 39154a2b51..ca40dfec46 100644 --- a/src/doc/reference/src/dynamically-sized-types.md +++ b/src/doc/reference/src/dynamically-sized-types.md @@ -20,7 +20,7 @@ types">DSTs. Such types can only be used in certain cases: last field, this makes the struct itself a DST. -Notably: [variables], function parameters, [const] and [static] items must be +> **Note**: [variables], function parameters, [const] items, and [static] items must be `Sized`. [sized]: special-types-and-traits.md#sized diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index c211fa933e..fc0764c000 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -13,6 +13,7 @@ >       | [_OperatorExpression_]\ >       | [_GroupedExpression_]\ >       | [_ArrayExpression_]\ +>       | [_AwaitExpression_]\ >       | [_IndexExpression_]\ >       | [_TupleExpression_]\ >       | [_TupleIndexingExpression_]\ @@ -33,6 +34,7 @@ >    [_OuterAttribute_]\*[†](#expression-attributes)\ >    (\ >          [_BlockExpression_]\ +>       | [_AsyncBlockExpression_]\ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ @@ -263,7 +265,7 @@ a few specific cases: * Before an expression used as a [statement]. * Elements of [array expressions], [tuple expressions], [call expressions], - tuple-style [struct] and [enum variant] expressions. + and tuple-style [struct] and [enum variant] expressions. diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md index d95445c43d..67be5755ed 100644 --- a/src/doc/reference/src/expressions/loop-expr.md +++ b/src/doc/reference/src/expressions/loop-expr.md @@ -130,9 +130,9 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`. If the iterator yields a -value, that value is given the specified name and the body of the loop is -executed, then control returns to the head of the `for` loop. If the iterator -is empty, the `for` expression completes. +value, that value is matched against the irrefutable pattern, the body of the +loop is executed, and then control returns to the head of the `for` loop. If the +iterator is empty, the `for` expression completes. An example of a `for` loop over the contents of an array: @@ -181,9 +181,9 @@ is equivalent to } ``` -`IntoIterator`, `Iterator` and `Option` are always the standard library items +`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope. The variable -names `next`, `iter` and `val` are for exposition only, they do not actually +names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type. > **Note**: that the outer `match` is used to ensure that any @@ -284,7 +284,7 @@ expression `()`. [LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels [_BlockExpression_]: block-expr.md -[_Expression_]: ../ expressions.md +[_Expression_]: ../expressions.md [_MatchArmPatterns_]: match-expr.md [_Pattern_]: ../patterns.md [`match` expression]: match-expr.md diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index f35d0328f9..3635cc0328 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -367,16 +367,15 @@ same trait object. * **[NOTE: currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type][float-int]**. This includes Inf and NaN. This is a bug and will be fixed. - * Casting from an integer to float will produce the floating point - representation of the integer, rounded if necessary (rounding strategy - unspecified) + * Casting from an integer to float will produce the closest possible float \* + * if necessary, rounding is according to `roundTiesToEven` mode \*\*\* + * on overflow, infinity (of the same sign as the input) is produced + * note: with the current set of numeric types, overflow can only happen + on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)` * Casting from an f32 to an f64 is perfect and lossless - * Casting from an f64 to an f32 will produce the closest possible value - (rounding strategy unspecified) - * **[NOTE: currently this will cause Undefined Behavior if the value - is finite but larger or smaller than the largest or smallest finite - value representable by f32][float-float]**. This is a bug and will - be fixed. + * Casting from an f64 to an f32 will produce the closest possible f32 \*\* + * if necessary, rounding is according to `roundTiesToEven` mode \*\*\* + * on overflow, infinity (of the same sign as the input) is produced * Enum cast * Casts an enum to its discriminant, then uses a numeric cast if needed. * Primitive to integer cast @@ -385,8 +384,19 @@ same trait object. * `u8` to `char` cast * Casts to the `char` with the corresponding code point. +\* if integer-to-float casts with this rounding mode and overflow behavior are +not supported natively by the hardware, these casts will likely be slower than +expected. + +\*\* if f64-to-f32 casts with this rounding mode and overflow behavior are not +supported natively by the hardware, these casts will likely be slower than +expected. + +\*\*\* as defined in IEEE 754-2008 §4.3.1: pick the nearest floating point +number, preferring the one with an even least significant digit if exactly +halfway between two floating point numbers. + [float-int]: https://github.com/rust-lang/rust/issues/10184 -[float-float]: https://github.com/rust-lang/rust/issues/15536 ## Assignment expressions diff --git a/src/doc/reference/src/influences.md b/src/doc/reference/src/influences.md index 46082bfc0b..3aa812abe8 100644 --- a/src/doc/reference/src/influences.md +++ b/src/doc/reference/src/influences.md @@ -16,7 +16,7 @@ that have since been removed): * Swift: optional bindings * Scheme: hygienic macros * C#: attributes -* Ruby: block syntax +* Ruby: closure syntax, block syntax * NIL, Hermes: typestate * [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and pattern syntax diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md index 66c45dc46f..873fa0c418 100644 --- a/src/doc/reference/src/introduction.md +++ b/src/doc/reference/src/introduction.md @@ -5,7 +5,7 @@ provides three kinds of material: - Chapters that informally describe each language construct and their use. - Chapters that informally describe the memory model, concurrency model, - runtime services, linkage model and debugging facilities. + runtime services, linkage model, and debugging facilities. - Appendix chapters providing rationale and references to languages that influenced the design. diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md index e8a18ad582..29ea6da9b9 100644 --- a/src/doc/reference/src/items/associated-items.md +++ b/src/doc/reference/src/items/associated-items.md @@ -133,7 +133,7 @@ Shorthand | Equivalent `&'lifetime self` | `self: &'lifetime Self` `&'lifetime mut self` | `self: &'lifetime mut Self` -> Note: Lifetimes can be and usually are elided with this shorthand. +> **Note**: Lifetimes can be, and usually are, elided with this shorthand. If the `self` parameter is prefixed with `mut`, it becomes a mutable variable, similar to regular parameters using a `mut` [identifier pattern]. For example: diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md index 9c69ad0ed9..f3e692ac95 100644 --- a/src/doc/reference/src/items/external-blocks.md +++ b/src/doc/reference/src/items/external-blocks.md @@ -29,9 +29,13 @@ > _NamedFunctionParametersWithVariadics_ :\ >    ( _NamedFunctionParam_ `,` )\* _NamedFunctionParam_ `,` `...` -External blocks form the basis for Rust's foreign function interface. -Declarations in an external block describe symbols in external, non-Rust -libraries. +External blocks provide _declarations_ of items that are not _defined_ in the +current crate and are the basis of Rust's foreign function interface. These are +akin to unchecked imports. + +Two kind of item _declarations_ are allowed in external blocks: [functions] and +[statics]. Calling functions or accessing statics that are declared in external +blocks is only allowed in an `unsafe` context. Functions within external blocks are declared in the same way as other Rust functions, with the exception that they may not have a body and are instead @@ -48,6 +52,8 @@ extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, ... `'lm` are its lifetime parameters, `A1`, ..., `An` are the declared types of its parameters and `R` is the declared return type. +Statics within external blocks are declared in the same way as statics outside of external blocks, +except that they do not have an expression initializing their value. It is `unsafe` to access a static item declared in an extern block, whether or not it's mutable. @@ -85,13 +91,6 @@ There are also some platform-specific ABI strings: * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and clang's `__attribute__((vectorcall))` -Finally, there are some rustc-specific ABI strings: - -* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics. -* `extern "rust-call"` -- The ABI of the Fn::call trait functions. -* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for - example, `sqrt` -- have this ABI. You should never have to deal with it. - ## Variadic functions Functions within external blocks may be variadic by specifying `...` after one @@ -165,6 +164,8 @@ extern { [IDENTIFIER]: ../identifiers.md [WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html +[functions]: functions.md +[statics]: static-items.md [_Abi_]: functions.md [_FunctionReturnType_]: functions.md [_Generics_]: generics.md diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md index bae5b8eff8..63f436fe46 100644 --- a/src/doc/reference/src/items/functions.md +++ b/src/doc/reference/src/items/functions.md @@ -8,7 +8,10 @@ >       [_BlockExpression_] > > _FunctionQualifiers_ :\ ->    `const`? `unsafe`? (`extern` _Abi_?)? +>    _AsyncConstQualifiers_? `unsafe`? (`extern` _Abi_?)? +> +> _AsyncConstQualifiers_ :\ +>    `async` | `const` > > _Abi_ :\ >    [STRING_LITERAL] | [RAW_STRING_LITERAL] @@ -107,35 +110,73 @@ component after the function name. This might be necessary if there is not sufficient context to determine the type parameters. For example, `mem::size_of::() == 4`. -## Extern functions +## Extern function qualifier + +The `extern` function qualifier allows providing function _definitions_ that can +be called with a particular ABI: + +```rust,ignore +extern "ABI" fn foo() { ... } +``` + +These are often used in combination with [external block] items which provide +function _declarations_ that can be used to call functions without providing +their _definition_: -Extern functions are part of Rust's foreign function interface, providing the -opposite functionality to [external blocks]. Whereas external -blocks allow Rust code to call foreign code, extern functions with bodies -defined in Rust code _can be called by foreign code_. They are defined in the -same way as any other Rust function, except that they have the `extern` -qualifier. +```rust,ignore +extern "ABI" { + fn foo(); /* no body */ +} +unsafe { foo() } +``` + +When `"extern" Abi?*` is omitted from `FunctionQualifiers` in function items, +the ABI `"Rust"` is assigned. For example: ```rust -// Declares an extern fn, the ABI defaults to "C" -extern fn new_i32() -> i32 { 0 } +fn foo() {} +``` -// Declares an extern fn with "stdcall" ABI +is equivalent to: + +```rust +extern "Rust" fn foo() {} +``` + +Functions in Rust can be called by foreign code, and using an ABI that +differs from Rust allows, for example, to provide functions that can be +called from other programming languages like C: + +```rust +// Declares a function with the "C" ABI +extern "C" fn new_i32() -> i32 { 0 } + +// Declares a function with the "stdcall" ABI # #[cfg(target_arch = "x86_64")] extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } ``` -Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the -same type as the functions declared in an extern block. +Just as with [external block], when the `extern` keyword is used and the `"ABI` +is omitted, the ABI used defaults to `"C"`. That is, this: ```rust -# extern fn new_i32() -> i32 { 0 } +extern fn new_i32() -> i32 { 0 } +let fptr: extern fn() -> i32 = new_i32; +``` + +is equivalent to: + +```rust +extern "C" fn new_i32() -> i32 { 0 } let fptr: extern "C" fn() -> i32 = new_i32; ``` -As non-Rust calling conventions do not support unwinding, unwinding past the end -of an extern function will cause the process to abort. In LLVM, this is -implemented by executing an illegal instruction. +Functions with an ABI that differs from `"Rust"` do not support unwinding in the +exact same way that Rust does. Therefore, unwinding past the end of functions +with such ABIs causes the process to abort. + +> **Note**: The LLVM backend of the `rustc` implementation +aborts the process by executing an illegal instruction. ## Const functions @@ -169,7 +210,7 @@ Exhaustive list of permitted structures in const functions: * lifetimes * `Sized` or [`?Sized`] - This means that ``, `` and `` + This means that ``, ``, and `` are all permitted. This rule also applies to type parameters of impl blocks that @@ -189,6 +230,104 @@ Exhaustive list of permitted structures in const functions: the following unsafe operations: * calls to const unsafe functions +## Async functions + +Functions may be qualified as async, and this can also be combined with the +`unsafe` qualifier: + +```rust,edition2018 +async fn regular_example() { } +async unsafe fn unsafe_example() { } +``` + +Async functions do no work when called: instead, they +capture their arguments into a future. When polled, that future will +execute the function's body. + +An async function is roughly equivalent to a function +that returns [`impl Future`] and with an [`async move` block][async-blocks] as +its body: + +```rust,edition2018 +// Source +async fn example(x: &str) -> usize { + x.len() +} +``` + +is roughly equivalent to: + +```rust,edition2018 +# use std::future::Future; +// Desugared +fn example<'a>(x: &'a str) -> impl Future + 'a { + async move { x.len() } +} +``` + +The actual desugaring is more complex: + +- The return type in the desugaring is assumed to capture all lifetime + parameters from the `async fn` declaration. This can be seen in the + desugared example above, which explicitly outlives, and hence + captures, `'a`. +- The [`async move` block][async-blocks] in the body captures all function + parameters, including those that are unused or bound to a `_` + pattern. This ensures that function parameters are dropped in the + same order as they would be if the function were not async, except + that the drop occurs when the returned future has been fully + awaited. + +For more information on the effect of async, see [`async` blocks][async-blocks]. + +[async-blocks]: ../expressions/block-expr.md#async-blocks +[`impl Future`]: ../types/impl-trait.md + +> **Edition differences**: Async functions are only available beginning with +> Rust 2018. + +### Combining `async` and `unsafe` + +It is legal to declare a function that is both async and unsafe. The +resulting function is unsafe to call and (like any async function) +returns a future. This future is just an ordinary future and thus an +`unsafe` context is not required to "await" it: + +```rust,edition2018 +// Returns a future that, when awaited, dereferences `x`. +// +// Soundness condition: `x` must be safe to dereference until +// the resulting future is complete. +async unsafe fn unsafe_example(x: *const i32) -> i32 { + *x +} + +async fn safe_example() { + // An `unsafe` block is required to invoke the function initially: + let p = 22; + let future = unsafe { unsafe_example(&p) }; + + // But no `unsafe` block required here. This will + // read the value of `p`: + let q = future.await; +} +``` + +Note that this behavior is a consequence of the desugaring to a +function that returns an `impl Future` -- in this case, the function +we desugar to is an `unsafe` function, but the return value remains +the same. + +Unsafe is used on an async function in precisely the same way that it +is used on other functions: it indicates that the function imposes +some additional obligations on its caller to ensure soundness. As in any +other unsafe function, these conditions may extend beyond the initial +call itself -- in the snippet above, for example, the `unsafe_example` +function took a pointer `x` as argument, and then (when awaited) +dereferenced that pointer. This implies that `x` would have to be +valid until the future is finished executing, and it is the callers +responsibility to ensure that. + ## Attributes on functions [Outer attributes][attributes] are allowed on functions. [Inner @@ -221,7 +360,7 @@ attributes macros. [_Type_]: ../types.md#type-expressions [_WhereClause_]: generics.md#where-clauses [const context]: ../const_eval.md#const-context -[external blocks]: external-blocks.md +[external block]: external-blocks.md [path]: ../paths.md [block]: ../expressions/block-expr.md [variables]: ../variables.md @@ -243,3 +382,4 @@ attributes macros. [`export_name`]: ../abi.md#the-export_name-attribute [`link_section`]: ../abi.md#the-link_section-attribute [`no_mangle`]: ../abi.md#the-no_mangle-attribute +[external_block_abi]: external-blocks.md#abi diff --git a/src/doc/reference/src/items/generics.md b/src/doc/reference/src/items/generics.md index f540ca7a79..074b5cf366 100644 --- a/src/doc/reference/src/items/generics.md +++ b/src/doc/reference/src/items/generics.md @@ -20,7 +20,7 @@ > _TypeParam_ :\ >    [_OuterAttribute_]? [IDENTIFIER] ( `:` [_TypeParamBounds_]? )? ( `=` [_Type_] )? -Functions, type aliases, structs, enumerations, unions, traits and +Functions, type aliases, structs, enumerations, unions, traits, and implementations may be *parameterized* by types and lifetimes. These parameters are listed in angle brackets (`<...>`), usually immediately after the name of the item and before its definition. For @@ -34,7 +34,7 @@ trait A {} struct Ref<'a, T> where T: 'a { r: &'a T } ``` -[References], [raw pointers], [arrays], [slices][arrays], [tuples] and +[References], [raw pointers], [arrays], [slices][arrays], [tuples], and [function pointers] have lifetime or type parameters as well, but are not referred to with path syntax. @@ -64,7 +64,7 @@ parameters. Bounds that don't use the item's parameters or higher-ranked lifetimes are checked when the item is defined. It is an error for such a bound to be false. -[`Copy`], [`Clone`] and [`Sized`] bounds are also checked for certain generic +[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when defining the item. It is an error to have `Copy` or `Clone`as a bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a bound on a trait object or slice. diff --git a/src/doc/reference/src/items/unions.md b/src/doc/reference/src/items/unions.md index f98c681bf7..22c40df7c2 100644 --- a/src/doc/reference/src/items/unions.md +++ b/src/doc/reference/src/items/unions.md @@ -151,7 +151,7 @@ fn test() { } ``` -As you could see, in many aspects (except for layouts, safety and ownership) +As you could see, in many aspects (except for layouts, safety, and ownership) unions behave exactly like structs, largely as a consequence of inheriting their syntactic shape from structs. This is also true for many unmentioned aspects of Rust language (such as privacy, name resolution, type inference, diff --git a/src/doc/reference/src/items/use-declarations.md b/src/doc/reference/src/items/use-declarations.md index aeddb83214..4397fc4bd4 100644 --- a/src/doc/reference/src/items/use-declarations.md +++ b/src/doc/reference/src/items/use-declarations.md @@ -129,8 +129,8 @@ fn main() {} > use ::foo::baz::foobaz; > ``` > -> The 2015 edition does not allow use declarations to reference the [extern -> prelude]. Thus [`extern crate`] declarations are still required in 2015 to +> The 2015 edition does not allow use declarations to reference the [extern prelude]. +> Thus [`extern crate`] declarations are still required in 2015 to > reference an external crate in a use declaration. Beginning with the 2018 > edition, use declarations can specify an external crate dependency the same > way `extern crate` can. diff --git a/src/doc/reference/src/lifetime-elision.md b/src/doc/reference/src/lifetime-elision.md index c4421b1040..51a03ef75c 100644 --- a/src/doc/reference/src/lifetime-elision.md +++ b/src/doc/reference/src/lifetime-elision.md @@ -6,7 +6,7 @@ compiler can infer a sensible default choice. ## Lifetime elision in functions In order to make common patterns more ergonomic, lifetime arguments can be -*elided* in [function item], [function pointer] and [closure trait] signatures. +*elided* in [function item], [function pointer], and [closure trait] signatures. The following rules are used to infer lifetime parameters for elided lifetimes. It is an error to elide lifetime parameters that cannot be inferred. The placeholder lifetime, `'_`, can also be used to have a lifetime inferred in the diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md index a47b3719f3..8cae03a8e3 100644 --- a/src/doc/reference/src/macros-by-example.md +++ b/src/doc/reference/src/macros-by-example.md @@ -177,7 +177,7 @@ compiler knows how to expand them properly: number of fragments. For instance, `( $( $i:ident ),* ; $( $j:ident ),* ) => ( $( ($i,$j) ),*` must bind the same number of `$i` fragments as `$j` fragments. This means that invoking the macro with `(a, b, c; d, e, f`) is - legal and expands to `((a,d), (b,e), c,f))`, but `(a, b, c; d, e)` is + legal and expands to `((a,d), (b,e), (c,f))`, but `(a, b, c; d, e)` is illegal because it does not have the same number. This requirement applies to every layer of nested repetitions. diff --git a/src/doc/reference/src/memory-allocation-and-lifetime.md b/src/doc/reference/src/memory-allocation-and-lifetime.md index 24addb1dd3..7a5bfc12cb 100644 --- a/src/doc/reference/src/memory-allocation-and-lifetime.md +++ b/src/doc/reference/src/memory-allocation-and-lifetime.md @@ -1,6 +1,6 @@ # Memory allocation and lifetime -The _items_ of a program are those functions, modules and types that have their +The _items_ of a program are those functions, modules, and types that have their value calculated at compile-time and stored uniquely in the memory image of the rust process. Items are neither dynamically allocated nor freed. diff --git a/src/doc/reference/src/special-types-and-traits.md b/src/doc/reference/src/special-types-and-traits.md index be2fdaa05c..9c2e0b1ff5 100644 --- a/src/doc/reference/src/special-types-and-traits.md +++ b/src/doc/reference/src/special-types-and-traits.md @@ -38,13 +38,13 @@ mutability aren't placed in memory marked as read only. ## `PhantomData` [`std::marker::PhantomData`] is a zero-sized, minimum alignment, type that -is considered to own a `T` for the purposes of [variance], [drop check] and +is considered to own a `T` for the purposes of [variance], [drop check], and [auto traits](#auto-traits). ## Operator Traits The traits in [`std::ops`] and [`std::cmp`] are used to overload [operators], -[indexing expressions] and [call expressions]. +[indexing expressions], and [call expressions]. ## `Deref` and `DerefMut` @@ -64,7 +64,7 @@ whose type implements `Copy` are copied rather than moved upon assignment. fields that are not `Copy`. `Copy` is implemented by the compiler for * [Numeric types] -* `char`, `bool` and [`!`] +* `char`, `bool`, and [`!`] * [Tuples] of `Copy` types * [Arrays] of `Copy` types * [Shared references] @@ -94,17 +94,17 @@ immutable [`static` items]. ## Auto traits -The [`Send`], [`Sync`], [`UnwindSafe`] and [`RefUnwindSafe`] traits are _auto +The [`Send`], [`Sync`], [`UnwindSafe`], and [`RefUnwindSafe`] traits are _auto traits_. Auto traits have special properties. If no explicit implementation or negative implementation is written out for an auto trait for a given type, then the compiler implements it automatically according to the following rules: -* `&T`, `&mut T`, `*const T`, `*mut T`, `[T; n]` and `[T]` implement the trait +* `&T`, `&mut T`, `*const T`, `*mut T`, `[T; n]`, and `[T]` implement the trait if `T` does. * Function item types and function pointers automatically implement the trait. -* Structs, enums, unions and tuples implement the trait if all of their fields +* Structs, enums, unions, and tuples implement the trait if all of their fields do. * Closures implement the trait if the types of all of their captures do. A closure that captures a `T` by shared reference and a `U` by value implements diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md index c55f002986..9b5bd94f1d 100644 --- a/src/doc/reference/src/statements.md +++ b/src/doc/reference/src/statements.md @@ -56,13 +56,13 @@ fn outer() { >    [_OuterAttribute_]\* `let` [_Pattern_] > ( `:` [_Type_] )? (`=` [_Expression_] )? `;` -A *`let` statement* introduces a new set of [variables], given by a [pattern]. The -pattern is followed optionally by a type annotation and then optionally by an -initializer expression. When no type annotation is given, the compiler will -infer the type, or signal an error if insufficient type information is -available for definite inference. Any variables introduced by a variable -declaration are visible from the point of declaration until the end of the -enclosing block scope. +A *`let` statement* introduces a new set of [variables], given by an +irrefutable [pattern]. The pattern is followed optionally by a type +annotation and then optionally by an initializer expression. When no +type annotation is given, the compiler will infer the type, or signal +an error if insufficient type information is available for definite +inference. Any variables introduced by a variable declaration are visible +from the point of declaration until the end of the enclosing block scope. ## Expression statements diff --git a/src/doc/reference/src/subtyping.md b/src/doc/reference/src/subtyping.md index b886830ad7..00764425ac 100644 --- a/src/doc/reference/src/subtyping.md +++ b/src/doc/reference/src/subtyping.md @@ -65,7 +65,7 @@ Variance of types is automatically determined as follows | `std::marker::PhantomData` | | covariant | | `Trait + 'a` | covariant | invariant | -The variance of other `struct`, `enum`, `union` and tuple types is decided by +The variance of other `struct`, `enum`, `union`, and tuple types is decided by looking at the variance of the types of their fields. If the parameter is used in positions with different variances then the parameter is invariant. For example the following struct is covariant in `'a` and `T` and invariant in `'b` diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index a9aa87d183..649bee4354 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -92,7 +92,7 @@ A suffix is a non-raw identifier immediately (without whitespace) following the primary part of a literal. Any kind of literal (string, integer, etc) with any suffix is valid as a token, -and can be passed to a macro without producing an error. +and can be passed to a macro without producing an error. The macro itself will decide how to interpret such a token and whether to produce an error or not. ```rust @@ -101,7 +101,7 @@ macro_rules! blackhole { ($tt:tt) => () } blackhole!("string"suffix); // OK ``` -However, suffixes on literal tokens parsed as Rust code are restricted. +However, suffixes on literal tokens parsed as Rust code are restricted. Any suffixes are rejected on non-numeric literal tokens, and numeric literal tokens are accepted only with suffixes from the list below. @@ -150,11 +150,12 @@ A _string literal_ is a sequence of any Unicode characters enclosed within two `U+0022` (double-quote) characters, with the exception of `U+0022` itself, which must be _escaped_ by a preceding `U+005C` character (`\`). -Line-break characters are allowed in string literals. Normally they represent -themselves (i.e. no translation), but as a special exception, when an unescaped -`U+005C` character (`\`) occurs immediately before the newline (`U+000A`), the -`U+005C` character, the newline, and all whitespace at the beginning of the -next line are ignored. Thus `a` and `b` are equal: +Line-breaks are allowed in string literals. A line-break is either a newline +(`U+000A`) or a pair of carriage return and newline (`U+000D`, `U+000A`). Both +byte sequences are normally translated to `U+000A`, but as a special exception, +when an unescaped `U+005C` character (`\`) occurs immediately before the +line-break, the `U+005C` character, the line-break, and all whitespace at the +beginning of the next line are ignored. Thus `a` and `b` are equal: ```rust let a = "foobar"; @@ -361,7 +362,7 @@ An _integer literal_ has one of four forms: mixture of *decimal digits* and _underscores_. * A _tuple index_ is either `0`, or starts with a *non-zero decimal digit* and continues with zero or more decimal digits. Tuple indexes are used to refer - to the fields of [tuples], [tuple structs] and [tuple variants]. + to the fields of [tuples], [tuple structs], and [tuple variants]. * A _hex literal_ starts with the character sequence `U+0030` `U+0078` (`0x`) and continues as any mixture (with at least one digit) of hex digits and underscores. @@ -429,7 +430,7 @@ Examples of invalid integer literals: 128_i8; 256_u8; -// bin, hex and octal literals must have at least one digit +// bin, hex, and octal literals must have at least one digit 0b_; 0b____; diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 2e85e3596e..b0cc71a734 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -69,9 +69,9 @@ Pointers to sized types have the same size and alignment as `usize`. Pointers to unsized types are sized. The size and alignment is guaranteed to be at least equal to the size and alignment of a pointer. -> Note: Though you should not rely on this, all pointers to title="Dynamically Sized Types">DSTs are currently twice the size of -> the size of `usize` and have the same alignment. +> Note: Though you should not rely on this, all pointers to +> DSTs are currently twice the +> size of the size of `usize` and have the same alignment. ## Array Layout diff --git a/src/doc/reference/src/types.md b/src/doc/reference/src/types.md index e105dab0fc..1a3fbab820 100644 --- a/src/doc/reference/src/types.md +++ b/src/doc/reference/src/types.md @@ -1,7 +1,7 @@ {{#include types-redirect.html}} # Types -Every variable, item and value in a Rust program has a type. The _type_ of a +Every variable, item, and value in a Rust program has a type. The _type_ of a *value* defines the interpretation of the memory holding it and the operations that may be performed on the value. @@ -94,7 +94,7 @@ type T<'a> = &'a (dyn Any + Send); ## Recursive types -Nominal types — [structs], [enumerations] and [unions] — may be +Nominal types — [structs], [enumerations], and [unions] — may be recursive. That is, each `enum` variant or `struct` or `union` field may refer, directly or indirectly, to the enclosing `enum` or `struct` type itself. Such recursion has restrictions: diff --git a/src/doc/reference/src/types/function-pointer.md b/src/doc/reference/src/types/function-pointer.md index 44da3ccbde..88ef50c245 100644 --- a/src/doc/reference/src/types/function-pointer.md +++ b/src/doc/reference/src/types/function-pointer.md @@ -51,6 +51,6 @@ x = bo(5,7); [_Type_]: ../types.md#type-expressions [`extern`]: ../items/external-blocks.md [closures]: closure.md -[extern function]: ../items/functions.md#extern-functions +[extern function]: ../items/functions.md#extern-function-qualifier [function items]: function-item.md [unsafe function]: ../unsafe-functions.md diff --git a/src/doc/reference/src/types/trait-object.md b/src/doc/reference/src/types/trait-object.md index 0fd74cec7a..d514e4a2d6 100644 --- a/src/doc/reference/src/types/trait-object.md +++ b/src/doc/reference/src/types/trait-object.md @@ -49,14 +49,6 @@ if the sets of auto traits are the same and the lifetime bounds are the same. For example, `dyn Trait + Send + UnwindSafe` is the same as `dyn Trait + Unwindsafe + Send`. -
- -***Warning:*** With two trait object types, even when the complete set of traits -is the same, if the base traits differ, the type is different. For example, -`dyn Send + Sync` is a different type from `dyn Sync + Send`. See [issue 33140]. - -
- Due to the opaqueness of which concrete type the value is of, trait objects are [dynamically sized types]. Like all DSTs, trait objects are used @@ -109,6 +101,5 @@ inferred with a sensible choice. [auto traits]: ../special-types-and-traits.md#auto-traits [defaults]: ../lifetime-elision.md#default-trait-object-lifetimes [dynamically sized types]: ../dynamically-sized-types.md -[issue 33140]: https://github.com/rust-lang/rust/issues/33140 [object safe]: ../items/traits.md#object-safety [supertraits]: ../items/traits.md#supertraits diff --git a/src/doc/reference/stable-check/Cargo.toml b/src/doc/reference/stable-check/Cargo.toml index 691722a0b2..1e3869b89f 100644 --- a/src/doc/reference/stable-check/Cargo.toml +++ b/src/doc/reference/stable-check/Cargo.toml @@ -2,5 +2,4 @@ name = "stable-check" version = "0.1.0" authors = ["steveklabnik "] - -[dependencies] +edition = "2018" diff --git a/src/doc/reference/stable-check/src/main.rs b/src/doc/reference/stable-check/src/main.rs index a9de831334..c0b1acc838 100644 --- a/src/doc/reference/stable-check/src/main.rs +++ b/src/doc/reference/stable-check/src/main.rs @@ -20,7 +20,7 @@ fn main() { } } -fn check_directory(dir: &Path) -> Result<(), Box> { +fn check_directory(dir: &Path) -> Result<(), Box> { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md index d4056e90ef..b23b3fc12a 100644 --- a/src/doc/rust-by-example/README.md +++ b/src/doc/rust-by-example/README.md @@ -9,7 +9,7 @@ Learn Rust with examples (Live code editor included) ## Using -If you'd like to read Rust by Example, you can visit https://doc.rust-lang.org/rust-by-example/ +If you'd like to read Rust by Example, you can visit https://doc.rust-lang.org/rust-by-example/ to read it online. If you'd like to read it locally, [install Rust], and then: @@ -38,7 +38,7 @@ Please see the [CONTRIBUTING.md] file for more details. * [Chinese](https://github.com/rust-lang-cn/rust-by-example-cn) * [Japanese](https://github.com/rust-lang-ja/rust-by-example-ja) * [French](https://github.com/Songbird0/FR_RBE) -* [Russian](https://github.com/ruRust/rust-by-example-ru) +* [Russian](https://github.com/ruRust/rust-by-example) ## License diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 6121054342..cd6bbc7b4f 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -36,6 +36,7 @@ - [Conversion](conversion.md) - [`From` and `Into`](conversion/from_into.md) + - [`TryFrom` and `TryInto`](conversion/try_from_try_into.md) - [To and from `String`s](conversion/string.md) - [Expressions](expression.md) @@ -132,10 +133,14 @@ - [Traits](trait.md) - [Derive](trait/derive.md) + - [Returning Traits with `dyn`](trait/dyn.md) - [Operator Overloading](trait/ops.md) - [Drop](trait/drop.md) - [Iterators](trait/iter.md) + - [`impl Trait`](trait/impl_trait.md) - [Clone](trait/clone.md) + - [Supertraits](traits/supertraits.md) + - [Disambiguating overlapping traits](traits/disambiguating.md) - [macro_rules!](macros.md) - [Syntax](macros/syntax.md) @@ -149,6 +154,7 @@ - [Error handling](error.md) - [`panic`](error/panic.md) - [`Option` & `unwrap`](error/option_unwrap.md) + - [Unpacking options with `?`](error/option_unwrap/question_mark.md) - [Combinators: `map`](error/option_unwrap/map.md) - [Combinators: `and_then`](error/option_unwrap/and_then.md) - [`Result`](error/result.md) diff --git a/src/doc/rust-by-example/src/conversion/try_from_try_into.md b/src/doc/rust-by-example/src/conversion/try_from_try_into.md new file mode 100644 index 0000000000..230600bf64 --- /dev/null +++ b/src/doc/rust-by-example/src/conversion/try_from_try_into.md @@ -0,0 +1,45 @@ +# `TryFrom` and `TryInto` + +Similar to [`From` and `Into`][from-into], [`TryFrom`] and [`TryInto`] are +generic traits for converting between types. Unlike `From`/`Into`, the +`TryFrom`/`TryInto` traits are used for fallible conversions, and as such, +return [`Result`]s. + +[from-into]: from_into.html +[`TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html +[`TryInto`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html +[`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html + +```rust +use std::convert::TryFrom; +use std::convert::TryInto; + +#[derive(Debug, PartialEq)] +struct EvenNumber(i32); + +impl TryFrom for EvenNumber { + type Error = (); + + fn try_from(value: i32) -> Result { + if value % 2 == 0 { + Ok(EvenNumber(value)) + } else { + Err(()) + } + } +} + +fn main() { + // TryFrom + + assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8))); + assert_eq!(EvenNumber::try_from(5), Err(())); + + // TryInto + + let result: Result = 8i32.try_into(); + assert_eq!(result, Ok(EvenNumber(8))); + let result: Result = 5i32.try_into(); + assert_eq!(result, Err(())); +} +``` diff --git a/src/doc/rust-by-example/src/custom_types/enum.md b/src/doc/rust-by-example/src/custom_types/enum.md index 5eae819adc..8580ce9f74 100644 --- a/src/doc/rust-by-example/src/custom_types/enum.md +++ b/src/doc/rust-by-example/src/custom_types/enum.md @@ -53,11 +53,56 @@ fn main() { ``` +## Type aliases + +If you use a type alias, you can refer to each enum variant via its alias. +This might be useful if the enum's name is too long or too generic, and you +want to rename it. + +```rust,editable +enum VeryVerboseEnumOfThingsToDoWithNumbers { + Add, + Subtract, +} + +// Creates a type alias +type Operations = VeryVerboseEnumOfThingsToDoWithNumbers; + +fn main() { + // We can refer to each variant via its alias, not its long and inconvenient + // name. + let x = Operations::Add; +} +``` + +The most common place you'll see this is in `impl` blocks using the `Self` alias. + +```rust,editable +enum VeryVerboseEnumOfThingsToDoWithNumbers { + Add, + Subtract, +} + +impl VeryVerboseEnumOfThingsToDoWithNumbers { + fn run(&self, x: i32, y: i32) -> i32 { + match self { + Self::Add => x + y, + Self::Subtract => x - y, + } + } +} +``` + +To learn more about enums and type aliases, you can read the +[stabilization report][aliasreport] from when this feature was stabilized into +Rust. + ### See also: -[`match`][match], [`fn`][fn], and [`String`][str] +[`match`][match], [`fn`][fn], and [`String`][str], [] [c_struct]: https://en.wikipedia.org/wiki/Struct_(C_programming_language) [match]: ../flow_control/match.md [fn]: ../fn.md [str]: ../std/str.md +[aliasreport]: https://github.com/rust-lang/rust/pull/61682/#issuecomment-502472847 diff --git a/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md b/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md new file mode 100644 index 0000000000..7437ff6c84 --- /dev/null +++ b/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md @@ -0,0 +1,58 @@ +# Unpacking options with `?` + +You can unpack `Option`s by using `match` statements, but it's often easier to +use the `?` operator. If `x` is an `Option`, then evaluating `x?` will return +the underlying value if `x` is `Some`, otherwise it will terminate whatever +function is being executed and return `None`. + +```rust,editable +fn next_birthday(current_age: Option) -> Option { + // If `current_age` is `None`, this returns `None`. + // If `current_age` is `Some`, the inner `u8` gets assigned to `next_age` + let next_age: u8 = current_age?; + Some(format!("Next year I will be {}", next_age)) +} +``` + +You can chain many `?`s together to make your code much more readable. + +```rust,editable +struct Person { + job: Option, +} + +#[derive(Clone, Copy)] +struct Job { + phone_number: Option, +} + +#[derive(Clone, Copy)] +struct PhoneNumber { + area_code: Option, + number: u32, +} + +impl Person { + + // Gets the area code of the phone number of the person's job, if it exists. + fn work_phone_area_code(&self) -> Option { + // This would need many nested `match` statements without the `?` operator. + // It would take a lot more code - try writing it yourself and see which + // is easier. + self.job?.phone_number?.area_code + } +} + +fn main() { + let p = Person { + job: Some(Job { + phone_number: Some(PhoneNumber { + area_code: Some(61), + number: 439222222, + }), + }), + }; + + assert_eq!(p.work_phone_area_code(), Some(61)); +} +``` diff --git a/src/doc/rust-by-example/src/error/result/enter_question_mark.md b/src/doc/rust-by-example/src/error/result/enter_question_mark.md index 5fb9ccfb02..8101e3efd7 100644 --- a/src/doc/rust-by-example/src/error/result/enter_question_mark.md +++ b/src/doc/rust-by-example/src/error/result/enter_question_mark.md @@ -10,7 +10,7 @@ Upon finding an `Err`, there are two valid actions to take: 2. `return` because an `Err` means it cannot be handled `?` is *almost*[^†] exactly equivalent to an `unwrap` which `return`s -instead of `panic`s on `Err`s. Let's see how we can simplify the earlier +instead of `panic`king on `Err`s. Let's see how we can simplify the earlier example that used combinators: ```rust,editable diff --git a/src/doc/rust-by-example/src/flow_control/for.md b/src/doc/rust-by-example/src/flow_control/for.md index a8a4762a2d..591b86637c 100644 --- a/src/doc/rust-by-example/src/flow_control/for.md +++ b/src/doc/rust-by-example/src/flow_control/for.md @@ -113,7 +113,7 @@ In the above snippets note the type of `match` branch, that is the key difference in the types of iteration. The difference in type then of course implies differing actions that are able to be performed. -### See also +### See also: [Iterator][iter] diff --git a/src/doc/rust-by-example/src/flow_control/if_let.md b/src/doc/rust-by-example/src/flow_control/if_let.md index 6b5c200080..a5671332b9 100644 --- a/src/doc/rust-by-example/src/flow_control/if_let.md +++ b/src/doc/rust-by-example/src/flow_control/if_let.md @@ -91,6 +91,11 @@ fn main() { if let Foo::Qux(value) = c { println!("c is {}", value); } + + // Binding also works with `if let` + if let Foo::Qux(value @ 100) = c { + println!("c is one hundred"); + } } ``` diff --git a/src/doc/rust-by-example/src/flow_control/match/binding.md b/src/doc/rust-by-example/src/flow_control/match/binding.md index d3e5d46fdb..e1aa232169 100644 --- a/src/doc/rust-by-example/src/flow_control/match/binding.md +++ b/src/doc/rust-by-example/src/flow_control/match/binding.md @@ -26,7 +26,29 @@ fn main() { } ``` +You can also use binding to "destructure" `enum` variants, such as `Option`: + +```rust,editable +fn some_number() -> Option { + Some(42) +} + +fn main() { + match some_number() { + // Got `Some` variant, match if its value, bound to `n`, + // is equal to 42. + Some(n @ 42) => println!("The Answer: {}!", n), + // Match any other number. + Some(n) => println!("Not interesting... {}", n), + // Match anything else (`None` variant). + _ => (), + } +} +``` + ### See also: -[functions] +[`functions`][functions], [`enums`][enums] and [`Option`][option] [functions]: ../../fn.md +[enums]: ../../custom_types/enum.md +[option]: ../../std/option.md diff --git a/src/doc/rust-by-example/src/fn/closures/output_parameters.md b/src/doc/rust-by-example/src/fn/closures/output_parameters.md index 0810b281ac..4ac4dd0c4a 100644 --- a/src/doc/rust-by-example/src/fn/closures/output_parameters.md +++ b/src/doc/rust-by-example/src/fn/closures/output_parameters.md @@ -1,11 +1,9 @@ # As output parameters -Closures as input parameters are possible, so returning closures as -output parameters should also be possible. However, returning closure types -are problematic because Rust currently only supports returning concrete -(non-generic) types. Anonymous closure types are, by definition, unknown -and so returning a closure is only possible by making it concrete. This -can be done via boxing. +Closures as input parameters are possible, so returning closures as +output parameters should also be possible. However, anonymous +closure types are, by definition, unknown, so we have to use +`impl Trait` to return them. The valid traits for returns are slightly different than before: @@ -21,16 +19,16 @@ dropped as soon as the function exited, leaving invalid references in the closure. ```rust,editable -fn create_fn() -> Box { +fn create_fn() -> impl Fn() { let text = "Fn".to_owned(); - Box::new(move || println!("This is a: {}", text)) + move || println!("This is a: {}", text) } -fn create_fnmut() -> Box { +fn create_fnmut() -> impl FnMut() { let text = "FnMut".to_owned(); - Box::new(move || println!("This is a: {}", text)) + move || println!("This is a: {}", text) } fn main() { @@ -44,10 +42,10 @@ fn main() { ### See also: -[Boxing][box], [`Fn`][fn], [`FnMut`][fnmut], and [Generics][generics]. +[`Fn`][fn], [`FnMut`][fnmut], [Generics][generics] and [impl Trait][impltrait]. -[box]: ../../std/box.md [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html [fnmut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html -[fnbox]: https://doc.rust-lang.org/std/boxed/trait.FnBox.html +[fnbox]: https://doc.rust-lang.org/std/boxed/trait.FnBox.html [generics]: ../../generics.md +[impltrait]: ../../trait/impl_trait.md diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index 7b1b7ed41e..00b750c8b3 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -80,7 +80,7 @@ Implementing the `fmt::Display` trait automatically implements the check the [`std::fmt`][fmt] documentation for setting the number of decimals to display) -### See also +### See also: [`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], and [`traits`][traits] diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index 5cdcda89f0..dd698d29fc 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -82,7 +82,7 @@ Two hints if you get stuck: * You [may need to list each color more than once][named_parameters], * You can [pad with zeros to a width of 2][fmt_width] with `:02`. -### See also +### See also: [`std::fmt`][fmt] diff --git a/src/doc/rust-by-example/src/hello/print/print_debug.md b/src/doc/rust-by-example/src/hello/print/print_debug.md index 05df667f0d..9f65460768 100644 --- a/src/doc/rust-by-example/src/hello/print/print_debug.md +++ b/src/doc/rust-by-example/src/hello/print/print_debug.md @@ -72,7 +72,7 @@ fn main() { One can manually implement `fmt::Display` to control the display. -### See also +### See also: [attributes][attributes], [`derive`][derive], [`std::fmt`][fmt], and [`struct`][structs] diff --git a/src/doc/rust-by-example/src/hello/print/print_display.md b/src/doc/rust-by-example/src/hello/print/print_display.md index 55ed8702ad..2083a5f643 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display.md +++ b/src/doc/rust-by-example/src/hello/print/print_display.md @@ -116,7 +116,7 @@ Display: 3.3 + 7.2i Debug: Complex { real: 3.3, imag: 7.2 } ``` -### See also +### See also: [`derive`][derive], [`std::fmt`][fmt], [macros], [`struct`][structs], [`trait`][traits], and [use][use] diff --git a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md index c44c022c62..735b356952 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md +++ b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md @@ -66,7 +66,7 @@ Try changing the program so that the index of each element in the vector is also [0: 1, 1: 2, 2: 3] ``` -### See also +### See also: [`for`][for], [`ref`][ref], [`Result`][result], [`struct`][struct], [`?`][q_mark], and [`vec!`][vec] diff --git a/src/doc/rust-by-example/src/macros.md b/src/doc/rust-by-example/src/macros.md index ac727f463f..ffeb923e50 100644 --- a/src/doc/rust-by-example/src/macros.md +++ b/src/doc/rust-by-example/src/macros.md @@ -35,6 +35,6 @@ So why are macros useful? 2. Domain-specific languages. Macros allow you to define special syntax for a specific purpose. (More on this later) -3. Variadic interfaces. Sometime you want to define an interface that takes a +3. Variadic interfaces. Sometimes you want to define an interface that takes a variable number of arguments. An example is `println!` which could take any number of arguments, depending on the format string!. (More on this later) diff --git a/src/doc/rust-by-example/src/std/rc.md b/src/doc/rust-by-example/src/std/rc.md index d89dd9057b..358bd45f39 100644 --- a/src/doc/rust-by-example/src/std/rc.md +++ b/src/doc/rust-by-example/src/std/rc.md @@ -46,7 +46,7 @@ fn main() { } ``` -### See also +### See also: [std::rc][1] and [Arc][2]. diff --git a/src/doc/rust-by-example/src/std_misc/path.md b/src/doc/rust-by-example/src/std_misc/path.md index ae66529c6b..eb83df8e10 100644 --- a/src/doc/rust-by-example/src/std_misc/path.md +++ b/src/doc/rust-by-example/src/std_misc/path.md @@ -38,7 +38,7 @@ fn main() { Be sure to check at other `Path` methods (`posix::Path` or `windows::Path`) and the `Metadata` struct. -### See also +### See also: [OsStr][1] and [Metadata][2]. diff --git a/src/doc/rust-by-example/src/testing/unit_testing.md b/src/doc/rust-by-example/src/testing/unit_testing.md index 22b93435c8..cd87706640 100644 --- a/src/doc/rust-by-example/src/testing/unit_testing.md +++ b/src/doc/rust-by-example/src/testing/unit_testing.md @@ -70,6 +70,35 @@ failures: test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out ``` +## Tests and `?` +None of the previous unit test examples had a return type. But in Rust 2018, +your unit tests can return `Result<()>`, which lets you use `?` in them! This +can make them much more concise. + +```rust,editable +fn sqrt(number: f64) -> Result { + if number >= 0.0 { + Ok(number.powf(0.5)) + } else { + Err("negative floats don't have square roots".to_owned()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sqrt() -> Result<(), String> { + let x = 4.0; + assert_eq!(sqrt(x)?.powf(2.0), x); + Ok(()) + } +} +``` + +See ["The Edition Guide"][editionguide] for more details. + ## Testing panics To check functions that should panic under certain circumstances, use attribute @@ -230,3 +259,4 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out [panic]: ../std/panic.md [macros]: ../macros.md [mod]: ../mod.md +[editionguide]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/question-mark-in-main-and-tests.html diff --git a/src/doc/rust-by-example/src/trait/dyn.md b/src/doc/rust-by-example/src/trait/dyn.md new file mode 100644 index 0000000000..5b2f8c2f3e --- /dev/null +++ b/src/doc/rust-by-example/src/trait/dyn.md @@ -0,0 +1,47 @@ +# Returning Traits with `dyn` + +The Rust compiler needs to know how much space every function's return type requires. This means all your functions have to return a concrete type. Unlike other languages, if you have a trait like `Animal`, you can't write a function that returns `Animal`, because its different implementations will need different amounts of memory. + +However, there's an easy workaround. Instead of returning a trait object directly, our functions return a `Box` which _contains_ some `Animal`. A `box` is just a reference to some memory in the heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a heap-allocated `Animal`, we can return a trait from our function! + +Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the `dyn` keyword, e.g. `Box`. + +```rust,editable +struct Sheep {} +struct Cow {} + +trait Animal { + // Instance method signature + fn noise(&self) -> &'static str; +} + +// Implement the `Animal` trait for `Sheep`. +impl Animal for Sheep { + fn noise(&self) -> &'static str { + "baaaaah!" + } +} + +// Implement the `Animal` trait for `Cow`. +impl Animal for Cow { + fn noise(&self) -> &'static str { + "moooooo!" + } +} + +// Returns some struct that implements Animal, but we don't know which one at compile time. +fn random_animal(random_number: f64) -> Box { + if random_number < 0.5 { + Box::new(Sheep {}) + } else { + Box::new(Cow {}) + } +} + +fn main() { + let random_number = 0.234; + let animal = random_animal(random_number); + println!("You've randomly chosen an animal, and it says {}", animal.noise()); +} + +``` \ No newline at end of file diff --git a/src/doc/rust-by-example/src/trait/impl_trait.md b/src/doc/rust-by-example/src/trait/impl_trait.md new file mode 100644 index 0000000000..601aaa3b64 --- /dev/null +++ b/src/doc/rust-by-example/src/trait/impl_trait.md @@ -0,0 +1,59 @@ +# `impl Trait` + +If your function returns a type that implements `MyTrait`, you can write its +return type as `-> impl MyTrait`. This can help simplify your type signatures quite a lot! + +```rust,editable +use std::iter; +use std::vec::IntoIter; + +// This function combines two `Vec` and returns an iterator over it. +// Look how complicated its return type is! +fn combine_vecs_explicit_return_type<'a>( + v: Vec, + u: Vec, +) -> iter::Cycle, IntoIter>> { + v.into_iter().chain(u.into_iter()).cycle() +} + +// This is the exact same function, but its return type uses `impl Trait`. +// Look how much simpler it is! +fn combine_vecs<'a>( + v: Vec, + u: Vec, +) -> impl Iterator { + v.into_iter().chain(u.into_iter()).cycle() +} +``` + +More importantly, some Rust types can't be written out. For example, every +closure has its own unnamed concrete type. Before `impl Trait` syntax, you had +to allocate on the heap in order to return a closure. But now you can do it all +statically, like this: + +```rust,editable +// Returns a function that adds `y` to its input +fn make_adder_function(y: i32) -> impl Fn(i32) -> i32 { + let closure = move |x: i32| { x + y }; + closure +} + +fn main() { + let plus_one = make_adder_function(1); + assert_eq!(plus_one(2), 3); +} +``` + +You can also use `impl Trait` to return an iterator that uses `map` or `filter` +closures! This makes using `map` and `filter` easier. Because closure types don't +have names, you can't write out an explicit return type if your function returns +iterators with closures. But with `impl Trait` you can do this easily: + +```rust,editable +fn double_positives<'a>(numbers: &'a Vec) -> impl Iterator + 'a { + numbers + .iter() + .filter(|x| x > &&0) + .map(|x| x * 2) +} +``` diff --git a/src/doc/rust-by-example/src/trait/iter.md b/src/doc/rust-by-example/src/trait/iter.md index 91f65a53cc..9c9540985b 100644 --- a/src/doc/rust-by-example/src/trait/iter.md +++ b/src/doc/rust-by-example/src/trait/iter.md @@ -38,7 +38,7 @@ impl Iterator for Fibonacci { // Returns a Fibonacci sequence generator fn fibonacci() -> Fibonacci { - Fibonacci { curr: 1, next: 1 } + Fibonacci { curr: 0, next: 1 } } fn main() { diff --git a/src/doc/rust-by-example/src/traits/disambiguating.md b/src/doc/rust-by-example/src/traits/disambiguating.md new file mode 100644 index 0000000000..c893e9dc8d --- /dev/null +++ b/src/doc/rust-by-example/src/traits/disambiguating.md @@ -0,0 +1,62 @@ +# Disambiguating overlapping traits + +A type can implement many different traits. What if two traits both require the same name? For example, many traits might have a method named `get()`. They might even have different return types! + +Good news: because each trait implementation gets its own `impl` block, it's +clear which trait's `get` method you're implementing. + +What about when it comes time to _call_ those methods? To disambiguate between +them, we have to use Fully Qualified Syntax. + +```rust,editable +trait UsernameWidget { + // Get the selected username out of this widget + fn get(&self) -> String; +} + +trait AgeWidget { + // Get the selected age out of this widget + fn get(&self) -> u8; +} + +// A form with both a UsernameWidget and an AgeWidget +struct Form { + username: String, + age: u8, +} + +impl UsernameWidget for Form { + fn get(&self) -> String { + self.username.clone() + } +} + +impl AgeWidget for Form { + fn get(&self) -> u8 { + self.age + } +} + +fn main() { + let form = Form{ + username: "rustacean".to_owned(), + age: 28, + }; + + // If you uncomment this line, you'll get an error saying + // "multiple `get` found". Because, after all, there are multiple methods + // named `get`. + // println!("{}", form.get()); + + let username =
::get(&form); + assert_eq!("rustacean".to_owned(), username); + let age = ::get(&form); + assert_eq!(28, age); +} +``` + +### See also: + +[The Rust Programming Language chapter on Fully Qualified syntax][trpl_fqsyntax] + +[trpl_fqsyntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name diff --git a/src/doc/rust-by-example/src/traits/supertraits.md b/src/doc/rust-by-example/src/traits/supertraits.md new file mode 100644 index 0000000000..b28b8f4c9d --- /dev/null +++ b/src/doc/rust-by-example/src/traits/supertraits.md @@ -0,0 +1,43 @@ +# Supertraits + +Rust doesn't have "inheritance", but you can define a trait as being a superset +of another trait. For example: + +```rust,editable +trait Person { + fn name(&self) -> String; +} + +// Student is a supertrait of Person. +// Implementing Student requires you to also impl Person. +trait Student: Person { + fn university(&self) -> String; +} + +trait Programmer { + fn fav_language(&self) -> String; +} + +// CompSciStudent (computer science student) is a supertrait of both Programmer +// and Student. Implementing CompSciStudent requires you to impl both subtraits. +trait CompSciStudent: Programmer + Student { + fn git_username(&self) -> String; +} + +fn comp_sci_student_greeting(student: &dyn CompSciStudent) -> String { + format!( + "My name is {} and I attend {}. My Git username is {}", + student.name(), + student.university(), + student.git_username() + ) +} + +fn main() {} +``` + +### See also: + +[The Rust Programming Language chapter on supertraits][trpl_supertraits] + +[trpl_supertraits]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait diff --git a/src/doc/rustc-guide/.travis.yml b/src/doc/rustc-guide/.travis.yml index bd72a03fc0..c33c38b84f 100644 --- a/src/doc/rustc-guide/.travis.yml +++ b/src/doc/rustc-guide/.travis.yml @@ -3,6 +3,8 @@ rust: - nightly cache: - cargo +- directories: + - $HOME/linkcheck/ before_install: - shopt -s globstar - MAX_LINE_LENGTH=100 bash ci/check_line_lengths.sh src/**/*.md diff --git a/src/doc/rustc-guide/book.toml b/src/doc/rustc-guide/book.toml index 856ef2eba1..1d207bf22a 100644 --- a/src/doc/rustc-guide/book.toml +++ b/src/doc/rustc-guide/book.toml @@ -3,10 +3,14 @@ title = "Guide to Rustc Development" author = "Rustc developers" description = "A guide to developing rustc" +[build] +create-missing = false + [output.html] [output.html.search] [output.linkcheck] +command = "sed 's/.*//'" # tell mdbook not to run, since we want to run it manually follow-web-links = true exclude = [ "crates\\.io", "gcc\\.godbolt\\.org", "youtube\\.com", "dl\\.acm\\.org" ] diff --git a/src/doc/rustc-guide/ci/build-ignore-timeouts.sh b/src/doc/rustc-guide/ci/build-ignore-timeouts.sh old mode 100644 new mode 100755 index e777f349a3..3ec81f6245 --- a/src/doc/rustc-guide/ci/build-ignore-timeouts.sh +++ b/src/doc/rustc-guide/ci/build-ignore-timeouts.sh @@ -2,7 +2,12 @@ output=$(mktemp) -RUST_LOG=mdbook_linkcheck=debug mdbook build 2>&1 | tee $output +mkdir -p book/ +cp -r $HOME/linkcheck/ book/ +RUST_LOG=mdbook_linkcheck=debug mdbook-linkcheck -s 2>&1 | tee -a $output +cp -r book/linkcheck $HOME/ + +mdbook build result=${PIPESTATUS[0]} diff --git a/src/doc/rustc-guide/ci/install.sh b/src/doc/rustc-guide/ci/install.sh index 48df957f97..a81e21c561 100755 --- a/src/doc/rustc-guide/ci/install.sh +++ b/src/doc/rustc-guide/ci/install.sh @@ -21,4 +21,4 @@ function cargo_install() { } cargo_install mdbook 0.3.1 -cargo_install mdbook-linkcheck 0.3.1 +cargo_install mdbook-linkcheck 0.4.0 diff --git a/src/doc/rustc-guide/src/SUMMARY.md b/src/doc/rustc-guide/src/SUMMARY.md index 75e1fcdc24..f672df5101 100644 --- a/src/doc/rustc-guide/src/SUMMARY.md +++ b/src/doc/rustc-guide/src/SUMMARY.md @@ -15,6 +15,7 @@ - [Using `compiletest` + commands to control test execution](./compiletest.md) - [Walkthrough: a typical contribution](./walkthrough.md) - [Implementing new features](./implementing_new_features.md) + - [Stability attributes](./stability.md) - [Stabilizing Features](./stabilization_guide.md) - [Debugging the Compiler](./compiler-debugging.md) - [Profiling the compiler](./profiling.md) @@ -64,7 +65,7 @@ - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) - - [Existential Types](./existential-types.md) + - [Opaque Types](./opaque-types-type-alias-impl-trait.md) - [The MIR (Mid-level IR)](./mir/index.md) - [MIR construction](./mir/construction.md) - [MIR visitor and traversal](./mir/visitor.md) diff --git a/src/doc/rustc-guide/src/appendix/bibliography.md b/src/doc/rustc-guide/src/appendix/bibliography.md index 19a9217f70..03ba3a41ce 100644 --- a/src/doc/rustc-guide/src/appendix/bibliography.md +++ b/src/doc/rustc-guide/src/appendix/bibliography.md @@ -61,7 +61,7 @@ Rust, as well as publications about Rust. * [Reenix: Implementing a Unix-Like Operating System in Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex Light. -* [Evaluation of performance and productivity metrics of potential programming languages in the HPC environment](http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf). +* [Evaluation of performance and productivity metrics of potential programming languages in the HPC environment](https://github.com/1wilkens/thesis-ba). Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust. * [Nom, a byte oriented, streaming, zero copy, parser combinators library in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By @@ -81,7 +81,7 @@ Rust, as well as publications about Rust. * [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf) * [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis. * [Rust-Bio: a fast and safe bioinformatics library](http://bioinformatics.oxfordjournals.org/content/early/2015/10/06/bioinformatics.btv573). Johannes Köster -* [Safe, Correct, and Fast Low-Level Networking](https://octarineparrot.com/assets/msci_paper.pdf). Robert Clipsham's master's thesis. +* [Safe, Correct, and Fast Low-Level Networking](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.704.1768). Robert Clipsham's master's thesis. * [Formalizing Rust traits](http://hdl.handle.net/2429/55609). Jonatan Milewski's master's thesis. * [Rust as a Language for High Performance GC Implementation](http://users.cecs.anu.edu.au/~steveb/downloads/pdf/rust-ismm-2016.pdf) * [Simple Verification of Rust Programs via Functional Purification](https://github.com/Kha/electrolysis). Sebastian Ullrich's master's thesis. diff --git a/src/doc/rustc-guide/src/appendix/code-index.md b/src/doc/rustc-guide/src/appendix/code-index.md index 52a7f42d6f..267a3a3ea5 100644 --- a/src/doc/rustc-guide/src/appendix/code-index.md +++ b/src/doc/rustc-guide/src/appendix/code-index.md @@ -19,7 +19,7 @@ Item | Kind | Short description | Chapter | `ParamEnv` | struct | Information about generic parameters or `Self`, useful for working with associated or generic items | [Parameter Environment] | [src/librustc/ty/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html) `ParseSess` | struct | This struct contains information about a parsing session | [The parser] | [src/libsyntax/parse/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/struct.ParseSess.html) `Query` | struct | Represents the result of query to the `Compiler` interface and allows stealing, borrowing, and returning the results of compiler passes. | [The Rustc Driver and Interface] | [src/librustc_interface/queries.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/queries/struct.Query.html) -`Rib` | struct | Represents a single scope of names | [Name resolution] | [src/librustc_resolve/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/struct.Rib.html) +`Rib` | struct | Represents a single scope of names | [Name resolution] | [src/librustc_resolve/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.Rib.html) `Session` | struct | The data associated with a compilation session | [The parser], [The Rustc Driver and Interface] | [src/librustc/session/mod.html](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html) `SourceFile` | struct | Part of the `SourceMap`. Maps AST nodes to their source code for a single source file. Was previously called FileMap | [The parser] | [src/libsyntax_pos/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceFile.html) `SourceMap` | struct | Maps AST nodes to their source code. It is composed of `SourceFile`s. Was previously called CodeMap | [The parser] | [src/libsyntax/source_map.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html) diff --git a/src/doc/rustc-guide/src/borrow_check.md b/src/doc/rustc-guide/src/borrow_check.md index b3eeaa3874..b3864aac47 100644 --- a/src/doc/rustc-guide/src/borrow_check.md +++ b/src/doc/rustc-guide/src/borrow_check.md @@ -8,7 +8,7 @@ enforcing a number of properties: - That you can't move a value while it is borrowed. - That you can't access a place while it is mutably borrowed (except through the reference). -- That you can't mutate a place while it is shared borrowed. +- That you can't mutate a place while it is immutably borrowed. - etc At the time of this writing, the code is in a state of transition. The diff --git a/src/doc/rustc-guide/src/compiler-team.md b/src/doc/rustc-guide/src/compiler-team.md index d611376823..42f6cc0ac0 100644 --- a/src/doc/rustc-guide/src/compiler-team.md +++ b/src/doc/rustc-guide/src/compiler-team.md @@ -27,10 +27,8 @@ who are experts on each one. ## Rust compiler meeting The compiler team has a weekly meeting where we do triage and try to -generally stay on top of new bugs, regressions, and other things. This -general plan for this meeting can be found in -[the rust-compiler-meeting etherpad][etherpad]. It works roughly as -follows: +generally stay on top of new bugs, regressions, and other things. +They are held on [Zulip][zulip]. It works roughly as follows: - **Review P-high bugs:** P-high bugs are those that are sufficiently important for us to actively track progress. P-high bugs should @@ -44,6 +42,8 @@ follows: the team is desired. - **Check for beta nominations:** These are nominations of things to backport to beta. +- **Possibly WG checking:** A WG may give an update at this point, if there is + time. The meeting currently takes place on Thursdays at 10am Boston time (UTC-4 typically, but daylight savings time sometimes makes things diff --git a/src/doc/rustc-guide/src/existential-types.md b/src/doc/rustc-guide/src/existential-types.md deleted file mode 100644 index ef20167c18..0000000000 --- a/src/doc/rustc-guide/src/existential-types.md +++ /dev/null @@ -1,48 +0,0 @@ -# Existential Types - -Existential types are essentially strong type aliases which only expose -a specific set of traits as their interface and the concrete type in the -background is inferred from a certain set of use sites of the existential -type. - -In the language they are expressed via - -```rust,ignore -existential type Foo: Bar; -``` - -This is in existential type named `Foo` which can be interacted with via -the `Bar` trait's interface. - -Since there needs to be a concrete background type, you can currently -express that type by using the existential type in a "defining use site". - -```rust,ignore -struct Struct; -impl Bar for Struct { /* stuff */ } -fn foo() -> Foo { - Struct -} -``` - -Any other "defining use site" needs to produce the exact same type. - -## Defining use site(s) - -Currently only the return value of a function inside can -be a defining use site of an existential type (and only if the return -type of that function contains the existential type). - -The defining use of an existential type can be any code *within* the parent -of the existential type definition. This includes any siblings of the -existential type and all children of the siblings. - -The initiative for *"not causing fatal brain damage to developers due to -accidentally running infinite loops in their brain while trying to -comprehend what the type system is doing"* has decided to disallow children -of existential types to be defining use sites. - -### Associated existential types - -Associated existential types can be defined by any other associated item -on the same trait `impl` or a child of these associated items. diff --git a/src/doc/rustc-guide/src/how-to-build-and-run.md b/src/doc/rustc-guide/src/how-to-build-and-run.md index 8a803e66cc..aac0f211c5 100644 --- a/src/doc/rustc-guide/src/how-to-build-and-run.md +++ b/src/doc/rustc-guide/src/how-to-build-and-run.md @@ -69,10 +69,10 @@ The result is that compiling `rustc` is done in stages: - **Stage 0:** the stage0 compiler is usually (you can configure `x.py` to use something else) the current _beta_ `rustc` compiler and its associated dynamic libraries (which `x.py` will download for you). This stage0 compiler is then - used only to compile `rustbuild`, `std`, `test`, and `rustc`. When compiling - `test` and `rustc`, this stage0 compiler uses the freshly compiled `std`. + used only to compile `rustbuild`, `std`, and `rustc`. When compiling + `rustc`, this stage0 compiler uses the freshly compiled `std`. There are two concepts at play here: a compiler (with its set of dependencies) - and its 'target' or 'object' libraries (`std`, `test`, and `rustc`). + and its 'target' or 'object' libraries (`std` and `rustc`). Both are staged, but in a staggered manner. - **Stage 1:** the code in your clone (for new version) is then compiled with the stage0 compiler to produce the stage1 compiler. @@ -102,8 +102,6 @@ When running `x.py` you will see output such as: ```txt Building stage0 std artifacts Copying stage0 std from stage0 -Building stage0 test artifacts -Copying stage0 test from stage0 Building stage0 compiler artifacts Copying stage0 rustc from stage0 Building LLVM for x86_64-apple-darwin @@ -111,8 +109,6 @@ Building stage0 codegen artifacts Assembling stage1 compiler Building stage1 std artifacts Copying stage1 std from stage1 -Building stage1 test artifacts -Copying stage1 test from stage1 Building stage1 compiler artifacts Copying stage1 rustc from stage1 Building stage1 codegen artifacts @@ -127,13 +123,10 @@ Building rustdoc for stage2 Documenting book redirect pages Documenting stage2 std Building rustdoc for stage1 -Documenting stage2 test Documenting stage2 whitelisted compiler Documenting stage2 compiler Documenting stage2 rustdoc Documenting error index -Uplifting stage1 test -Copying stage2 test from stage1 Uplifting stage1 rustc Copying stage2 rustc from stage1 Building stage2 tool error_index_generator @@ -155,8 +148,6 @@ The following tables indicate the outputs of various stage actions: | `stage0` builds `bootstrap` | `build/bootstrap` | | `stage0` builds `libstd` | `build/HOST/stage0-std/TARGET` | | copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | -| `stage0` builds `libtest` with `stage0-sysroot` | `build/HOST/stage0-test/TARGET` | -| copy `stage0-test` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | | `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` | | copy `stage0-rustc (except executable)` | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | | build `llvm` | `build/HOST/llvm` | @@ -172,8 +163,6 @@ The following tables indicate the outputs of various stage actions: | copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` | | `stage1` builds `libstd` | `build/HOST/stage1-std/TARGET` | | copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | -| `stage1` builds `libtest` | `build/HOST/stage1-test/TARGET` | -| copy `stage1-test` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | | `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` | | copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` | | `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` | @@ -186,8 +175,6 @@ The following tables indicate the outputs of various stage actions: | copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` | | `stage2` builds `libstd` (except HOST?) | `build/HOST/stage2-std/TARGET` | | copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | -| `stage2` builds `libtest` (except HOST?) | `build/HOST/stage2-test/TARGET` | -| copy `stage2-test` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | | `stage2` builds `rustdoc` | `build/HOST/stage2-tools/HOST` | | copy `rustdoc` | `build/HOST/stage2/bin` | @@ -201,10 +188,10 @@ Note that the convention `x.py` uses is that: In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which will later be uplifted to stage1_. -Every time any of the main artifacts (`std`, `test`, `rustc`) are compiled, two +Every time any of the main artifacts (`std` and `rustc`) are compiled, two steps are performed. When `std` is compiled by a stage N compiler, that `std` will be linked to -programs built by the stage N compiler (including test and `rustc` built later +programs built by the stage N compiler (including `rustc` built later on). It will also be used by the stage (N+1) compiler to link against itself. This is somewhat intuitive if one thinks of the stage (N+1) compiler as "just" another program we are building with the stage N compiler. In some ways, `rustc` @@ -213,7 +200,7 @@ another program we are building with the stage N compiler. In some ways, `rustc` So "stage0 std artifacts" are in fact the output of the downloaded stage0 compiler, and are going to be used for anything built by the stage0 compiler: -e.g. `rustc`, `test` artifacts. When it announces that it is "building stage1 +e.g. `rustc` artifacts. When it announces that it is "building stage1 std artifacts" it has moved on to the next bootstrapping phase. This pattern continues in latter stages. @@ -247,9 +234,9 @@ recompiling that `std`. `--keep-stage` simply assumes the previous compile is fine and copies those artifacts into the appropriate place, skipping the cargo invocation. -The reason we first build `std`, then `test`, then `rustc`, is largely just +The reason we first build `std`, then `rustc`, is largely just because we want to minimize `cfg(stage0)` in the code for `rustc`. -Currently `rustc` is always linked against a "new" `std`/`test` so it doesn't +Currently `rustc` is always linked against a "new" `std` so it doesn't ever need to be concerned with differences in std; it can assume that the std is as fresh as possible. @@ -265,7 +252,7 @@ same libraries as the `stage2/bin/rustc` compiler uses itself for programs it links against. This `stage2/bin/rustc` compiler is shipped to end-users, along with the -`stage 1 {std,test,rustc}` artifacts. +`stage 1 {std,rustc}` artifacts. If you want to learn more about `x.py`, read its README.md [here](https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md). @@ -469,6 +456,18 @@ You can also use `--keep-stage 1` when running tests. Something like this: - Initial test run: `./x.py test -i --stage 1 src/test/ui` - Subsequent test run: `./x.py test -i --stage 1 src/test/ui --keep-stage 1` +### Building with system LLVM + +By default, LLVM is built from source, and that can take significant amount of time. +An alternative is to use LLVM already installed on your computer. + +This is specified in the `target` section of `config.toml`: + +```toml +[target.x86_64-unknown-linux-gnu] +llvm-config = "/path/to/llvm/llvm-7.0.1/bin/llvm-config" +``` + ### Other `x.py` commands Here are a few other useful `x.py` commands. We'll cover some of them in detail diff --git a/src/doc/rustc-guide/src/opaque-types-type-alias-impl-trait.md b/src/doc/rustc-guide/src/opaque-types-type-alias-impl-trait.md new file mode 100644 index 0000000000..e78d3c75de --- /dev/null +++ b/src/doc/rustc-guide/src/opaque-types-type-alias-impl-trait.md @@ -0,0 +1,62 @@ +# Opaque types (type alias `impl Trait`) + +Opaque types are syntax to declare an opaque type alias that only +exposes a specific set of traits as their interface; the concrete type in the +background is inferred from a certain set of use sites of the opaque type. + +This is expressed by using `impl Trait` within type aliases, for example: + +```rust,ignore +type Foo = impl Bar; +``` + +This declares an opaque type named `Foo`, of which the only information is that +it implements `Bar`. Therefore, any of `Bar`'s interface can be used on a `Foo`, +but nothing else (regardless of whether it implements any other traits). + +Since there needs to be a concrete background type, you can currently +express that type by using the opaque type in a "defining use site". + +```rust,ignore +struct Struct; +impl Bar for Struct { /* stuff */ } +fn foo() -> Foo { + Struct +} +``` + +Any other "defining use site" needs to produce the exact same type. + +## Defining use site(s) + +Currently only the return value of a function can be a defining use site +of an opaque type (and only if the return type of that function contains +the opaque type). + +The defining use of an opaque type can be any code *within* the parent +of the opaque type definition. This includes any siblings of the +opaque type and all children of the siblings. + +The initiative for *"not causing fatal brain damage to developers due to +accidentally running infinite loops in their brain while trying to +comprehend what the type system is doing"* has decided to disallow children +of opaque types to be defining use sites. + +### Associated opaque types + +Associated opaque types can be defined by any other associated item +on the same trait `impl` or a child of these associated items. For instance: + +```rust,ignore +trait Baz { + type Foo; + fn foo() -> Self::Foo; +} + +struct Quux; + +impl Baz for Quux { + type Foo = impl Bar; + fn foo() -> Self::Foo { ... } +} +``` diff --git a/src/doc/rustc-guide/src/profiling.md b/src/doc/rustc-guide/src/profiling.md index f6771b07bb..b7cc72258c 100644 --- a/src/doc/rustc-guide/src/profiling.md +++ b/src/doc/rustc-guide/src/profiling.md @@ -1,9 +1,16 @@ # Profiling the compiler -This discussion talks about how profile the compiler and find out -where it spends its time. If you just want to get a general overview, -it is often a good idea to just add `-Zself-profile` option to the -rustc command line. This will break down time spent into various -categories. But if you want a more detailed look, you probably want -to break out a custom profiler. +This section talks about how to profile the compiler and find out where it spends its time. + +Depending on what you're trying to measure, there are several different approaches: + +- If you want to see if a PR improves or regresses compiler performance: + - The [rustc-perf](https://github.com/rust-lang-nursery/rustc-perf) project makes this easy and can be triggered to run on a PR via the `@rustc-perf` bot. + +- If you want a medium-to-high level overview of where `rustc` is spending its time: + - The `-Zself-profile` flag and [measureme](https://github.com/rust-lang/measureme) tools offer a query-based approach to profiling. + See [their docs](https://github.com/rust-lang/measureme/blob/master/summarize/Readme.md) for more information. + +- If you want function level performance data or even just more details than the above approaches: + - Consider using a native code profiler such as [perf](profiling/with_perf.html). diff --git a/src/doc/rustc-guide/src/query.md b/src/doc/rustc-guide/src/query.md index 4ab1d079ec..f5961f6ba7 100644 --- a/src/doc/rustc-guide/src/query.md +++ b/src/doc/rustc-guide/src/query.md @@ -35,9 +35,9 @@ will in turn demand information about that crate, starting from the However, that vision is not fully realized. Still, big chunks of the compiler (for example, generating MIR) work exactly like this. -### The Query Evaluation Model in Detail +### Incremental Compilation in Detail -The [Query Evaluation Model in Detail][query-model] chapter gives a more +The [Incremental Compilation in Detail][query-model] chapter gives a more in-depth description of what queries are and how they work. If you intend to write a query of your own, this is a good read. @@ -277,4 +277,4 @@ rustc_queries! { `rustc_queries` macro will generate an appropriate `impl` automatically. -[query-model]: queries/query-evaluation-model-in-detail.html +[query-model]: queries/incremental-compilation-in-detail.md diff --git a/src/doc/rustc-guide/src/stability.md b/src/doc/rustc-guide/src/stability.md new file mode 100644 index 0000000000..46f62e5203 --- /dev/null +++ b/src/doc/rustc-guide/src/stability.md @@ -0,0 +1,52 @@ +# Stability attributes + +This section is about the stability attributes and schemes that allow stable APIs to use unstable +APIs internally in the rustc standard library. + +For instructions on stabilizing a language feature see +[Stabilizing Features](./stabilization_guide.md). + +# unstable + +The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` attribute explicitly +marks an item as unstable. This infects all sub-items, where the attribute doesn't have to be +reapplied. So if you apply this to a module, all items in the module will be unstable. + +You can make specific sub-items stable by using the `#[stable]` attribute on them. +The stability scheme works similarly to how `pub` works. You can have public functions of +nonpublic modules and you can have stable functions in unstable modules or vice versa. + +Note, however, that due to a [rustc bug], stable items inside unstable modules +*are* available to stable code in that location! So, for example, stable code +can import `core::intrinsics::transmute` even though `intrinsics` is an unstable +module. Thus, this kind of nesting should be avoided when possible. + +[rustc bug]: https://github.com/rust-lang/rust/issues/15702 + +# stable + +The `#[stable(feature = "foo", "since = "1.420.69")]` attribute explicitly marks an item as +stabilized. To do this, follow the instructions in +[Stabilizing Features](./stabilization_guide.md). + +Note that stable functions may use unstable things in their body. + +# allow_internal_unstable + +Macros, compiler desugarings and `const fn`s expose their bodies to the call site. To +work around not being able to use unstable things in the standard library's macros, there's the +`#[allow_internal_unstable(feature1, feature2)]` attribute that whitelists the given features for +usage in stable macros or `const fn`s. + +Note that `const fn`s are even more special in this regard. You can't just whitelist any feature, +the features need an implementation in `qualify_min_const_fn.rs`. For example the `const_fn_union` +feature gate allows accessing fields of unions inside stable `const fn`s. The rules for when it's +ok to use such a feature gate are that behavior matches the runtime behavior of the same code +(see also [this blog post][blog]). This means that you may not create a +`const fn` that e.g. transmutes a memory address to an integer, because the addresses of things +are nondeterministic and often unknown at compile-time. + +Always ping @oli-obk, @RalfJung, and @Centril if you are adding more `allow_internal_unstable` +attributes to any `const fn` + +[blog]: https://www.ralfj.de/blog/2018/07/19/const.html diff --git a/src/doc/rustc-guide/src/traits/bibliography.md b/src/doc/rustc-guide/src/traits/bibliography.md index b8f345d9d2..a0242d4c44 100644 --- a/src/doc/rustc-guide/src/traits/bibliography.md +++ b/src/doc/rustc-guide/src/traits/bibliography.md @@ -21,9 +21,7 @@ environments, and Lambda Prolog-style proof search. Quite readable. ["A new formulation of tabled resolution with delay"][nftrd], by -[Theresa Swift]. This paper gives a kind of abstract treatment of the +Theresa Swift. This paper gives a kind of abstract treatment of the SLG formulation that is the basis for our on-demand solver. [nftrd]: https://dl.acm.org/citation.cfm?id=651202 -[ts]: http://www3.cs.stonybrook.edu/~tswift/ -[Theresa Swift]: http://www3.cs.stonybrook.edu/~tswift/ diff --git a/src/doc/rustc-guide/src/traits/lowering-rules.md b/src/doc/rustc-guide/src/traits/lowering-rules.md index bbebf1450a..c780e7cf58 100644 --- a/src/doc/rustc-guide/src/traits/lowering-rules.md +++ b/src/doc/rustc-guide/src/traits/lowering-rules.md @@ -114,7 +114,7 @@ cover). For each trait, we produce two clauses: // // For each where clause WC: forall { - FromEnv(WC) :- FromEnv(Self: Trait) } ``` diff --git a/src/doc/rustc-ux-guidelines.md b/src/doc/rustc-ux-guidelines.md index e3684fc9f3..dfd8e9db3c 100644 --- a/src/doc/rustc-ux-guidelines.md +++ b/src/doc/rustc-ux-guidelines.md @@ -70,7 +70,7 @@ for details on how to format and write long error codes. [librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/error_codes.rs), [librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/error_codes.rs), [librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/error_codes.rs), - [librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/error_codes.rs), + [librustc_plugin_impl](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/error_codes.rs), [librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/error_codes.rs). * Explanations have full markdown support. Use it, especially to highlight code with backticks. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index d774e46511..5eea9c8687 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -304,3 +304,10 @@ to customize the output: Note that it is invalid to combine the `--json` argument with the `--color` argument, and it is required to combine `--json` with `--error-format=json`. + +## `@path`: load command-line flags from a path + +If you specify `@path` on the command-line, then it will open `path` and read +command line options from it. These options are one per line; a blank line indicates +an empty option. The file can use Unix or Windows style line endings, and must be +encoded as UTF-8. diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index a6e4e166d7..d3dfc3197e 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -208,7 +208,7 @@ error: missing documentation for a function To fix the lint, add documentation to all items. -## single-use-lifetime +## single-use-lifetimes This lint detects lifetimes that are only used once. Some example code that triggers this lint: diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md index 38be07a644..d066f4a9cf 100644 --- a/src/doc/rustc/src/profile-guided-optimization.md +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -125,6 +125,17 @@ RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \ cargo build --release --target=x86_64-unknown-linux-gnu ``` +### Troubleshooting + +- It is recommended to pass `-Cllvm-args=-pgo-warn-missing-function` during the + `-Cprofile-use` phase. LLVM by default does not warn if it cannot find + profiling data for a given function. Enabling this warning will make it + easier to spot errors in your setup. + +- There is a [known issue](https://github.com/rust-lang/cargo/issues/7416) in + Cargo prior to version 1.39 that will prevent PGO from working correctly. Be + sure to use Cargo 1.39 or newer when doing PGO. + ## Further Reading `rustc`'s PGO support relies entirely on LLVM's implementation of the feature diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 6e32468b64..49d05b5038 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -311,19 +311,6 @@ When `rustdoc` receives this flag, it will print an extra "Version (version)" in the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation. -### `--linker`: control the linker used for documentation tests - -Using this flag looks like this: - -```bash -$ rustdoc --test src/lib.rs -Z unstable-options --linker foo -$ rustdoc --test README.md -Z unstable-options --linker foo -``` - -When `rustdoc` runs your documentation tests, it needs to compile and link the tests as executables -before running them. This flag can be used to change the linker used on these executables. It's -equivalent to passing `-C linker=foo` to `rustc`. - ### `--sort-modules-by-appearance`: control how items on module pages are sorted Using this flag looks like this: @@ -484,3 +471,53 @@ Some methodology notes about what rustdoc counts in this metric: Public items that are not documented can be seen with the built-in `missing_docs` lint. Private items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint. + +### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores +``` + +This flag allows you to tag doctests with compiltest style `ignore-foo` filters that prevent +rustdoc from running that test if the target triple string contains foo. For example: + +```rust +///```ignore-foo,ignore-bar +///assert!(2 == 2); +///``` +struct Foo; +``` + +This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`. +If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and +the above example will be run for all targets. +If you want to preserve backwards compatibility for older versions of rustdoc, you can use + +```rust +///```ignore,ignore-foo +///assert!(2 == 2); +///``` +struct Foo; +``` + +In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will +override `ignore`. + +### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it + +Using thses options looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing +``` + +These options can be used to run the doctest under a program, and also pass arguments to +that program. For example, if you want to run your doctests under valgrind you might run + +```bash +$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind +``` + +Another use case would be to run a test inside an emulator, or through a Virtual Machine. diff --git a/src/doc/unstable-book/src/language-features/or-patterns.md b/src/doc/unstable-book/src/language-features/or-patterns.md new file mode 100644 index 0000000000..8ebacb44d3 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/or-patterns.md @@ -0,0 +1,36 @@ +# `or_patterns` + +The tracking issue for this feature is: [#54883] + +[#54883]: https://github.com/rust-lang/rust/issues/54883 + +------------------------ + +The `or_pattern` language feature allows `|` to be arbitrarily nested within +a pattern, for example, `Some(A(0) | B(1 | 2))` becomes a valid pattern. + +## Examples + +```rust,ignore +#![feature(or_patterns)] + +pub enum Foo { + Bar, + Baz, + Quux, +} + +pub fn example(maybe_foo: Option) { + match maybe_foo { + Some(Foo::Bar | Foo::Baz) => { + println!("The value contained `Bar` or `Baz`"); + } + Some(_) => { + println!("The value did not contain `Bar` or `Baz`"); + } + None => { + println!("The value was `None`"); + } + } +} +``` diff --git a/src/doc/unstable-book/src/language-features/param-attrs.md b/src/doc/unstable-book/src/language-features/param-attrs.md deleted file mode 100644 index 4b83c204ba..0000000000 --- a/src/doc/unstable-book/src/language-features/param-attrs.md +++ /dev/null @@ -1,27 +0,0 @@ -# `param_attrs` - -The tracking issue for this feature is: [#60406] - -[#60406]: https://github.com/rust-lang/rust/issues/60406 - -Allow attributes in formal function parameter position so external tools and compiler internals can -take advantage of the additional information that the parameters provide. - -Enables finer conditional compilation with `#[cfg(..)]` and linting control of variables. Moreover, -opens the path to richer DSLs created by users. - ------------------------- - -Example: - -```rust -#![feature(param_attrs)] - -fn len( - #[cfg(windows)] slice: &[u16], - #[cfg(not(windows))] slice: &[u8], -) -> usize -{ - slice.len() -} -``` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 8be4d16998..68877b4843 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -18,7 +18,7 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc. A plugin is a dynamic library crate with a designated *registrar* function that registers extensions with `rustc`. Other crates can load these extensions using the crate attribute `#![plugin(...)]`. See the -`rustc_plugin` documentation for more about the +`rustc_driver::plugin` documentation for more about the mechanics of defining and loading a plugin. If present, arguments passed as `#![plugin(foo(... args ...))]` are not @@ -54,15 +54,15 @@ that implements Roman numeral integer literals. extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; +extern crate rustc_driver; use syntax::parse::token::{self, Token}; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream) -> Box { static NUMERALS: &'static [(&'static str, usize)] = &[ @@ -78,7 +78,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) return DummyResult::any(sp); } - let text = match args[0] { + let text = match args.into_trees().next().unwrap() { TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); @@ -180,11 +180,11 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; +extern crate rustc_driver; use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index 1c525101c7..66a3c8e555 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -14,6 +14,8 @@ TEST_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), '../test/ui/derives/')) TEMPLATE = """\ +// ignore-x86 +// ^ due to stderr output differences // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' {error_deriving} diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss index c22d60b6c5..70648beac3 100644 --- a/src/etc/installer/exe/rust.iss +++ b/src/etc/installer/exe/rust.iss @@ -25,9 +25,9 @@ SourceDir=.\ OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} DefaultDirName={sd}\Rust -Compression=lzma2/ultra -InternalCompressLevel=ultra -SolidCompression=true +Compression=lzma2/normal +InternalCompressLevel=normal +SolidCompression=no ChangesEnvironment=true ChangesAssociations=no diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index a471ccc6f5..a2e378f7b1 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -152,7 +152,7 @@ - + diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index 537b419b32..7c2e91474c 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -45,7 +45,10 @@ def normalize_whitespace(s): def breakpoint_callback(frame, bp_loc, dict): """This callback is registered with every breakpoint and makes sure that the - frame containing the breakpoint location is selected""" + frame containing the breakpoint location is selected """ + + # HACK(eddyb) print a newline to avoid continuing an unfinished line. + print("") print("Hit breakpoint " + str(bp_loc)) # Select the frame and the thread containing it diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js index 2a89c0d321..262a53eabe 100644 --- a/src/etc/wasm32-shim.js +++ b/src/etc/wasm32-shim.js @@ -15,113 +15,7 @@ const buffer = fs.readFileSync(process.argv[2]); Error.stackTraceLimit = 20; let m = new WebAssembly.Module(buffer); - -let memory = null; - -function viewstruct(data, fields) { - return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields); -} - -function copystr(a, b) { - let view = new Uint8Array(memory.buffer).subarray(a, a + b); - return String.fromCharCode.apply(null, view); -} - -function syscall_write([fd, ptr, len]) { - let s = copystr(ptr, len); - switch (fd) { - case 1: process.stdout.write(s); break; - case 2: process.stderr.write(s); break; - } -} - -function syscall_exit([code]) { - process.exit(code); -} - -function syscall_args(params) { - let [ptr, len] = params; - - // Calculate total required buffer size - let totalLen = -1; - for (let i = 2; i < process.argv.length; ++i) { - totalLen += Buffer.byteLength(process.argv[i]) + 1; - } - if (totalLen < 0) { totalLen = 0; } - params[2] = totalLen; - - // If buffer is large enough, copy data - if (len >= totalLen) { - let view = new Uint8Array(memory.buffer); - for (let i = 2; i < process.argv.length; ++i) { - let value = process.argv[i]; - Buffer.from(value).copy(view, ptr); - ptr += Buffer.byteLength(process.argv[i]) + 1; - } - } -} - -function syscall_getenv(params) { - let [keyPtr, keyLen, valuePtr, valueLen] = params; - - let key = copystr(keyPtr, keyLen); - let value = process.env[key]; - - if (value == null) { - params[4] = 0xFFFFFFFF; - } else { - let view = new Uint8Array(memory.buffer); - let totalLen = Buffer.byteLength(value); - params[4] = totalLen; - if (valueLen >= totalLen) { - Buffer.from(value).copy(view, valuePtr); - } - } -} - -function syscall_time(params) { - let t = Date.now(); - let secs = Math.floor(t / 1000); - let millis = t % 1000; - params[1] = Math.floor(secs / 0x100000000); - params[2] = secs % 0x100000000; - params[3] = Math.floor(millis * 1000000); -} - -let imports = {}; -imports.env = { - // These are generated by LLVM itself for various intrinsic calls. Hopefully - // one day this is not necessary and something will automatically do this. - fmod: function(x, y) { return x % y; }, - exp2: function(x) { return Math.pow(2, x); }, - exp2f: function(x) { return Math.pow(2, x); }, - ldexp: function(x, y) { return x * Math.pow(2, y); }, - ldexpf: function(x, y) { return x * Math.pow(2, y); }, - sin: Math.sin, - sinf: Math.sin, - cos: Math.cos, - cosf: Math.cos, - log: Math.log, - log2: Math.log2, - log10: Math.log10, - log10f: Math.log10, - - rust_wasm_syscall: function(index, data) { - switch (index) { - case 1: syscall_write(viewstruct(data, 3)); return true; - case 2: syscall_exit(viewstruct(data, 1)); return true; - case 3: syscall_args(viewstruct(data, 3)); return true; - case 4: syscall_getenv(viewstruct(data, 5)); return true; - case 6: syscall_time(viewstruct(data, 4)); return true; - default: - console.log("Unsupported syscall: " + index); - return false; - } - } -}; - -let instance = new WebAssembly.Instance(m, imports); -memory = instance.exports.memory; +let instance = new WebAssembly.Instance(m, {}); try { instance.exports.main(); } catch (e) { diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index dc7fd1adc2..a39fcd5ad4 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -240,7 +240,7 @@ pub(crate) unsafe fn box_free(ptr: Unique) { #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_allocator_nounwind] pub fn handle_alloc_error(layout: Layout) -> ! { - #[allow(improper_ctypes)] + #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "oom"] fn oom_impl(layout: Layout) -> !; diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c92db517ca..c61e318340 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -91,8 +91,10 @@ use core::ops::{ CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState }; use core::ptr::{self, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; +use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -121,6 +123,34 @@ impl Box { box x } + /// Constructs a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Box> { + let layout = alloc::Layout::new::>(); + let ptr = unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + }; + Box(ptr.cast().into()) + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -130,6 +160,111 @@ impl Box { } } +impl Box<[T]> { + /// Constructs a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + Box(Unique::from(slice)) + } +} + +impl Box> { + /// Converts to `Box`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five: Box = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box { + Box(Box::into_unique(self).cast()) + } +} + +impl Box<[mem::MaybeUninit]> { + /// Converts to `Box<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T]> { + Box(Unique::new_unchecked(Box::into_raw(self) as _)) + } +} + impl Box { /// Constructs a box from a raw pointer. /// diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 9f531f5b83..3d04f30e7b 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1163,6 +1163,9 @@ impl FusedIterator for Drain<'_, T> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl From> for BinaryHeap { + /// Converts a `Vec` into a `BinaryHeap`. + /// + /// This conversion happens in-place, and has `O(n)` time complexity. fn from(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index e067096f0c..0b5a271dbe 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -106,8 +106,8 @@ impl LeafNode { LeafNode { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. - keys: uninit_array![_; CAPACITY], - vals: uninit_array![_; CAPACITY], + keys: [MaybeUninit::UNINIT; CAPACITY], + vals: [MaybeUninit::UNINIT; CAPACITY], parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 @@ -159,7 +159,7 @@ impl InternalNode { unsafe fn new() -> Self { InternalNode { data: LeafNode::new(), - edges: uninit_array![_; 2*B], + edges: [MaybeUninit::UNINIT; 2*B] } } } diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index d3af910a82..0cb91ba4c8 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -3,7 +3,7 @@ use core::borrow::Borrow; use core::cmp::Ordering::{self, Less, Greater, Equal}; -use core::cmp::max; +use core::cmp::{max, min}; use core::fmt::{self, Debug}; use core::iter::{Peekable, FromIterator, FusedIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds}; @@ -187,8 +187,8 @@ pub struct Intersection<'a, T: 'a> { } enum IntersectionInner<'a, T: 'a> { Stitch { - small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets - other_iter: Iter<'a, T>, + a: Iter<'a, T>, + b: Iter<'a, T>, }, Search { small_iter: Iter<'a, T>, @@ -201,12 +201,12 @@ impl fmt::Debug for Intersection<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.inner { IntersectionInner::Stitch { - small_iter, - other_iter, + a, + b, } => f .debug_tuple("Intersection") - .field(&small_iter) - .field(&other_iter) + .field(&a) + .field(&b) .finish(), IntersectionInner::Search { small_iter, @@ -397,8 +397,8 @@ impl BTreeSet { // Iterate both sets jointly, spotting matches along the way. Intersection { inner: IntersectionInner::Stitch { - small_iter: small.iter(), - other_iter: other.iter(), + a: small.iter(), + b: other.iter(), }, } } else { @@ -1221,11 +1221,11 @@ impl Clone for Intersection<'_, T> { Intersection { inner: match &self.inner { IntersectionInner::Stitch { - small_iter, - other_iter, + a, + b, } => IntersectionInner::Stitch { - small_iter: small_iter.clone(), - other_iter: other_iter.clone(), + a: a.clone(), + b: b.clone(), }, IntersectionInner::Search { small_iter, @@ -1245,16 +1245,16 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { fn next(&mut self) -> Option<&'a T> { match &mut self.inner { IntersectionInner::Stitch { - small_iter, - other_iter, + a, + b, } => { - let mut small_next = small_iter.next()?; - let mut other_next = other_iter.next()?; + let mut a_next = a.next()?; + let mut b_next = b.next()?; loop { - match Ord::cmp(small_next, other_next) { - Less => small_next = small_iter.next()?, - Greater => other_next = other_iter.next()?, - Equal => return Some(small_next), + match Ord::cmp(a_next, b_next) { + Less => a_next = a.next()?, + Greater => b_next = b.next()?, + Equal => return Some(a_next), } } } @@ -1272,7 +1272,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { fn size_hint(&self) -> (usize, Option) { let min_len = match &self.inner { - IntersectionInner::Stitch { small_iter, .. } => small_iter.len(), + IntersectionInner::Stitch { a, b } => min(a.len(), b.len()), IntersectionInner::Search { small_iter, .. } => small_iter.len(), }; (0, Some(min_len)) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index a14a3fe999..816a71f255 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -276,7 +276,7 @@ impl LinkedList { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Self { + pub const fn new() -> Self { LinkedList { head: None, tail: None, diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs index 9a6c57d286..ecb5948f11 100644 --- a/src/liballoc/collections/linked_list/tests.rs +++ b/src/liballoc/collections/linked_list/tests.rs @@ -102,8 +102,8 @@ fn test_append() { assert_eq!(m.pop_front(), Some(elt)) } assert_eq!(n.len(), 0); - // let's make sure it's working properly, since we - // did some direct changes to private members + // Let's make sure it's working properly, since we + // did some direct changes to private members. n.push_back(3); assert_eq!(n.len(), 1); assert_eq!(n.pop_front(), Some(3)); diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs index 5a33ddc14f..f1f22fe48c 100644 --- a/src/liballoc/collections/mod.rs +++ b/src/liballoc/collections/mod.rs @@ -41,32 +41,35 @@ pub use linked_list::LinkedList; #[doc(no_inline)] pub use vec_deque::VecDeque; -use crate::alloc::{AllocErr, LayoutErr}; +use crate::alloc::{Layout, LayoutErr}; -/// Augments `AllocErr` with a CapacityOverflow variant. +/// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub enum CollectionAllocErr { +pub enum TryReserveError { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). CapacityOverflow, - /// Error due to the allocator (see the `AllocErr` type's docs). - AllocErr, -} -#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From for CollectionAllocErr { - #[inline] - fn from(AllocErr: AllocErr) -> Self { - CollectionAllocErr::AllocErr - } + /// The memory allocator returned an error + AllocError { + /// The layout of allocation request that failed + layout: Layout, + + #[doc(hidden)] + #[unstable(feature = "container_error_extra", issue = "0", reason = "\ + Enable exposing the allocator’s custom error value \ + if an associated type is added in the future: \ + https://github.com/rust-lang/wg-allocators/issues/23")] + non_exhaustive: (), + }, } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From for CollectionAllocErr { +impl From for TryReserveError { #[inline] fn from(_: LayoutErr) -> Self { - CollectionAllocErr::CapacityOverflow + TryReserveError::CapacityOverflow } } diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 9240346ace..a4a0fbb194 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -18,7 +18,7 @@ use core::ptr::{self, NonNull}; use core::slice; use core::hash::{Hash, Hasher}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::raw_vec::RawVec; use crate::vec::Vec; @@ -576,10 +576,10 @@ impl VecDeque { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -595,7 +595,7 @@ impl VecDeque { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.try_reserve(additional) } @@ -614,10 +614,10 @@ impl VecDeque { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -633,12 +633,12 @@ impl VecDeque { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { let old_cap = self.cap(); let used_cap = self.len() + 1; let new_cap = used_cap.checked_add(additional) .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) - .ok_or(CollectionAllocErr::CapacityOverflow)?; + .ok_or(TryReserveError::CapacityOverflow)?; if new_cap > old_cap { self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; @@ -1199,6 +1199,31 @@ impl VecDeque { } } + /// Removes the last element from the `VecDeque` and returns it, or `None` if + /// it is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.pop_back(), None); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(buf.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option { + if self.is_empty() { + None + } else { + self.head = self.wrap_sub(self.head, 1); + let head = self.head; + unsafe { Some(self.buffer_read(head)) } + } + } + /// Prepends an element to the `VecDeque`. /// /// # Examples @@ -1243,38 +1268,13 @@ impl VecDeque { unsafe { self.buffer_write(head, value) } } - /// Removes the last element from the `VecDeque` and returns it, or `None` if - /// it is empty. - /// - /// # Examples - /// - /// ``` - /// use std::collections::VecDeque; - /// - /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.pop_back(), None); - /// buf.push_back(1); - /// buf.push_back(3); - /// assert_eq!(buf.pop_back(), Some(3)); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn pop_back(&mut self) -> Option { - if self.is_empty() { - None - } else { - self.head = self.wrap_sub(self.head, 1); - let head = self.head; - unsafe { Some(self.buffer_read(head)) } - } - } - #[inline] fn is_contiguous(&self) -> bool { self.tail <= self.head } - /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the - /// last element. + /// Removes an element from anywhere in the `VecDeque` and returns it, + /// replacing it with the first element. /// /// This does not preserve ordering, but is O(1). /// @@ -1288,28 +1288,28 @@ impl VecDeque { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_back(0), None); + /// assert_eq!(buf.swap_remove_front(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_back(0), Some(1)); - /// assert_eq!(buf, [3, 2]); + /// assert_eq!(buf.swap_remove_front(2), Some(3)); + /// assert_eq!(buf, [2, 1]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_back(&mut self, index: usize) -> Option { + pub fn swap_remove_front(&mut self, index: usize) -> Option { let length = self.len(); - if length > 0 && index < length - 1 { - self.swap(index, length - 1); + if length > 0 && index < length && index != 0 { + self.swap(index, 0); } else if index >= length { return None; } - self.pop_back() + self.pop_front() } - /// Removes an element from anywhere in the `VecDeque` and returns it, - /// replacing it with the first element. + /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the + /// last element. /// /// This does not preserve ordering, but is O(1). /// @@ -1323,24 +1323,24 @@ impl VecDeque { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_front(0), None); + /// assert_eq!(buf.swap_remove_back(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_front(2), Some(3)); - /// assert_eq!(buf, [2, 1]); + /// assert_eq!(buf.swap_remove_back(0), Some(1)); + /// assert_eq!(buf, [3, 2]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_front(&mut self, index: usize) -> Option { + pub fn swap_remove_back(&mut self, index: usize) -> Option { let length = self.len(); - if length > 0 && index < length && index != 0 { - self.swap(index, 0); + if length > 0 && index < length - 1 { + self.swap(index, length - 1); } else if index >= length { return None; } - self.pop_front() + self.pop_back() } /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices @@ -1810,7 +1810,7 @@ impl VecDeque { other } - /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// Moves all the elements of `other` into `self`, leaving `other` empty. /// /// # Panics /// @@ -1847,7 +1847,7 @@ impl VecDeque { /// /// let mut buf = VecDeque::new(); /// buf.extend(1..5); - /// buf.retain(|&x| x%2 == 0); + /// buf.retain(|&x| x % 2 == 0); /// assert_eq!(buf, [2, 4]); /// ``` /// diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index a1936b36ac..9e6ed92ffb 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -69,7 +69,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] @@ -84,9 +84,10 @@ #![feature(coerce_unsized)] #![feature(const_generic_impls_guard)] #![feature(const_generics)] -#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))] +#![feature(const_in_array_repeat_expressions)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] +#![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] @@ -116,9 +117,9 @@ #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(rustc_const_unstable)] -#![feature(const_vec_new)] +#![cfg_attr(bootstrap, feature(const_vec_new))] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(mem_take)] @@ -170,3 +171,9 @@ pub mod vec; mod std { pub use core::ops; // RangeFull } + +#[doc(hidden)] +#[unstable(feature = "liballoc_internals", issue = "0", reason = "implementation detail")] +pub mod __export { + pub use core::format_args; +} diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 250c419c53..2f2cdc39c6 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -98,5 +98,5 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) + ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*))) } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 0abab45e92..ee75fc288f 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,8 +7,8 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{Alloc, Layout, Global, handle_alloc_error}; -use crate::collections::CollectionAllocErr::{self, *}; +use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error}; +use crate::collections::TryReserveError::{self, *}; use crate::boxed::Box; #[cfg(test)] @@ -19,26 +19,26 @@ mod tests; /// involved. This type is excellent for building your own data structures like Vec and VecDeque. /// In particular: /// -/// * Produces Unique::empty() on zero-sized types -/// * Produces Unique::empty() on zero-length allocations -/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics) -/// * Guards against 32-bit systems allocating more than isize::MAX bytes -/// * Guards against overflowing your length -/// * Aborts on OOM or calls handle_alloc_error as applicable -/// * Avoids freeing Unique::empty() -/// * Contains a ptr::Unique and thus endows the user with all related benefits +/// * Produces `Unique::empty()` on zero-sized types. +/// * Produces `Unique::empty()` on zero-length allocations. +/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics). +/// * Guards against 32-bit systems allocating more than isize::MAX bytes. +/// * Guards against overflowing your length. +/// * Aborts on OOM or calls `handle_alloc_error` as applicable. +/// * Avoids freeing `Unique::empty()`. +/// * Contains a `ptr::Unique` and thus endows the user with all related benefits. /// /// This type does not in anyway inspect the memory that it manages. When dropped it *will* -/// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec -/// to handle the actual things *stored* inside of a RawVec. +/// free its memory, but it *won't* try to drop its contents. It is up to the user of `RawVec` +/// to handle the actual things *stored* inside of a `RawVec`. /// -/// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types. -/// This enables you to use capacity growing logic catch the overflows in your length +/// Note that a `RawVec` always forces its capacity to be `usize::MAX` for zero-sized types. +/// This enables you to use capacity-growing logic catch the overflows in your length /// that might occur with zero-sized types. /// -/// However this means that you need to be careful when round-tripping this type -/// with a `Box<[T]>`: `capacity()` won't yield the len. However `with_capacity`, -/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity +/// The above means that you need to be careful when round-tripping this type with a +/// `Box<[T]>`, since `capacity()` won't yield the length. However, `with_capacity`, +/// `shrink_to_fit`, and `from_box` will actually set `RawVec`'s private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. #[allow(missing_debug_implementations)] @@ -49,14 +49,14 @@ pub struct RawVec { } impl RawVec { - /// Like `new` but parameterized over the choice of allocator for - /// the returned RawVec. + /// Like `new`, but parameterized over the choice of allocator for + /// the returned `RawVec`. pub const fn new_in(a: A) -> Self { - // !0 is usize::MAX. This branch should be stripped at compile time. - // FIXME(mark-i-m): use this line when `if`s are allowed in `const` + // `!0` is `usize::MAX`. This branch should be stripped at compile time. + // FIXME(mark-i-m): use this line when `if`s are allowed in `const`: //let cap = if mem::size_of::() == 0 { !0 } else { 0 }; - // Unique::empty() doubles as "unallocated" and "zero-sized allocation" + // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation". RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const @@ -65,15 +65,15 @@ impl RawVec { } } - /// Like `with_capacity` but parameterized over the choice of - /// allocator for the returned RawVec. + /// Like `with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self { RawVec::allocate_in(capacity, false, a) } - /// Like `with_capacity_zeroed` but parameterized over the choice - /// of allocator for the returned RawVec. + /// Like `with_capacity_zeroed`, but parameterized over the choice + /// of allocator for the returned `RawVec`. #[inline] pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self { RawVec::allocate_in(capacity, true, a) @@ -86,7 +86,7 @@ impl RawVec { let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); - // handles ZSTs and `capacity = 0` alike + // Handles ZSTs and `capacity == 0` alike. let ptr = if alloc_size == 0 { NonNull::::dangling() } else { @@ -113,20 +113,45 @@ impl RawVec { } impl RawVec { - /// Creates the biggest possible RawVec (on the system heap) - /// without allocating. If T has positive size, then this makes a - /// RawVec with capacity 0. If T has 0 size, then it makes a - /// RawVec with capacity `usize::MAX`. Useful for implementing + /// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform + /// to `min_const_fn` and so they cannot be called in `min_const_fn`s either. + /// + /// If you change `RawVec::new` or dependencies, please take care to not + /// introduce anything that would truly violate `min_const_fn`. + /// + /// NOTE: We could avoid this hack and check conformance with some + /// `#[rustc_force_min_const_fn]` attribute which requires conformance + /// with `min_const_fn` but does not necessarily allow calling it in + /// `stable(...) const fn` / user code not enabling `foo` when + /// `#[rustc_const_unstable(feature = "foo", ..)]` is present. + pub const NEW: Self = Self::new(); + + /// Creates the biggest possible `RawVec` (on the system heap) + /// without allocating. If `T` has positive size, then this makes a + /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a + /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. pub const fn new() -> Self { - Self::new_in(Global) + // FIXME(Centril): Reintegrate this with `fn new_in` when we can. + + // `!0` is `usize::MAX`. This branch should be stripped at compile time. + // FIXME(mark-i-m): use this line when `if`s are allowed in `const`: + //let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + + // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation". + RawVec { + ptr: Unique::empty(), + // FIXME(mark-i-m): use `cap` when ifs are allowed in const + cap: [0, !0][(mem::size_of::() == 0) as usize], + a: Global, + } } - /// Creates a RawVec (on the system heap) with exactly the + /// Creates a `RawVec` (on the system heap) with exactly the /// capacity and alignment requirements for a `[T; capacity]`. This is - /// equivalent to calling RawVec::new when `capacity` is 0 or T is + /// equivalent to calling `RawVec::new` when `capacity` is `0` or `T` is /// zero-sized. Note that if `T` is zero-sized this means you will - /// *not* get a RawVec with the requested capacity! + /// *not* get a `RawVec` with the requested capacity. /// /// # Panics /// @@ -136,13 +161,13 @@ impl RawVec { /// /// # Aborts /// - /// Aborts on OOM + /// Aborts on OOM. #[inline] pub fn with_capacity(capacity: usize) -> Self { RawVec::allocate_in(capacity, false, Global) } - /// Like `with_capacity` but guarantees the buffer is zeroed. + /// Like `with_capacity`, but guarantees the buffer is zeroed. #[inline] pub fn with_capacity_zeroed(capacity: usize) -> Self { RawVec::allocate_in(capacity, true, Global) @@ -150,13 +175,13 @@ impl RawVec { } impl RawVec { - /// Reconstitutes a RawVec from a pointer, capacity, and allocator. + /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. /// /// # Undefined Behavior /// - /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The - /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). - /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed. + /// The `ptr` must be allocated (via the given allocator `a`), and with the given `capacity`. + /// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems). + /// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed. pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), @@ -167,13 +192,13 @@ impl RawVec { } impl RawVec { - /// Reconstitutes a RawVec from a pointer, capacity. + /// Reconstitutes a `RawVec` from a pointer and capacity. /// /// # Undefined Behavior /// - /// The ptr must be allocated (on the system heap), and with the given capacity. The - /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). - /// If the ptr and capacity come from a RawVec, then this is guaranteed. + /// The `ptr` must be allocated (on the system heap), and with the given `capacity`. + /// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems). + /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed. pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), @@ -194,7 +219,7 @@ impl RawVec { impl RawVec { /// Gets a raw pointer to the start of the allocation. Note that this is - /// Unique::empty() if `capacity = 0` or T is zero-sized. In the former case, you must + /// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must /// be careful. pub fn ptr(&self) -> *mut T { self.ptr.as_ptr() @@ -212,12 +237,12 @@ impl RawVec { } } - /// Returns a shared reference to the allocator backing this RawVec. + /// Returns a shared reference to the allocator backing this `RawVec`. pub fn alloc(&self) -> &A { &self.a } - /// Returns a mutable reference to the allocator backing this RawVec. + /// Returns a mutable reference to the allocator backing this `RawVec`. pub fn alloc_mut(&mut self) -> &mut A { &mut self.a } @@ -247,7 +272,7 @@ impl RawVec { /// /// # Panics /// - /// * Panics if T is zero-sized on the assumption that you managed to exhaust + /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust /// all `usize::MAX` slots in your imaginary buffer. /// * Panics on 32-bit platforms if the requested capacity exceeds /// `isize::MAX` bytes. @@ -290,20 +315,20 @@ impl RawVec { unsafe { let elem_size = mem::size_of::(); - // since we set the capacity to usize::MAX when elem_size is - // 0, getting to here necessarily means the RawVec is overfull. + // Since we set the capacity to `usize::MAX` when `elem_size` is + // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); let (new_cap, uniq) = match self.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than - // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as + // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as // a precondition, so this can't overflow. Additionally the // alignment will never be too large as to "not be // satisfiable", so `Layout::from_size_align` will always // return `Some`. // - // tl;dr; we bypass runtime checks due to dynamic assertions + // TL;DR, we bypass runtime checks due to dynamic assertions // in this module, allowing us to use // `from_size_align_unchecked`. let new_cap = 2 * self.cap; @@ -320,8 +345,8 @@ impl RawVec { } } None => { - // skip to 4 because tiny Vec's are dumb; but not if that - // would cause overflow + // Skip to 4 because tiny `Vec`'s are dumb; but not if that + // would cause overflow. let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; match self.a.alloc_array::(new_cap) { Ok(ptr) => (new_cap, ptr.into()), @@ -342,7 +367,7 @@ impl RawVec { /// /// # Panics /// - /// * Panics if T is zero-sized on the assumption that you managed to exhaust + /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust /// all `usize::MAX` slots in your imaginary buffer. /// * Panics on 32-bit platforms if the requested capacity exceeds /// `isize::MAX` bytes. @@ -356,15 +381,15 @@ impl RawVec { None => return false, // nothing to double }; - // since we set the capacity to usize::MAX when elem_size is - // 0, getting to here necessarily means the RawVec is overfull. + // Since we set the capacity to `usize::MAX` when `elem_size` is + // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); - // Since we guarantee that we never allocate more than isize::MAX + // Since we guarantee that we never allocate more than `isize::MAX` // bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so // this can't overflow. // - // Similarly like with `double` above we can go straight to + // Similarly to with `double` above, we can go straight to // `Layout::from_size_align_unchecked` as we know this won't // overflow and the alignment is sufficiently small. let new_cap = 2 * self.cap; @@ -385,7 +410,7 @@ impl RawVec { /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact) } @@ -409,11 +434,11 @@ impl RawVec { /// /// # Aborts /// - /// Aborts on OOM + /// Aborts on OOM. pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -422,9 +447,9 @@ impl RawVec { /// needed_extra_capacity` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize) - -> Result { + -> Result { - // Nothing we can really do about these checks :( + // Nothing we can really do about these checks, sadly. let required_cap = used_capacity.checked_add(needed_extra_capacity) .ok_or(CapacityOverflow)?; // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. @@ -435,7 +460,7 @@ impl RawVec { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized) } @@ -459,7 +484,7 @@ impl RawVec { /// /// # Aborts /// - /// Aborts on OOM + /// Aborts on OOM. /// /// # Examples /// @@ -494,7 +519,7 @@ impl RawVec { pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -538,7 +563,7 @@ impl RawVec { // Here, `cap < used_capacity + needed_extra_capacity <= new_cap` // (regardless of whether `self.cap - used_capacity` wrapped). - // Therefore we can safely call grow_in_place. + // Therefore, we can safely call `grow_in_place`. let new_layout = Layout::new::().repeat(new_cap).unwrap().0; // FIXME: may crash and burn on over-reserve @@ -576,14 +601,14 @@ impl RawVec { return; } - // This check is my waterloo; it's the only thing Vec wouldn't have to do. + // This check is my waterloo; it's the only thing `Vec` wouldn't have to do. assert!(self.cap >= amount, "Tried to shrink to a larger capacity"); if amount == 0 { // We want to create a new zero-length vector within the - // same allocator. We use ptr::write to avoid an + // same allocator. We use `ptr::write` to avoid an // erroneous attempt to drop the contents, and we use - // ptr::read to sidestep condition against destructuring + // `ptr::read` to sidestep condition against destructuring // types that implement Drop. unsafe { @@ -600,7 +625,7 @@ impl RawVec { // // We also know that `self.cap` is greater than `amount`, and // consequently we don't need runtime checks for creating either - // layout + // layout. let old_size = elem_size * self.cap; let new_size = elem_size * amount; let align = mem::align_of::(); @@ -640,10 +665,8 @@ impl RawVec { needed_extra_capacity: usize, fallibility: Fallibility, strategy: ReserveStrategy, - ) -> Result<(), CollectionAllocErr> { + ) -> Result<(), TryReserveError> { unsafe { - use crate::alloc::AllocErr; - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -655,7 +678,7 @@ impl RawVec { return Ok(()); } - // Nothing we can really do about these checks :( + // Nothing we can really do about these checks, sadly. let new_cap = match strategy { Exact => used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?, Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?, @@ -672,12 +695,16 @@ impl RawVec { None => self.a.alloc(new_layout), }; - match (&res, fallibility) { + let ptr = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), - _ => {} - } + (Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError { + layout: new_layout, + non_exhaustive: (), + }), + (Ok(ptr), _) => ptr, + }; - self.ptr = res?.cast().into(); + self.ptr = ptr.cast().into(); self.cap = new_cap; Ok(()) @@ -690,7 +717,7 @@ impl RawVec { /// Converts the entire buffer into `Box<[T]>`. /// /// Note that this will correctly reconstitute any `cap` changes - /// that may have been performed. (see description of type for details) + /// that may have been performed. (See description of type for details.) /// /// # Undefined Behavior /// @@ -698,7 +725,7 @@ impl RawVec { /// the rules around uninitialized boxed values are not finalized yet, /// but until they are, it is advisable to avoid them. pub unsafe fn into_box(self) -> Box<[T]> { - // NOTE: not calling `capacity()` here, actually using the real `cap` field! + // NOTE: not calling `capacity()` here; actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); let output: Box<[T]> = Box::from_raw(slice); mem::forget(self); @@ -707,7 +734,7 @@ impl RawVec { } impl RawVec { - /// Frees the memory owned by the RawVec *without* trying to Drop its contents. + /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. pub unsafe fn dealloc_buffer(&mut self) { let elem_size = mem::size_of::(); if elem_size != 0 { @@ -719,25 +746,23 @@ impl RawVec { } unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec { - /// Frees the memory owned by the RawVec *without* trying to Drop its contents. + /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. fn drop(&mut self) { unsafe { self.dealloc_buffer(); } } } - - // We need to guarantee the following: -// * We don't ever allocate `> isize::MAX` byte-size objects -// * We don't overflow `usize::MAX` and actually allocate too little +// * We don't ever allocate `> isize::MAX` byte-size objects. +// * We don't overflow `usize::MAX` and actually allocate too little. // // On 64-bit we just need to check for overflow since trying to allocate // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add // an extra guard for this in case we're running on a platform which can use -// all 4GB in user-space. e.g., PAE or x32 +// all 4GB in user-space, e.g., PAE or x32. #[inline] -fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if mem::size_of::() < 8 && alloc_size > core::isize::MAX as usize { Err(CapacityOverflow) } else { @@ -749,5 +774,5 @@ fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. fn capacity_overflow() -> ! { - panic!("capacity overflow") + panic!("capacity overflow"); } diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index c389898d1e..d35b62fc1e 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -5,12 +5,12 @@ fn allocator_param() { use crate::alloc::AllocErr; // Writing a test of integration between third-party - // allocators and RawVec is a little tricky because the RawVec + // allocators and `RawVec` is a little tricky because the `RawVec` // API does not expose fallible allocation methods, so we // cannot check what happens when allocator is exhausted // (beyond detecting a panic). // - // Instead, this just checks that the RawVec methods do at + // Instead, this just checks that the `RawVec` methods do at // least go through the Allocator API when it reserves // storage. @@ -44,7 +44,7 @@ fn allocator_param() { fn reserve_does_not_overallocate() { { let mut v: RawVec = RawVec::new(); - // First `reserve` allocates like `reserve_exact` + // First, `reserve` allocates like `reserve_exact`. v.reserve(0, 9); assert_eq!(9, v.capacity()); } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0c406a9202..f234ac5ebe 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,6 +327,37 @@ impl Rc { })) } + /// Constructs a new `Rc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Rc> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::(), + |mem| mem as *mut RcBox>, + )) + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -377,6 +408,118 @@ impl Rc { } } +impl Rc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + unsafe { + Rc::from_ptr(Rc::allocate_for_slice(len)) + } + } +} + +impl Rc> { + /// Converts to `Rc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc { + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl Rc<[mem::MaybeUninit]> { + /// Converts to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl Rc { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -424,7 +567,7 @@ impl Rc { /// let x = Rc::from_raw(x_ptr); /// assert_eq!(&*x, "hello"); /// - /// // Further calls to `Rc::from_raw(x_ptr)` would be memory unsafe. + /// // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe. /// } /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! @@ -560,13 +703,46 @@ impl Rc { pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { unsafe { - Some(&mut this.ptr.as_mut().value) + Some(Rc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Rc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().value + } + #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Rc`s point to the same value (not @@ -704,11 +880,11 @@ impl Rc { impl Rc { /// Allocates an `RcBox` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox ) -> *mut RcBox { @@ -737,7 +913,7 @@ impl Rc { /// Allocates an `RcBox` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox, ) @@ -768,7 +944,7 @@ impl Rc { impl Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, ) @@ -1656,8 +1832,9 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same value (not just values - /// that compare as equal). + /// Returns `true` if the two `Weak`s point to the same value (not just + /// values that compare as equal), or if both don't point to any value + /// (because they were created with `Weak::new()`). /// /// # Notes /// @@ -1667,7 +1844,6 @@ impl Weak { /// # Examples /// /// ``` - /// #![feature(weak_ptr_eq)] /// use std::rc::Rc; /// /// let first_rc = Rc::new(5); @@ -1685,7 +1861,6 @@ impl Weak { /// Comparing `Weak::new`. /// /// ``` - /// #![feature(weak_ptr_eq)] /// use std::rc::{Rc, Weak}; /// /// let first = Weak::new(); @@ -1697,7 +1872,7 @@ impl Weak { /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] - #[unstable(feature = "weak_ptr_eq", issue = "55981")] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { self.ptr.as_ptr() == other.ptr.as_ptr() } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index eca726cd41..1166e7b5df 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -56,7 +56,7 @@ use core::ptr; use core::str::{pattern::Pattern, lossy}; use crate::borrow::{Cow, ToOwned}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use crate::vec::Vec; @@ -369,7 +369,7 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_string_new")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))] pub const fn new() -> String { String { vec: Vec::new() } } @@ -937,9 +937,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result { + /// fn process_data(data: &str) -> Result { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -953,7 +953,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve(additional) } @@ -975,9 +975,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result { + /// fn process_data(data: &str) -> Result { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -991,7 +991,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve_exact(additional) } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 7d3b2656a7..45f98162e4 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -107,10 +107,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // a, b, and foo are all Arcs that point to the same memory location /// ``` /// -/// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly -/// the meaning of the code. In the example above, this syntax makes it easier to see that -/// this code is creating a new reference rather than copying the whole content of foo. -/// /// ## `Deref` behavior /// /// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), @@ -311,6 +307,37 @@ impl Arc { Self::from_inner(Box::into_raw_non_null(x)) } + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Arc> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |mem| mem as *mut ArcInner>, + )) + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -361,6 +388,118 @@ impl Arc { } } +impl Arc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + unsafe { + Arc::from_ptr(Arc::allocate_for_slice(len)) + } + } +} + +impl Arc> { + /// Converts to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc { + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl Arc<[mem::MaybeUninit]> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl Arc { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -408,7 +547,7 @@ impl Arc { /// let x = Arc::from_raw(x_ptr); /// assert_eq!(&*x, "hello"); /// - /// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe. + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. /// } /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! @@ -593,11 +732,11 @@ impl Arc { impl Arc { /// Allocates an `ArcInner` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner ) -> *mut ArcInner { @@ -625,7 +764,7 @@ impl Arc { /// Allocates an `ArcInner` with sufficient space for an unsized value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner, ) @@ -656,7 +795,7 @@ impl Arc { impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, ) @@ -945,13 +1084,46 @@ impl Arc { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - Some(&mut this.ptr.as_mut().data) + Some(Arc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Arc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().data + } + /// Determine whether this is the unique reference (including weak refs) to /// the underlying data. /// @@ -1378,19 +1550,18 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same value (not just values - /// that compare as equal). + /// Returns `true` if the two `Weak`s point to the same value (not just + /// values that compare as equal), or if both don't point to any value + /// (because they were created with `Weak::new()`). /// /// # Notes /// /// Since this compares pointers it means that `Weak::new()` will equal each /// other, even though they don't point to any value. /// - /// /// # Examples /// /// ``` - /// #![feature(weak_ptr_eq)] /// use std::sync::Arc; /// /// let first_rc = Arc::new(5); @@ -1408,7 +1579,6 @@ impl Weak { /// Comparing `Weak::new`. /// /// ``` - /// #![feature(weak_ptr_eq)] /// use std::sync::{Arc, Weak}; /// /// let first = Weak::new(); @@ -1420,7 +1590,7 @@ impl Weak { /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] - #[unstable(feature = "weak_ptr_eq", issue = "55981")] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { self.ptr.as_ptr() == other.ptr.as_ptr() } diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 62ccb53fce..35db18c39c 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -90,6 +90,17 @@ fn test_intersection() { &[1, 3, 11, 77, 103]); } +#[test] +fn test_intersection_size_hint() { + let x: BTreeSet = [3, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.intersection(&y); + assert_eq!(iter.size_hint(), (0, Some(2))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); +} + #[test] fn test_difference() { fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 765210e5aa..55edf56345 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -566,11 +566,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -590,7 +590,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -629,10 +629,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -651,7 +651,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 6e8ffe1852..29a22aa031 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::mem::size_of; use std::{usize, isize}; use std::vec::{Drain, IntoIter}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; struct DropCounter<'a> { count: &'a mut u32, @@ -1121,11 +1121,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1145,7 +1145,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1168,7 +1168,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1209,10 +1209,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1231,7 +1231,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1252,7 +1252,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 1bbcca97b3..d49b553fc0 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; use std::collections::{VecDeque, vec_deque::Drain}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -1168,7 +1168,7 @@ fn test_try_reserve() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1188,7 +1188,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1211,7 +1211,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1256,7 +1256,7 @@ fn test_try_reserve_exact() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1275,7 +1275,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1296,7 +1296,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index dac04e4e62..405969a550 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -70,7 +70,7 @@ use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; use crate::borrow::{ToOwned, Cow}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::raw_vec::RawVec; @@ -291,6 +291,7 @@ use crate::raw_vec::RawVec; /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve /// [owned slice]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")] pub struct Vec { buf: RawVec, len: usize, @@ -313,10 +314,10 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_new")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))] pub const fn new() -> Vec { Vec { - buf: RawVec::new(), + buf: RawVec::NEW, len: 0, } } @@ -498,9 +499,9 @@ impl Vec { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -516,7 +517,7 @@ impl Vec { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) } @@ -538,9 +539,9 @@ impl Vec { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -556,7 +557,7 @@ impl Vec { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) } @@ -684,21 +685,25 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { - let current_len = self.len; - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len); - // Set the final length at the end, keeping in mind that - // dropping an element might panic. Works around a missed - // optimization, as seen in the following issue: - // https://github.com/rust-lang/rust/issues/51802 - let mut local_len = SetLenOnDrop::new(&mut self.len); + if mem::needs_drop::() { + let current_len = self.len; + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); - // drop any extra elements - for _ in len..current_len { - local_len.decrement_len(1); - ptr = ptr.offset(-1); - ptr::drop_in_place(ptr); + // drop any extra elements + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); + } } + } else if len <= self.len { + self.len = len; } } diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 078091a9b5..0afbf4f134 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -153,13 +153,13 @@ impl dyn Any { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is(&self) -> bool { - // Get TypeId of the type this function is instantiated with + // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); - // Get TypeId of the type in the trait object + // Get `TypeId` of the type in the trait object. let concrete = self.type_id(); - // Compare both TypeIds on equality + // Compare both `TypeId`s on equality. t == concrete } @@ -470,10 +470,5 @@ impl TypeId { #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name() -> &'static str { - #[cfg(bootstrap)] - unsafe { - intrinsics::type_name::() - } - #[cfg(not(bootstrap))] intrinsics::type_name::() } diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index e6a6fdde54..4087333e2c 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -14,6 +14,7 @@ use crate::fmt; use crate::ops::Range; use crate::iter::FusedIterator; +use crate::str::from_utf8_unchecked; /// An iterator over the escaped version of a byte. /// @@ -22,6 +23,7 @@ use crate::iter::FusedIterator; /// /// [`escape_default`]: fn.escape_default.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] pub struct EscapeDefault { range: Range, data: [u8; 4], @@ -130,6 +132,13 @@ impl ExactSizeIterator for EscapeDefault {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "ascii_escape_display", since = "1.39.0")] +impl fmt::Display for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs new file mode 100644 index 0000000000..f751ccb428 --- /dev/null +++ b/src/libcore/bool.rs @@ -0,0 +1,45 @@ +//! impl bool {} + +#[cfg(not(bootstrap))] +#[lang = "bool"] +impl bool { + /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_option)] + /// + /// assert_eq!(false.then(0), None); + /// assert_eq!(true.then(0), Some(0)); + /// ``` + #[unstable(feature = "bool_to_option", issue = "64260")] + #[inline] + pub fn then(self, t: T) -> Option { + if self { + Some(t) + } else { + None + } + } + + /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_option)] + /// + /// assert_eq!(false.then_with(|| 0), None); + /// assert_eq!(true.then_with(|| 0), Some(0)); + /// ``` + #[unstable(feature = "bool_to_option", issue = "64260")] + #[inline] + pub fn then_with T>(self, f: F) -> Option { + if self { + Some(f()) + } else { + None + } + } +} diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index aa834db2b9..a69eb0f6d4 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -547,39 +547,6 @@ impl char { } } - /// Returns `true` if this `char` satisfies the `XID_Start` Unicode property, and false - /// otherwise. - /// - /// `XID_Start` is a Unicode Derived Property specified in - /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), - /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] - pub fn is_xid_start(self) -> bool { - derived_property::XID_Start(self) - } - - /// Returns `true` if this `char` satisfies the `XID_Continue` Unicode property, and false - /// otherwise. - /// - /// `XID_Continue` is a Unicode Derived Property specified in - /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), - /// mostly similar to `ID_Continue` but modified for closure under NFKx. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] - #[inline] - pub fn is_xid_continue(self) -> bool { - derived_property::XID_Continue(self) - } - /// Returns `true` if this `char` is lowercase. /// /// 'Lowercase' is defined according to the terms of the Unicode Derived Core diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0c99356390..6bdae1b557 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -134,9 +134,8 @@ pub trait Clone : Sized { } /// Derive macro generating an impl of the trait `Clone`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 38a52d97da..fc7329f57d 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -9,14 +9,22 @@ //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and //! partial orderings between values, respectively. Implementing them overloads //! the `<`, `<=`, `>`, and `>=` operators. -//! * [`Ordering`][cmp::Ordering] is an enum returned by the -//! main functions of [`Ord`] and [`PartialOrd`], and describes an ordering. -//! * [`Reverse`][cmp::Reverse] is a struct that allows you to easily reverse -//! an ordering. -//! * [`max`][cmp::max] and [`min`][cmp::min] are functions that build off of -//! [`Ord`] and allow you to find the maximum or minimum of two values. +//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and +//! [`PartialOrd`], and describes an ordering. +//! * [`Reverse`] is a struct that allows you to easily reverse an ordering. +//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you +//! to find the maximum or minimum of two values. //! //! For more details, see the respective documentation of each item in the list. +//! +//! [`Eq`]: trait.Eq.html +//! [`PartialEq`]: trait.PartialEq.html +//! [`Ord`]: trait.Ord.html +//! [`PartialOrd`]: trait.PartialOrd.html +//! [`Ordering`]: enum.Ordering.html +//! [`Reverse`]: struct.Reverse.html +//! [`max`]: fn.max.html +//! [`min`]: fn.min.html #![stable(feature = "rust1", since = "1.0.0")] @@ -201,9 +209,8 @@ pub trait PartialEq { } /// Derive macro generating an impl of the trait `PartialEq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -265,9 +272,8 @@ pub trait Eq: PartialEq { } /// Derive macro generating an impl of the trait `Eq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -564,7 +570,7 @@ pub trait Ord: Eq + PartialOrd { #[inline] fn max(self, other: Self) -> Self where Self: Sized { - if other >= self { other } else { self } + max_by(self, other, Ord::cmp) } /// Compares and returns the minimum of two values. @@ -581,7 +587,7 @@ pub trait Ord: Eq + PartialOrd { #[inline] fn min(self, other: Self) -> Self where Self: Sized { - if self <= other { self } else { other } + min_by(self, other, Ord::cmp) } /// Restrict a value to a certain interval. @@ -617,9 +623,8 @@ pub trait Ord: Eq + PartialOrd { } /// Derive macro generating an impl of the trait `Ord`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -867,9 +872,8 @@ pub trait PartialOrd: PartialEq { } /// Derive macro generating an impl of the trait `PartialOrd`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } @@ -894,6 +898,49 @@ pub fn min(v1: T, v2: T) -> T { v1.min(v2) } +/// Returns the minimum of two values with respect to the specified comparison function. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_by)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1); +/// assert_eq!(cmp::min_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2); +/// ``` +#[inline] +#[unstable(feature = "cmp_min_max_by", issue = "64460")] +pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { + match compare(&v1, &v2) { + Ordering::Less | Ordering::Equal => v1, + Ordering::Greater => v2, + } +} + +/// Returns the element that gives the minimum value from the specified function. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_by)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1); +/// assert_eq!(cmp::min_by_key(-2, 2, |x: &i32| x.abs()), -2); +/// ``` +#[inline] +#[unstable(feature = "cmp_min_max_by", issue = "64460")] +pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + /// Compares and returns the maximum of two values. /// /// Returns the second argument if the comparison determines them to be equal. @@ -914,6 +961,49 @@ pub fn max(v1: T, v2: T) -> T { v1.max(v2) } +/// Returns the maximum of two values with respect to the specified comparison function. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_by)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2); +/// assert_eq!(cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 2); +/// ``` +#[inline] +#[unstable(feature = "cmp_min_max_by", issue = "64460")] +pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { + match compare(&v1, &v2) { + Ordering::Less | Ordering::Equal => v2, + Ordering::Greater => v1, + } +} + +/// Returns the element that gives the maximum value from the specified function. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_by)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2); +/// assert_eq!(cmp::max_by_key(-2, 2, |x: &i32| x.abs()), 2); +/// ``` +#[inline] +#[unstable(feature = "cmp_min_max_by", issue = "64460")] +pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types mod impls { use crate::cmp::Ordering::{self, Less, Greater, Equal}; @@ -1016,8 +1106,10 @@ mod impls { impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { - if *self == *other { Equal } - else if *self < *other { Less } + // The order here is important to generate more optimal assembly. + // See for more info. + if *self < *other { Less } + else if *self == *other { Equal } else { Greater } } } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 641621f492..06f2b7bab1 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -42,11 +42,11 @@ use crate::fmt; -/// An identity function. +/// The identity function. /// /// Two things are important to note about this function: /// -/// - It is not always equivalent to a closure like `|x| x` since the +/// - It is not always equivalent to a closure like `|x| x`, since the /// closure may coerce `x` into a different type. /// /// - It moves the input `x` passed to the function. @@ -56,31 +56,32 @@ use crate::fmt; /// /// # Examples /// -/// Using `identity` to do nothing among other interesting functions: +/// Using `identity` to do nothing in a sequence of other, interesting, +/// functions: /// /// ```rust /// use std::convert::identity; /// /// fn manipulation(x: u32) -> u32 { -/// // Let's assume that this function does something interesting. +/// // Let's pretend that adding one is an interesting function. /// x + 1 /// } /// /// let _arr = &[identity, manipulation]; /// ``` /// -/// Using `identity` to get a function that changes nothing in a conditional: +/// Using `identity` as a "do nothing" base case in a conditional: /// /// ```rust /// use std::convert::identity; /// /// # let condition = true; -/// +/// # /// # fn manipulation(x: u32) -> u32 { x + 1 } -/// +/// # /// let do_stuff = if condition { manipulation } else { identity }; /// -/// // do more interesting stuff.. +/// // Do more interesting stuff... /// /// let _results = do_stuff(42); /// ``` @@ -104,22 +105,17 @@ pub const fn identity(x: T) -> T { x } /// If you need to do a costly conversion it is better to implement [`From`] with type /// `&T` or write a custom function. /// -/// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects: +/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects: /// -/// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either +/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either /// a reference or a value. -/// - `Borrow` also requires that `Hash`, `Eq` and `Ord` for borrowed value are +/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are /// equivalent to those of the owned value. For this reason, if you want to -/// borrow only a single field of a struct you can implement `AsRef`, but not `Borrow`. -/// -/// [`Borrow`]: ../../std/borrow/trait.Borrow.html +/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`]. /// /// **Note: This trait must not fail**. If the conversion can fail, use a /// dedicated method which returns an [`Option`] or a [`Result`]. /// -/// [`Option`]: ../../std/option/enum.Option.html -/// [`Result`]: ../../std/result/enum.Result.html -/// /// # Generic Implementations /// /// - `AsRef` auto-dereferences if the inner type is a reference or a mutable @@ -132,9 +128,16 @@ pub const fn identity(x: T) -> T { x } /// converted to the specified type `T`. /// /// For example: By creating a generic function that takes an `AsRef` we express that we -/// want to accept all references that can be converted to `&str` as an argument. -/// Since both [`String`] and `&str` implement `AsRef` we can accept both as input argument. +/// want to accept all references that can be converted to [`&str`] as an argument. +/// Since both [`String`] and [`&str`] implement `AsRef` we can accept both as input argument. /// +/// [`Option`]: ../../std/option/enum.Option.html +/// [`Result`]: ../../std/result/enum.Result.html +/// [`Borrow`]: ../../std/borrow/trait.Borrow.html +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`Ord`]: ../../std/cmp/trait.Ord.html +/// [`&str`]: ../../std/primitive.str.html /// [`String`]: ../../std/string/struct.String.html /// /// ``` diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 8d95e9de15..806d478310 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -116,9 +116,8 @@ pub trait Default: Sized { } /// Derive macro generating an impl of the trait `Default`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index cb4e32622f..15ce2277fa 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -98,7 +98,7 @@ pub struct DebugStruct<'a, 'b: 'a> { has_fields: bool, } -pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, +pub(super) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugStruct<'a, 'b> { let result = fmt.write_str(name); @@ -251,7 +251,10 @@ pub struct DebugTuple<'a, 'b: 'a> { empty_name: bool, } -pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> { +pub(super) fn debug_tuple_new<'a, 'b>( + fmt: &'a mut fmt::Formatter<'b>, + name: &str, +) -> DebugTuple<'a, 'b> { let result = fmt.write_str(name); DebugTuple { fmt, @@ -418,7 +421,7 @@ pub struct DebugSet<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { +pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { let result = fmt.write_str("{"); DebugSet { inner: DebugInner { @@ -555,7 +558,7 @@ pub struct DebugList<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { +pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { let result = fmt.write_str("["); DebugList { inner: DebugInner { @@ -697,7 +700,7 @@ pub struct DebugMap<'a, 'b: 'a> { state: PadAdapterState, } -pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { +pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { let result = fmt.write_str("{"); DebugMap { fmt, diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0ea01d4b84..65e2f8b9be 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -518,7 +518,8 @@ impl Display for Arguments<'_> { label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] -#[lang = "debug_trait"] +#[cfg_attr(bootstrap, lang = "debug_trait")] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_trait")] pub trait Debug { /// Formats the value using the given formatter. /// @@ -546,16 +547,14 @@ pub trait Debug { } // Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Debug; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index c4cbf40a93..aaaa6f9c57 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -199,16 +199,14 @@ pub trait Hash { } // Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Hash; @@ -553,8 +551,6 @@ impl PartialEq for BuildHasherDefault { #[stable(since = "1.29.0", feature = "build_hasher_eq")] impl Eq for BuildHasherDefault {} -////////////////////////////////////////////////////////////////////////////// - mod impls { use crate::mem; use crate::slice; diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 3b2b28217f..ee4be6c915 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -49,28 +49,16 @@ pub unsafe fn unreachable_unchecked() -> ! { intrinsics::unreachable() } -/// Signals the processor that it is entering a busy-wait spin-loop. +/// Emits a machine instruction hinting to the processor that it is running in busy-wait +/// spin-loop ("spin lock"). /// -/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving -/// power or switching hyper-threads. -/// -/// This function is different than [`std::thread::yield_now`] which directly yields to the -/// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a -/// busy-wait spin-loop without yielding control to the system's scheduler. -/// -/// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a -/// contended lock is held by another thread executed on a different CPU and where the waiting -/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's -/// scheduler, no overhead for switching threads occurs. However, if the thread holding the -/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice -/// before switching to the thread that holds the lock. If the contending lock is held by a thread -/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to -/// use [`std::thread::yield_now`]. +/// For a discussion of different locking strategies and their trade-offs, see +/// [`core::sync::atomic::spin_loop_hint`]. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// -/// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html +/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { @@ -104,11 +92,19 @@ pub fn spin_loop() { } } -/// A function that is opaque to the optimizer, to allow benchmarks to -/// pretend to use outputs to assist in avoiding dead-code -/// elimination. +/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what +/// `black_box` could do. +/// +/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html +/// +/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can +/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined +/// behavior in the calling code. This property makes `black_box` useful for writing code in which +/// certain optimizations are not desired, such as benchmarks. /// -/// This function is a no-op, and does not even read from `dummy`. +/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The +/// extent to which it can block optimisations may vary depending upon the platform and code-gen +/// backend used. Programs cannot rely on `black_box` for *correctness* in any way. #[inline] #[unstable(feature = "test", issue = "50297")] #[allow(unreachable_code)] // this makes #[cfg] a bit easier below. diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ceaa870d2b..905375eb60 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -845,21 +845,26 @@ extern "rust-intrinsic" { /// /// ``` /// let store = [0, 1, 2, 3]; - /// let mut v_orig = store.iter().collect::>(); + /// let v_orig = store.iter().collect::>(); + /// + /// // clone the vector as we will reuse them later + /// let v_clone = v_orig.clone(); /// /// // Using transmute: this is Undefined Behavior, and a bad idea. /// // However, it is no-copy. /// let v_transmuted = unsafe { - /// std::mem::transmute::, Vec>>( - /// v_orig.clone()) + /// std::mem::transmute::, Vec>>(v_clone) /// }; /// + /// let v_clone = v_orig.clone(); + /// /// // This is the suggested, safe way. /// // It does copy the entire vector, though, into a new array. - /// let v_collected = v_orig.clone() - /// .into_iter() - /// .map(|r| Some(r)) - /// .collect::>>(); + /// let v_collected = v_clone.into_iter() + /// .map(Some) + /// .collect::>>(); + /// + /// let v_clone = v_orig.clone(); /// /// // The no-copy, unsafe way, still using transmute, but not UB. /// // This is equivalent to the original, but safer, and reuses the @@ -869,11 +874,12 @@ extern "rust-intrinsic" { /// // the original inner type (`&i32`) to the converted inner type /// // (`Option<&i32>`), so read the nomicon pages linked above. /// let v_from_raw = unsafe { - /// Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>, - /// v_orig.len(), - /// v_orig.capacity()) + /// // Ensure the original vector is not dropped. + /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); + /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, + /// v_clone.len(), + /// v_clone.capacity()) /// }; - /// std::mem::forget(v_orig); /// ``` /// /// Implementing `split_at_mut`: @@ -1293,18 +1299,40 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(bootstrap)] pub fn overflowing_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(bootstrap)] pub fn overflowing_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(bootstrap)] pub fn overflowing_mul(a: T, b: T) -> T; + /// Returns (a + b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_add` method. For example, + /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(not(bootstrap))] + pub fn wrapping_add(a: T, b: T) -> T; + /// Returns (a - b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_sub` method. For example, + /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(not(bootstrap))] + pub fn wrapping_sub(a: T, b: T) -> T; + /// Returns (a * b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_mul` method. For example, + /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(not(bootstrap))] + pub fn wrapping_mul(a: T, b: T) -> T; + /// Computes `a + b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index 76239ebc0a..c9612596b1 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -173,17 +173,23 @@ impl Iterator for Chain where #[inline] fn size_hint(&self) -> (usize, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); + match self.state { + ChainState::Both => { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); - let lower = a_lower.saturating_add(b_lower); + let lower = a_lower.saturating_add(b_lower); - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None - }; + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None + }; - (lower, upper) + (lower, upper) + } + ChainState::Front => self.a.size_hint(), + ChainState::Back => self.b.size_hint(), + } } } @@ -207,6 +213,29 @@ impl DoubleEndedIterator for Chain where } } + #[inline] + fn nth_back(&mut self, mut n: usize) -> Option { + match self.state { + ChainState::Both | ChainState::Back => { + for x in self.b.by_ref().rev() { + if n == 0 { + return Some(x) + } + n -= 1; + } + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + ChainState::Front => {} + } + if let ChainState::Front = self.state { + self.a.nth_back(n) + } else { + None + } + } + fn try_rfold(&mut self, init: Acc, mut f: F) -> R where Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try { diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index d8d41a2a31..a45173f614 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -72,8 +72,7 @@ impl Iterator for FlatMap impl DoubleEndedIterator for FlatMap where F: FnMut(I::Item) -> U, - U: IntoIterator, - U::IntoIter: DoubleEndedIterator, + U: IntoIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } @@ -107,10 +106,7 @@ impl FusedIterator for FlatMap /// [`Iterator`]: trait.Iterator.html #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] -pub struct Flatten -where - I::Item: IntoIterator, -{ +pub struct Flatten> { inner: FlattenCompat::IntoIter>, } @@ -229,7 +225,7 @@ where if let elt@Some(_) = inner.next() { return elt } } match self.iter.next() { - None => return self.backiter.as_mut().and_then(|it| it.next()), + None => return self.backiter.as_mut()?.next(), Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -237,8 +233,8 @@ where #[inline] fn size_hint(&self) -> (usize, Option) { - let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), @@ -250,20 +246,25 @@ where fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try>( + frontiter: &'a mut Option, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, x| { + let mut mid = x.into_iter(); + let r = mid.try_fold(acc, &mut *fold); + *frontiter = Some(mid); + r + } + } + if let Some(ref mut front) = self.frontiter { init = front.try_fold(init, &mut fold)?; } self.frontiter = None; - { - let frontiter = &mut self.frontiter; - init = self.iter.try_fold(init, |acc, x| { - let mut mid = x.into_iter(); - let r = mid.try_fold(acc, &mut fold); - *frontiter = Some(mid); - r - })?; - } + init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?; self.frontiter = None; if let Some(ref mut back) = self.backiter { @@ -275,13 +276,20 @@ where } #[inline] - fn fold(self, init: Acc, mut fold: Fold) -> Acc + fn fold(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.fold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .fold(init, |acc, iter| iter.fold(acc, &mut fold)) + .fold(init, flatten(fold)) } } @@ -297,7 +305,7 @@ where if let elt@Some(_) = inner.next_back() { return elt } } match self.iter.next_back() { - None => return self.frontiter.as_mut().and_then(|it| it.next_back()), + None => return self.frontiter.as_mut()?.next_back(), next => self.backiter = next.map(IntoIterator::into_iter), } } @@ -307,22 +315,29 @@ where fn try_rfold(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - if let Some(ref mut back) = self.backiter { - init = back.try_rfold(init, &mut fold)?; - } - self.backiter = None; - + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try>( + backiter: &'a mut Option, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a where + T::IntoIter: DoubleEndedIterator, { - let backiter = &mut self.backiter; - init = self.iter.try_rfold(init, |acc, x| { + move |acc, x| { let mut mid = x.into_iter(); - let r = mid.try_rfold(acc, &mut fold); + let r = mid.try_rfold(acc, &mut *fold); *backiter = Some(mid); r - })?; + } + } + + if let Some(ref mut back) = self.backiter { + init = back.try_rfold(init, &mut fold)?; } self.backiter = None; + init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?; + self.backiter = None; + if let Some(ref mut front) = self.frontiter { init = front.try_rfold(init, &mut fold)?; } @@ -332,12 +347,19 @@ where } #[inline] - fn rfold(self, init: Acc, mut fold: Fold) -> Acc + fn rfold(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.rfold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .rfold(init, |acc, iter| iter.rfold(acc, &mut fold)) + .rfold(init, flatten(fold)) } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index b270290295..3b8edc2ad6 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1,11 +1,11 @@ use crate::cmp; use crate::fmt; -use crate::ops::Try; +use crate::ops::{Add, AddAssign, Try}; use crate::usize; use crate::intrinsics; use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen}; -use super::LoopState; +use super::{LoopState, from_fn}; mod chain; mod flatten; @@ -66,13 +66,6 @@ impl Iterator for Rev where I: DoubleEndedIterator { { self.iter.rfind(predicate) } - - #[inline] - fn rposition

(&mut self, predicate: P) -> Option where - P: FnMut(Self::Item) -> bool - { - self.iter.position(predicate) - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -143,6 +136,18 @@ impl Copied { } } +fn copy_fold( + mut f: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, &T) -> Acc { + move |acc, &elt| f(acc, elt) +} + +fn copy_try_fold( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, &elt| f(acc, elt) +} + #[stable(feature = "iter_copied", since = "1.36.0")] impl<'a, I, T: 'a> Iterator for Copied where I: Iterator, T: Copy @@ -157,16 +162,16 @@ impl<'a, I, T: 'a> Iterator for Copied self.it.size_hint() } - fn try_fold(&mut self, init: B, mut f: F) -> R where + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { - self.it.try_fold(init, move |acc, &elt| f(acc, elt)) + self.it.try_fold(init, copy_try_fold(f)) } - fn fold(self, init: Acc, mut f: F) -> Acc + fn fold(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, &elt| f(acc, elt)) + self.it.fold(init, copy_fold(f)) } } @@ -178,16 +183,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Copied self.it.next_back().copied() } - fn try_rfold(&mut self, init: B, mut f: F) -> R where + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { - self.it.try_rfold(init, move |acc, &elt| f(acc, elt)) + self.it.try_rfold(init, copy_try_fold(f)) } - fn rfold(self, init: Acc, mut f: F) -> Acc + fn rfold(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, &elt| f(acc, elt)) + self.it.rfold(init, copy_fold(f)) } } @@ -248,6 +253,12 @@ impl Cloned { } } +fn clone_try_fold( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, elt| f(acc, elt.clone()) +} + #[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> Iterator for Cloned where I: Iterator, T: Clone @@ -262,16 +273,16 @@ impl<'a, I, T: 'a> Iterator for Cloned self.it.size_hint() } - fn try_fold(&mut self, init: B, mut f: F) -> R where + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { - self.it.try_fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_fold(init, clone_try_fold(f)) } - fn fold(self, init: Acc, mut f: F) -> Acc + fn fold(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).fold(init, f) } } @@ -283,16 +294,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned self.it.next_back().cloned() } - fn try_rfold(&mut self, init: B, mut f: F) -> R where + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { - self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_rfold(init, clone_try_fold(f)) } - fn rfold(self, init: Acc, mut f: F) -> Acc + fn rfold(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).rfold(init, f) } } @@ -387,6 +398,36 @@ impl Iterator for Cycle where I: Clone + Iterator { _ => (usize::MAX, None) } } + + #[inline] + fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + // fully iterate the current iterator. this is necessary because + // `self.iter` may be empty even when `self.orig` isn't + acc = self.iter.try_fold(acc, &mut f)?; + self.iter = self.orig.clone(); + + // complete a full cycle, keeping track of whether the cycled + // iterator is empty or not. we need to return early in case + // of an empty iterator to prevent an infinite loop + let mut is_empty = true; + acc = self.iter.try_fold(acc, |acc, x| { + is_empty = false; + f(acc, x) + })?; + + if is_empty { + return Try::from_ok(acc); + } + + loop { + self.iter = self.orig.clone(); + acc = self.iter.try_fold(acc, &mut f)?; + } + } } #[stable(feature = "fused", since = "1.26.0")] @@ -430,14 +471,24 @@ impl Iterator for StepBy where I: Iterator { #[inline] fn size_hint(&self) -> (usize, Option) { - let inner_hint = self.iter.size_hint(); + #[inline] + fn first_size(step: usize) -> impl Fn(usize) -> usize { + move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) } + } + + #[inline] + fn other_size(step: usize) -> impl Fn(usize) -> usize { + move |n| n / (step + 1) + } + + let (low, high) = self.iter.size_hint(); if self.first_take { - let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) }; - (f(inner_hint.0), inner_hint.1.map(f)) + let f = first_size(self.step); + (f(low), high.map(f)) } else { - let f = |n| n / (self.step+1); - (f(inner_hint.0), inner_hint.1.map(f)) + let f = other_size(self.step); + (f(low), high.map(f)) } } @@ -483,6 +534,26 @@ impl Iterator for StepBy where I: Iterator { self.iter.nth(nth - 1); } } + + fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { + move || iter.nth(step) + } + + if self.first_take { + self.first_take = false; + match self.iter.next() { + None => return Try::from_ok(acc), + Some(x) => acc = f(acc, x)?, + } + } + from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f) + } } impl StepBy where I: ExactSizeIterator { @@ -516,6 +587,28 @@ impl DoubleEndedIterator for StepBy where I: DoubleEndedIterator + ExactSi .saturating_add(self.next_back_index()); self.iter.nth_back(n) } + + fn try_rfold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth_back( + iter: &mut I, + step: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth_back(step) + } + + match self.next_back() { + None => Try::from_ok(init), + Some(x) => { + let acc = f(init, x)?; + from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f) + } + } + } } // StepBy can only make the iterator shorter, so the len will still fit. @@ -594,6 +687,20 @@ impl fmt::Debug for Map { } } +fn map_fold( + mut f: impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, elt| g(acc, f(elt)) +} + +fn map_try_fold<'a, T, B, Acc, R>( + f: &'a mut impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, elt| g(acc, f(elt)) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Map where F: FnMut(I::Item) -> B { type Item = B; @@ -608,18 +715,16 @@ impl Iterator for Map where F: FnMut(I::Item) -> B { self.iter.size_hint() } - fn try_fold(&mut self, init: Acc, mut g: G) -> R where + fn try_fold(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } - fn fold(self, init: Acc, mut g: G) -> Acc + fn fold(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.fold(init, map_fold(self.f, g)) } } @@ -632,18 +737,16 @@ impl DoubleEndedIterator for Map where self.iter.next_back().map(&mut self.f) } - fn try_rfold(&mut self, init: Acc, mut g: G) -> R where + fn try_rfold(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } - fn rfold(self, init: Acc, mut g: G) -> Acc + fn rfold(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.rfold(init, map_fold(self.f, g)) } } @@ -710,13 +813,27 @@ impl fmt::Debug for Filter { } } +fn filter_fold( + mut predicate: impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} + +fn filter_try_fold<'a, T, Acc, R: Try>( + predicate: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Filter where P: FnMut(&I::Item) -> bool { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - self.try_for_each(Err).err() + self.iter.find(&mut self.predicate) } #[inline] @@ -738,32 +855,26 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool // leaving more budget for LLVM optimizations. #[inline] fn count(self) -> usize { - let mut predicate = self.predicate; - self.iter.map(|x| predicate(&x) as usize).sum() + #[inline] + fn to_usize(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize { + move |x| predicate(&x) as usize + } + + self.iter.map(to_usize(self.predicate)).sum() } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let predicate = &mut self.predicate; - self.iter.try_fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn fold(self, init: Acc, mut fold: Fold) -> Acc + fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.fold(init, filter_fold(self.predicate, fold)) } } @@ -773,31 +884,21 @@ impl DoubleEndedIterator for Filter { #[inline] fn next_back(&mut self) -> Option { - self.try_rfold((), |_, x| Err(x)).err() + self.iter.rfind(&mut self.predicate) } #[inline] - fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let predicate = &mut self.predicate; - self.iter.try_rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn rfold(self, init: Acc, mut fold: Fold) -> Acc + fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.rfold(init, filter_fold(self.predicate, fold)) } } @@ -834,6 +935,26 @@ impl fmt::Debug for FilterMap { } } +fn filter_map_fold( + mut f: impl FnMut(T) -> Option, + mut fold: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + } +} + +fn filter_map_try_fold<'a, T, B, Acc, R: Try>( + f: &'a mut impl FnMut(T) -> Option, + mut fold: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => R::from_ok(acc), + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for FilterMap where F: FnMut(I::Item) -> Option, @@ -842,7 +963,7 @@ impl Iterator for FilterMap #[inline] fn next(&mut self) -> Option { - self.try_for_each(Err).err() + self.iter.find_map(&mut self.f) } #[inline] @@ -852,25 +973,17 @@ impl Iterator for FilterMap } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn fold(self, init: Acc, mut fold: Fold) -> Acc + fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.fold(init, filter_map_fold(self.f, fold)) } } @@ -880,29 +993,31 @@ impl DoubleEndedIterator for FilterMap { #[inline] fn next_back(&mut self) -> Option { - self.try_rfold((), |_, x| Err(x)).err() + #[inline] + fn find( + f: &mut impl FnMut(T) -> Option + ) -> impl FnMut((), T) -> LoopState<(), B> + '_ { + move |(), x| match f(x) { + Some(x) => LoopState::Break(x), + None => LoopState::Continue(()), + } + } + + self.iter.try_rfold((), find(&mut self.f)).break_value() } #[inline] - fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn rfold(self, init: Acc, mut fold: Fold) -> Acc + fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.rfold(init, filter_map_fold(self.f, fold)) } } @@ -944,14 +1059,12 @@ impl Iterator for Enumerate where I: Iterator { /// /// Might panic if the index of the element overflows a `usize`. #[inline] - #[rustc_inherit_overflow_checks] fn next(&mut self) -> Option<(usize, ::Item)> { - self.iter.next().map(|a| { - let ret = (self.count, a); - // Possible undefined overflow. - self.count += 1; - ret - }) + let a = self.iter.next()?; + let i = self.count; + // Possible undefined overflow. + AddAssign::add_assign(&mut self.count, 1); + Some((i, a)) } #[inline] @@ -960,13 +1073,12 @@ impl Iterator for Enumerate where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> { - self.iter.nth(n).map(|a| { - let i = self.count + n; - self.count = i + 1; - (i, a) - }) + let a = self.iter.nth(n)?; + // Possible undefined overflow. + let i = Add::add(self.count, n); + self.count = Add::add(i, 1); + Some((i, a)) } #[inline] @@ -975,29 +1087,43 @@ impl Iterator for Enumerate where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let count = &mut self.count; - self.iter.try_fold(init, move |acc, item| { - let acc = fold(acc, (*count, item)); - *count += 1; - acc - }) + #[inline] + fn enumerate<'a, T, Acc, R>( + count: &'a mut usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { + let acc = fold(acc, (*count, item)); + // Possible undefined overflow. + AddAssign::add_assign(count, 1); + acc + } + } + + self.iter.try_fold(init, enumerate(&mut self.count, fold)) } #[inline] - #[rustc_inherit_overflow_checks] - fn fold(self, init: Acc, mut fold: Fold) -> Acc + fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut count = self.count; - self.iter.fold(init, move |acc, item| { - let acc = fold(acc, (count, item)); - count += 1; - acc - }) + #[inline] + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + let acc = fold(acc, (count, item)); + // Possible undefined overflow. + AddAssign::add_assign(&mut count, 1); + acc + } + } + + self.iter.fold(init, enumerate(self.count, fold)) } } @@ -1007,48 +1133,60 @@ impl DoubleEndedIterator for Enumerate where { #[inline] fn next_back(&mut self) -> Option<(usize, ::Item)> { - self.iter.next_back().map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.next_back()?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] fn nth_back(&mut self, n: usize) -> Option<(usize, ::Item)> { - self.iter.nth_back(n).map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.nth_back(n)?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] - fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.try_rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R, + ) -> impl FnMut(Acc, T) -> R { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.try_rfold(init, enumerate(count, fold)) } #[inline] - fn rfold(self, init: Acc, mut fold: Fold) -> Acc + fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.rfold(init, enumerate(count, fold)) } } @@ -1162,7 +1300,10 @@ impl Iterator for Peekable { }; let (lo, hi) = self.iter.size_hint(); let lo = lo.saturating_add(peek_len); - let hi = hi.and_then(|x| x.checked_add(peek_len)); + let hi = match hi { + Some(x) => x.checked_add(peek_len), + None => None, + }; (lo, hi) } @@ -1203,7 +1344,7 @@ impl DoubleEndedIterator for Peekable where I: DoubleEndedIterator { Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { match self.peeked.take() { - Some(None) => return Try::from_ok(init), + Some(None) => Try::from_ok(init), Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { Ok(acc) => f(acc, v), Err(e) => { @@ -1220,7 +1361,7 @@ impl DoubleEndedIterator for Peekable where I: DoubleEndedIterator { where Fold: FnMut(Acc, Self::Item) -> Acc, { match self.peeked { - Some(None) => return init, + Some(None) => init, Some(Some(v)) => { let acc = self.iter.rfold(init, &mut fold); fold(acc, v) @@ -1321,16 +1462,23 @@ impl Iterator for SkipWhile #[inline] fn next(&mut self) -> Option { + fn check<'a, T>( + flag: &'a mut bool, + pred: &'a mut impl FnMut(&T) -> bool, + ) -> impl FnMut(&T) -> bool + 'a { + move |x| { + if *flag || !pred(x) { + *flag = true; + true + } else { + false + } + } + } + let flag = &mut self.flag; let pred = &mut self.predicate; - self.iter.find(move |x| { - if *flag || !pred(x) { - *flag = true; - true - } else { - false - } - }) + self.iter.find(check(flag, pred)) } #[inline] @@ -1412,14 +1560,13 @@ impl Iterator for TakeWhile if self.flag { None } else { - self.iter.next().and_then(|x| { - if (self.predicate)(&x) { - Some(x) - } else { - self.flag = true; - None - } - }) + let x = self.iter.next()?; + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } } } @@ -1434,22 +1581,30 @@ impl Iterator for TakeWhile } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - if self.flag { - Try::from_ok(init) - } else { - let flag = &mut self.flag; - let p = &mut self.predicate; - self.iter.try_fold(init, move |acc, x|{ + fn check<'a, T, Acc, R: Try>( + flag: &'a mut bool, + p: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState + 'a { + move |acc, x| { if p(&x) { LoopState::from_try(fold(acc, x)) } else { *flag = true; LoopState::Break(Try::from_ok(acc)) } - }).into_try() + } + } + + if self.flag { + Try::from_ok(init) + } else { + let flag = &mut self.flag; + let p = &mut self.predicate; + self.iter.try_fold(init, check(flag, p, fold)).into_try() } } } @@ -1534,7 +1689,10 @@ impl Iterator for Skip where I: Iterator { let (lower, upper) = self.iter.size_hint(); let lower = lower.saturating_sub(self.n); - let upper = upper.map(|x| x.saturating_sub(self.n)); + let upper = match upper { + Some(x) => Some(x.saturating_sub(self.n)), + None => None, + }; (lower, upper) } @@ -1595,19 +1753,26 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } - fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let mut n = self.len(); - if n == 0 { - Try::from_ok(init) - } else { - self.iter.try_rfold(init, move |acc, x| { + fn check>( + mut n: usize, + mut fold: impl FnMut(Acc, T) -> R, + ) -> impl FnMut(Acc, T) -> LoopState { + move |acc, x| { n -= 1; let r = fold(acc, x); if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + let n = self.len(); + if n == 0 { + Try::from_ok(init) + } else { + self.iter.try_rfold(init, check(n, fold)).into_try() } } } @@ -1682,19 +1847,26 @@ impl Iterator for Take where I: Iterator{ } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - if self.n == 0 { - Try::from_ok(init) - } else { - let n = &mut self.n; - self.iter.try_fold(init, move |acc, x| { + fn check<'a, T, Acc, R: Try>( + n: &'a mut usize, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState + 'a { + move |acc, x| { *n -= 1; let r = fold(acc, x); if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + if self.n == 0 { + Try::from_ok(init) + } else { + let n = &mut self.n; + self.iter.try_fold(init, check(n, fold)).into_try() } } } @@ -1793,7 +1965,8 @@ impl Iterator for Scan where #[inline] fn next(&mut self) -> Option { - self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) + let a = self.iter.next()?; + (self.f)(&mut self.state, a) } #[inline] @@ -1803,17 +1976,25 @@ impl Iterator for Scan where } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { + fn scan<'a, T, St, B, Acc, R: Try>( + state: &'a mut St, + f: &'a mut impl FnMut(&mut St, T) -> Option, + mut fold: impl FnMut(Acc, B) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState + 'a { + move |acc, x| { + match f(state, x) { + None => LoopState::Break(Try::from_ok(acc)), + Some(x) => LoopState::from_try(fold(acc, x)), + } + } + } + let state = &mut self.state; let f = &mut self.f; - self.iter.try_fold(init, move |acc, x| { - match f(state, x) { - None => LoopState::Break(Try::from_ok(acc)), - Some(x) => LoopState::from_try(fold(acc, x)), - } - }).into_try() + self.iter.try_fold(init, scan(state, f, fold)).into_try() } } @@ -2104,6 +2285,20 @@ impl Inspect where F: FnMut(&I::Item) { } } +fn inspect_fold( + mut f: impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { f(&item); fold(acc, item) } +} + +fn inspect_try_fold<'a, T, Acc, R>( + f: &'a mut impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { f(&item); fold(acc, item) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Inspect where F: FnMut(&I::Item) { type Item = I::Item; @@ -2120,19 +2315,17 @@ impl Iterator for Inspect where F: FnMut(&I::Item) { } #[inline] - fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn fold(self, init: Acc, mut fold: Fold) -> Acc + fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.fold(init, inspect_fold(self.f, fold)) } } @@ -2147,19 +2340,17 @@ impl DoubleEndedIterator for Inspect } #[inline] - fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn rfold(self, init: Acc, mut fold: Fold) -> Acc + fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.rfold(init, inspect_fold(self.f, fold)) } } diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index 06f047d928..430ceacdd9 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -94,11 +94,9 @@ impl ZipImpl for Zip #[inline] default fn next(&mut self) -> Option<(A::Item, B::Item)> { - self.a.next().and_then(|x| { - self.b.next().and_then(|y| { - Some((x, y)) - }) - }) + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) } #[inline] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 70a3b70c18..183176005e 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -394,7 +394,8 @@ impl A> Iterator for OnceWith { #[inline] fn next(&mut self) -> Option { - self.gen.take().map(|f| f()) + let f = self.gen.take()?; + Some(f()) } #[inline] @@ -608,10 +609,9 @@ impl Iterator for Successors #[inline] fn next(&mut self) -> Option { - self.next.take().map(|item| { - self.next = (self.succ)(&item); - item - }) + let item = self.next.take()?; + self.next = (self.succ)(&item); + Some(item) } #[inline] diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 812463e77f..818f033032 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -85,28 +85,28 @@ macro_rules! float_sum_product { #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * b) + iter.fold(1.0, Mul::mul) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + *b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * *b) + iter.fold(1.0, Mul::mul) } } )*) diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 2c1aeb5690..006b243ca4 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -69,7 +69,7 @@ pub trait DoubleEndedIterator: Iterator { /// Returns the `n`th element from the end of the iterator. /// /// This is essentially the reversed version of [`nth`]. Although like most indexing - /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// operations, the count starts from zero, so `nth_back(0)` returns the first value from /// the end, `nth_back(1)` the second, and so on. /// /// Note that all elements between the end and the returned element will be @@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold(mut self, accum: B, mut f: F) -> B + fn rfold(mut self, accum: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_rfold(accum, move |acc, x| Ok::(f(acc, x))).unwrap() + #[inline] + fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(accum, ok(f)).unwrap() } /// Searches for an element of an iterator from the back that satisfies a predicate. @@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind

(&mut self, mut predicate: P) -> Option + fn rfind

(&mut self, predicate: P) -> Option where Self: Sized, P: FnMut(&Self::Item) -> bool { - self.try_rfold((), move |(), x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check( + mut predicate: impl FnMut(&T) -> bool, + ) -> impl FnMut((), T) -> LoopState<(), T> { + move |(), x| { + if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) } + } + } + + self.try_rfold((), check(predicate)).break_value() } } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 7e941267ce..da49223dfb 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1,5 +1,5 @@ -use crate::cmp::Ordering; -use crate::ops::Try; +use crate::cmp::{self, Ordering}; +use crate::ops::{Add, Try}; use super::super::LoopState; use super::super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse}; @@ -234,11 +234,15 @@ pub trait Iterator { /// assert_eq!(a.iter().count(), 5); /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] fn count(self) -> usize where Self: Sized { - // Might overflow. - self.fold(0, |cnt, _| cnt + 1) + #[inline] + fn add1(count: usize, _: T) -> usize { + // Might overflow. + Add::add(count, 1) + } + + self.fold(0, add1) } /// Consumes the iterator, returning the last element. @@ -263,7 +267,12 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn last(self) -> Option where Self: Sized { - self.fold(None, |_, x| Some(x)) + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) } /// Returns the `n`th element of the iterator. @@ -596,10 +605,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] - fn for_each(self, mut f: F) where + fn for_each(self, f: F) where Self: Sized, F: FnMut(Self::Item), { - self.fold((), move |(), item| f(item)); + #[inline] + fn call(mut f: impl FnMut(T)) -> impl FnMut((), T) { + move |(), item| f(item) + } + + self.fold((), call(f)); } /// Creates an iterator which uses a closure to determine if an element @@ -1490,21 +1504,30 @@ pub trait Iterator { /// assert_eq!(odd, vec![1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn partition(self, mut f: F) -> (B, B) where + fn partition(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend, F: FnMut(&Self::Item) -> bool { + #[inline] + fn extend<'a, T, B: Extend>( + mut f: impl FnMut(&T) -> bool + 'a, + left: &'a mut B, + right: &'a mut B, + ) -> impl FnMut(T) + 'a { + move |x| { + if f(&x) { + left.extend(Some(x)); + } else { + right.extend(Some(x)); + } + } + } + let mut left: B = Default::default(); let mut right: B = Default::default(); - self.for_each(|x| { - if f(&x) { - left.extend(Some(x)) - } else { - right.extend(Some(x)) - } - }); + self.for_each(extend(f, &mut left, &mut right)); (left, right) } @@ -1702,10 +1725,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_for_each(&mut self, mut f: F) -> R where + fn try_for_each(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try { - self.try_fold((), move |(), x| f(x)) + #[inline] + fn call(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { + move |(), x| f(x) + } + + self.try_fold((), call(f)) } /// An iterator method that applies a function, producing a single, final value. @@ -1777,10 +1805,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn fold(mut self, init: B, mut f: F) -> B where + fn fold(mut self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, move |acc, x| Ok::(f(acc, x))).unwrap() + #[inline] + fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { + move |acc, x| Ok(f(acc, x)) + } + + self.try_fold(init, ok(f)).unwrap() } /// Tests if every element of the iterator matches a predicate. @@ -1822,13 +1855,18 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn all(&mut self, mut f: F) -> bool where + fn all(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Continue(()) } - else { LoopState::Break(()) } - }) == LoopState::Continue(()) + #[inline] + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Continue(()) } + else { LoopState::Break(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -1870,14 +1908,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn any(&mut self, mut f: F) -> bool where + fn any(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Break(()) } - else { LoopState::Continue(()) } - }) == LoopState::Break(()) + #[inline] + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Break(()) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -1924,14 +1967,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn find

(&mut self, mut predicate: P) -> Option where + fn find

(&mut self, predicate: P) -> Option where Self: Sized, P: FnMut(&Self::Item) -> bool, { - self.try_for_each(move |x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> { + move |x| { + if predicate(&x) { LoopState::Break(x) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(predicate)).break_value() } /// Applies function to the elements of iterator and returns @@ -1951,16 +1999,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] - fn find_map(&mut self, mut f: F) -> Option where + fn find_map(&mut self, f: F) -> Option where Self: Sized, F: FnMut(Self::Item) -> Option, { - self.try_for_each(move |x| { - match f(x) { + #[inline] + fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut(T) -> LoopState<(), B> { + move |x| match f(x) { Some(x) => LoopState::Break(x), None => LoopState::Continue(()), } - }).break_value() + } + + self.try_for_each(check(f)).break_value() } /// Searches for an element in an iterator, returning its index. @@ -2018,17 +2069,23 @@ pub trait Iterator { /// /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] - fn position

(&mut self, mut predicate: P) -> Option where + fn position

(&mut self, predicate: P) -> Option where Self: Sized, P: FnMut(Self::Item) -> bool, { - // The addition might panic on overflow - self.try_fold(0, move |i, x| { - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i + 1) } - }).break_value() + #[inline] + fn check( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState { + // The addition might panic on overflow + move |i, x| { + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(Add::add(i, 1)) } + } + } + + self.try_fold(0, check(predicate)).break_value() } /// Searches for an element in an iterator from the right, returning its @@ -2071,18 +2128,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rposition

(&mut self, mut predicate: P) -> Option where + fn rposition

(&mut self, predicate: P) -> Option where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator { // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. + #[inline] + fn check( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState { + move |i, x| { + let i = i - 1; + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(i) } + } + } + let n = self.len(); - self.try_rfold(n, move |i, x| { - let i = i - 1; - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i) } - }).break_value() + self.try_rfold(n, check(predicate)).break_value() } /// Returns the maximum element of an iterator. @@ -2151,11 +2215,21 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn max_by_key(self, mut f: F) -> Option + fn max_by_key(self, f: F) -> Option where Self: Sized, F: FnMut(&Self::Item) -> B, { - // switch to y even if it is only equal, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x) + #[inline] + fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + + #[inline] + fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + x_p.cmp(y_p) + } + + let (_, x) = self.map(key(f)).max_by(compare)?; + Some(x) } /// Returns the element that gives the maximum value with respect to the @@ -2174,11 +2248,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] - fn max_by(self, mut compare: F) -> Option + fn max_by(self, compare: F) -> Option where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - // switch to y even if it is only equal, to preserve stability. - select_fold1(self, |x, y| compare(x, y) != Ordering::Greater) + #[inline] + fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { + move |x, y| cmp::max_by(x, y, &mut compare) + } + + fold1(self, fold(compare)) } /// Returns the element that gives the minimum value from the @@ -2195,12 +2273,23 @@ pub trait Iterator { /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); /// ``` + #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn min_by_key(self, mut f: F) -> Option + fn min_by_key(self, f: F) -> Option where Self: Sized, F: FnMut(&Self::Item) -> B, { - // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x) + #[inline] + fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + + #[inline] + fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + x_p.cmp(y_p) + } + + let (_, x) = self.map(key(f)).min_by(compare)?; + Some(x) } /// Returns the element that gives the minimum value with respect to the @@ -2219,11 +2308,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] - fn min_by(self, mut compare: F) -> Option + fn min_by(self, compare: F) -> Option where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self, |x, y| compare(x, y) == Ordering::Greater) + #[inline] + fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { + move |x, y| cmp::min_by(x, y, &mut compare) + } + + fold1(self, fold(compare)) } @@ -2284,13 +2377,20 @@ pub trait Iterator { FromB: Default + Extend, Self: Sized + Iterator, { + fn extend<'a, A, B>( + ts: &'a mut impl Extend, + us: &'a mut impl Extend, + ) -> impl FnMut((A, B)) + 'a { + move |(t, u)| { + ts.extend(Some(t)); + us.extend(Some(u)); + } + } + let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - self.for_each(|(t, u)| { - ts.extend(Some(t)); - us.extend(Some(u)); - }); + self.for_each(extend(&mut ts, &mut us)); (ts, us) } @@ -2442,11 +2542,51 @@ pub trait Iterator { /// Lexicographically compares the elements of this `Iterator` with those /// of another. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1].iter().cmp([1].iter()), Ordering::Equal); + /// assert_eq!([1].iter().cmp([1, 2].iter()), Ordering::Less); + /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn cmp(mut self, other: I) -> Ordering where + fn cmp(self, other: I) -> Ordering + where I: IntoIterator, Self::Item: Ord, Self: Sized, + { + self.cmp_by(other, |x, y| x.cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn cmp_by(mut self, other: I, mut cmp: F) -> Ordering + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Ordering, { let mut other = other.into_iter(); @@ -2465,7 +2605,7 @@ pub trait Iterator { Some(val) => val, }; - match x.cmp(&y) { + match cmp(x, y) { Ordering::Equal => (), non_eq => return non_eq, } @@ -2474,11 +2614,62 @@ pub trait Iterator { /// Lexicographically compares the elements of this `Iterator` with those /// of another. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal)); + /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less)); + /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater)); + /// + /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn partial_cmp(mut self, other: I) -> Option where + fn partial_cmp(self, other: I) -> Option + where I: IntoIterator, Self::Item: PartialOrd, Self: Sized, + { + self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1.0, 2.0, 3.0, 4.0]; + /// let ys = [1.0, 4.0, 9.0, 16.0]; + /// + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)), + /// Some(Ordering::Less) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)), + /// Some(Ordering::Equal) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)), + /// Some(Ordering::Greater) + /// ); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn partial_cmp_by(mut self, other: I, mut partial_cmp: F) -> Option + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Option, { let mut other = other.into_iter(); @@ -2497,7 +2688,7 @@ pub trait Iterator { Some(val) => val, }; - match x.partial_cmp(&y) { + match partial_cmp(x, y) { Some(Ordering::Equal) => (), non_eq => return non_eq, } @@ -2506,11 +2697,44 @@ pub trait Iterator { /// Determines if the elements of this `Iterator` are equal to those of /// another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().eq([1].iter()), true); + /// assert_eq!([1].iter().eq([1, 2].iter()), false); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn eq(mut self, other: I) -> bool where + fn eq(self, other: I) -> bool + where I: IntoIterator, Self::Item: PartialEq, Self: Sized, + { + self.eq_by(other, |x, y| x == y) + } + + /// Determines if the elements of this `Iterator` are equal to those of + /// another with respect to the specified equality function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn eq_by(mut self, other: I, mut eq: F) -> bool + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> bool, { let mut other = other.into_iter(); @@ -2525,12 +2749,21 @@ pub trait Iterator { Some(val) => val, }; - if x != y { return false } + if !eq(x, y) { + return false; + } } } /// Determines if the elements of this `Iterator` are unequal to those of /// another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().ne([1].iter()), false); + /// assert_eq!([1].iter().ne([1, 2].iter()), true); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] fn ne(self, other: I) -> bool where I: IntoIterator, @@ -2542,6 +2775,14 @@ pub trait Iterator { /// Determines if the elements of this `Iterator` are lexicographically /// less than those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().lt([1].iter()), false); + /// assert_eq!([1].iter().lt([1, 2].iter()), true); + /// assert_eq!([1, 2].iter().lt([1].iter()), false); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] fn lt(self, other: I) -> bool where I: IntoIterator, @@ -2553,6 +2794,14 @@ pub trait Iterator { /// Determines if the elements of this `Iterator` are lexicographically /// less or equal to those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().le([1].iter()), true); + /// assert_eq!([1].iter().le([1, 2].iter()), true); + /// assert_eq!([1, 2].iter().le([1].iter()), false); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] fn le(self, other: I) -> bool where I: IntoIterator, @@ -2567,6 +2816,14 @@ pub trait Iterator { /// Determines if the elements of this `Iterator` are lexicographically /// greater than those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().gt([1].iter()), false); + /// assert_eq!([1].iter().gt([1, 2].iter()), false); + /// assert_eq!([1, 2].iter().gt([1].iter()), true); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] fn gt(self, other: I) -> bool where I: IntoIterator, @@ -2578,6 +2835,14 @@ pub trait Iterator { /// Determines if the elements of this `Iterator` are lexicographically /// greater than or equal to those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().ge([1].iter()), true); + /// assert_eq!([1].iter().ge([1, 2].iter()), false); + /// assert_eq!([1, 2].iter().ge([1].iter()), true); + /// ``` #[stable(feature = "iter_order", since = "1.5.0")] fn ge(self, other: I) -> bool where I: IntoIterator, @@ -2617,7 +2882,7 @@ pub trait Iterator { Self: Sized, Self::Item: PartialOrd, { - self.is_sorted_by(|a, b| a.partial_cmp(b)) + self.is_sorted_by(PartialOrd::partial_cmp) } /// Checks if the elements of this iterator are sorted using the given comparator function. @@ -2626,6 +2891,18 @@ pub trait Iterator { /// function to determine the ordering of two elements. Apart from that, it's equivalent to /// [`is_sorted`]; see its documentation for more information. /// + /// # Examples + /// + /// ``` + /// #![feature(is_sorted)] + /// + /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b))); + /// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b))); + /// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b))); + /// assert!(std::iter::empty::().is_sorted_by(|a, b| a.partial_cmp(b))); + /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b))); + /// ``` + /// /// [`is_sorted`]: trait.Iterator.html#method.is_sorted #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] fn is_sorted_by(mut self, mut compare: F) -> bool @@ -2639,10 +2916,7 @@ pub trait Iterator { }; while let Some(curr) = self.next() { - if compare(&last, &curr) - .map(|o| o == Ordering::Greater) - .unwrap_or(true) - { + if let Some(Ordering::Greater) | None = compare(&last, &curr) { return false; } last = curr; @@ -2680,24 +2954,18 @@ pub trait Iterator { } } -/// Select an element from an iterator based on the given "comparison" -/// function. -/// -/// This is an idiosyncratic helper to try to factor out the -/// commonalities of {max,min}{,_by}. In particular, this avoids -/// having to implement optimizations several times. +/// Fold an iterator without having to provide an initial value. #[inline] -fn select_fold1(mut it: I, mut f: F) -> Option +fn fold1(mut it: I, f: F) -> Option where I: Iterator, - F: FnMut(&I::Item, &I::Item) -> bool, + F: FnMut(I::Item, I::Item) -> I::Item, { // start with the first element as our selection. This avoids // having to use `Option`s inside the loop, translating to a // sizeable performance gain (6x in one case). - it.next().map(|first| { - it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel }) - }) + let first = it.next()?; + Some(it.fold(first, f)) } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 678ff76879..8221df56a5 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -63,7 +63,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] @@ -87,7 +87,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] @@ -120,16 +120,16 @@ #![feature(rtm_target_feature)] #![feature(f16c_target_feature)] #![feature(hexagon_target_feature)] -#![feature(const_slice_len)] -#![feature(const_str_as_bytes)] -#![feature(const_str_len)] +#![cfg_attr(bootstrap, feature(const_slice_len))] +#![cfg_attr(bootstrap, feature(const_str_as_bytes))] +#![cfg_attr(bootstrap, feature(const_str_len))] #![feature(const_int_conversion)] #![feature(const_transmute)] #![feature(non_exhaustive)] #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(mem_take)] #![feature(associated_type_bounds)] @@ -227,6 +227,7 @@ pub mod task; pub mod alloc; // note: does not need to be public +mod bool; mod tuple; mod unit; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 680fcd12c4..c6f5fb0b16 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -2,21 +2,21 @@ /// /// For details, see `std::macros`. #[macro_export] -#[allow_internal_unstable(core_panic, __rust_unstable_column)] +#[allow_internal_unstable(core_panic)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( $crate::panic!("explicit panic") ); ($msg:expr) => ({ - $crate::panicking::panic(&($msg, file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!())) }); ($msg:expr,) => ( $crate::panic!($msg) ); ($fmt:expr, $($arg:tt)+) => ({ - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)+), - &(file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), + &($crate::file!(), $crate::line!(), $crate::column!())) }); } @@ -70,7 +70,7 @@ macro_rules! assert_eq { panic!(r#"assertion failed: `(left == right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -127,7 +127,7 @@ macro_rules! assert_ne { panic!(r#"assertion failed: `(left != right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -181,7 +181,7 @@ macro_rules! assert_ne { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } /// Asserts that two expressions are equal to each other. @@ -208,7 +208,7 @@ macro_rules! debug_assert { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) } /// Asserts that two expressions are not equal to each other. @@ -235,7 +235,7 @@ macro_rules! debug_assert_eq { #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] macro_rules! debug_assert_ne { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) } /// Unwraps a result or propagates its error. @@ -386,7 +386,7 @@ macro_rules! r#try { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! write { - ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*))) + ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*))) } /// Write formatted data into a buffer, with a newline appended. @@ -446,7 +446,7 @@ macro_rules! writeln { $crate::writeln!($dst) ); ($dst:expr, $($arg:tt)*) => ( - $dst.write_fmt(format_args_nl!($($arg)*)) + $dst.write_fmt($crate::format_args_nl!($($arg)*)) ); } @@ -515,7 +515,7 @@ macro_rules! unreachable { $crate::unreachable!($msg) }); ($fmt:expr, $($arg:tt)*) => ({ - panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) }); } @@ -573,7 +573,7 @@ macro_rules! unreachable { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Indicates unfinished code. @@ -632,41 +632,7 @@ macro_rules! unimplemented { #[unstable(feature = "todo_macro", issue = "59277")] macro_rules! todo { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Remove both versions of this macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(bootstrap)] -macro_rules! uninit_array { - // This `assume_init` is safe because an array of `MaybeUninit` does not - // require initialization. - ($t:ty; $size:expr) => (unsafe { - MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init() - }); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Just inline this version of the macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(not(bootstrap))] -macro_rules! uninit_array { - ($t:ty; $size:expr) => ( - [MaybeUninit::<$t>::UNINIT; $size] - ); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Definitions of built-in macros. @@ -674,7 +640,6 @@ macro_rules! uninit_array { /// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, /// with exception of expansion functions transforming macro inputs into outputs, /// those functions are provided by the compiler. -#[cfg(not(bootstrap))] pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. @@ -769,7 +734,6 @@ pub(crate) mod builtin { #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] - #[rustc_macro_transparency = "opaque"] macro_rules! format_args { ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) @@ -782,7 +746,6 @@ pub(crate) mod builtin { #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] - #[rustc_macro_transparency = "opaque"] macro_rules! format_args_nl { ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) @@ -962,13 +925,6 @@ pub(crate) mod builtin { #[macro_export] macro_rules! column { () => { /* compiler built-in */ } } - /// Same as `column`, but less likely to be shadowed. - #[unstable(feature = "__rust_unstable_column", issue = "0", - reason = "internal implementation detail of the `panic` macro")] - #[rustc_builtin_macro] - #[macro_export] - macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } } - /// Expands to the file name in which it was invoked. /// /// With [`line!`] and [`column!`], these macros provide debugging information for @@ -1277,17 +1233,15 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. - #[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297", + #[cfg_attr(not(bootstrap), unstable(soft, feature = "test", issue = "50297", reason = "`bench` is a part of custom test frameworks which are unstable"))] - #[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297", + #[cfg_attr(bootstrap, unstable(feature = "test", issue = "50297", reason = "`bench` is a part of custom test frameworks which are unstable"))] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro bench($item:item) { /* compiler built-in */ } /// An implementation detail of the `#[test]` and `#[bench]` macros. @@ -1295,26 +1249,22 @@ pub(crate) mod builtin { reason = "custom test frameworks are an unstable feature")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro test_case($item:item) { /* compiler built-in */ } /// Attribute macro applied to a static to register it as a global allocator. #[stable(feature = "global_allocator", since = "1.28.0")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro global_allocator($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)] pub macro RustcDecodable($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics)] pub macro RustcEncodable($item:item) { /* compiler built-in */ } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 78a2736116..a2cfb320e7 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -289,9 +289,8 @@ pub trait Copy : Clone { } /// Derive macro generating an impl of the trait `Copy`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } @@ -603,10 +602,10 @@ unsafe impl Freeze for *mut T {} unsafe impl Freeze for &T {} unsafe impl Freeze for &mut T {} -/// Types which can be safely moved after being pinned. +/// Types that can be safely moved after being pinned. /// /// Since Rust itself has no notion of immovable types, and considers moves -/// (e.g. through assignment or [`mem::replace`]) to always be safe, +/// (e.g., through assignment or [`mem::replace`]) to always be safe, /// this trait cannot prevent types from moving by itself. /// /// Instead it is used to prevent moves through the type system, diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 1bbea02e0c..9e9e901c76 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -213,7 +213,7 @@ use crate::mem::ManuallyDrop; #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for generators. -#[cfg_attr(not(bootstrap), lang = "maybe_uninit")] +#[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] pub union MaybeUninit { @@ -312,7 +312,7 @@ impl MaybeUninit { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -502,7 +502,7 @@ impl MaybeUninit { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::(); @@ -516,7 +516,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined /// behavior. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { &*self.value @@ -532,21 +532,21 @@ impl MaybeUninit { // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { &mut *self.value } /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr(this: &[MaybeUninit]) -> *const T { this as *const [MaybeUninit] as *const T } /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { this as *mut [MaybeUninit] as *mut T diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 2534400b83..87ec05a243 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -453,7 +453,7 @@ pub const fn needs_drop() -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn zeroed() -> T { intrinsics::panic_if_uninhabited::(); @@ -481,7 +481,7 @@ pub unsafe fn zeroed() -> T { #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 8ff78166a9..22e7573eca 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -315,7 +315,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d45c04f45a..bbe1d04078 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -327,7 +327,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 67e30e7ffc..5d99c10e73 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,7 +1112,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -1135,7 +1141,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -1157,7 +1169,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_mul(self, rhs) + } } } @@ -1383,12 +1401,8 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] - pub fn wrapping_abs(self) -> Self { - if self.is_negative() { - self.wrapping_neg() - } else { - self - } + pub const fn wrapping_abs(self) -> Self { + (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1)) } } @@ -1746,12 +1760,8 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] - pub fn overflowing_abs(self) -> (Self, bool) { - if self.is_negative() { - self.overflowing_neg() - } else { - (self, false) - } + pub const fn overflowing_abs(self) -> (Self, bool) { + (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1)) } } @@ -1955,15 +1965,11 @@ $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_inherit_overflow_checks] - pub fn abs(self) -> Self { - if self.is_negative() { - // Note that the #[inline] above means that the overflow - // semantics of this negation depend on the crate we're being - // inlined into. - -self - } else { - self - } + pub const fn abs(self) -> Self { + // Note that the #[inline] above means that the overflow + // semantics of the subtraction depend on the crate we're being + // inlined into. + (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1)) } } @@ -2086,11 +2092,14 @@ $to_xe_bytes_doc, ``` let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); -assert_eq!(bytes, if cfg!(target_endian = \"big\") { +assert_eq!( + bytes, + if cfg!(target_endian = \"big\") { ", $be_bytes, " } else { ", $le_bytes, " - }); + } +); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2182,10 +2191,10 @@ $from_xe_bytes_doc, ``` let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { - ", $be_bytes, " - } else { - ", $le_bytes, " - }); + ", $be_bytes, " +} else { + ", $le_bytes, " +}); assert_eq!(value, ", $swap_op, "); ``` @@ -3031,7 +3040,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -3053,7 +3068,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -3076,7 +3097,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(bootstrap)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(bootstrap))] { + intrinsics::wrapping_mul(self, rhs) + } } doc_comment! { @@ -3887,11 +3914,14 @@ $to_xe_bytes_doc, ``` let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); -assert_eq!(bytes, if cfg!(target_endian = \"big\") { +assert_eq!( + bytes, + if cfg!(target_endian = \"big\") { ", $be_bytes, " } else { ", $le_bytes, " - }); + } +); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3983,10 +4013,10 @@ $from_xe_bytes_doc, ``` let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { - ", $be_bytes, " - } else { - ", $le_bytes, " - }); + ", $be_bytes, " +} else { + ", $le_bytes, " +}); assert_eq!(value, ", $swap_op, "); ``` diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index fd129a306d..59a10ae99b 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -18,6 +18,8 @@ macro_rules! sh_impl_signed { } } } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -41,6 +43,8 @@ macro_rules! sh_impl_signed { } } } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { @@ -64,6 +68,8 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) } } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -83,6 +89,8 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) } } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index b9552eaa1a..4a0a2720fe 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -185,14 +185,6 @@ pub trait FnMut : FnOnce { /// /// # Examples /// -/// ## Calling a by-value closure -/// -/// ``` -/// let x = 5; -/// let square_x = move || x * x; -/// assert_eq!(square_x(), 25); -/// ``` -/// /// ## Using a `FnOnce` parameter /// /// ``` diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 259ed36c57..5569d99f8d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -295,7 +295,7 @@ impl Option { /// [`Pin`]: ../pin/struct.Pin.html #[inline] #[stable(feature = "pin", since = "1.33.0")] - pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { + pub fn as_pin_ref(self: Pin<&Self>) -> Option> { unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } @@ -306,7 +306,7 @@ impl Option { /// [`Pin`]: ../pin/struct.Pin.html #[inline] #[stable(feature = "pin", since = "1.33.0")] - pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { + pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } @@ -1110,6 +1110,18 @@ impl Option { /// to the original one, additionally coercing the contents via [`Deref`]. /// /// [`Deref`]: ../../std/ops/trait.Deref.html + /// + /// # Examples + /// + /// ``` + /// #![feature(inner_deref)] + /// + /// let x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref(), Some("hey")); + /// + /// let x: Option = None; + /// assert_eq!(x.as_deref(), None); + /// ``` pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } @@ -1121,6 +1133,18 @@ impl Option { /// /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to /// the inner type's `Deref::Target` type. + /// + /// # Examples + /// + /// ``` + /// #![feature(inner_deref)] + /// + /// let mut x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref_mut().map(|x| { + /// x.make_ascii_uppercase(); + /// x + /// }), Some("HEY".to_owned().as_mut_str())); + /// ``` pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { self.as_mut().map(|t| t.deref_mut()) } @@ -1199,6 +1223,13 @@ impl Clone for Option { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { /// Returns [`None`][Option::None]. + /// + /// # Examples + /// + /// ``` + /// let opt: Option = Option::default(); + /// assert!(opt.is_none()); + /// ``` #[inline] fn default() -> Option { None } } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 15b7d69c58..7b7253419b 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -71,7 +71,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3 } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - #[allow(improper_ctypes)] // PanicInfo contains a trait object which is not FFI safe + #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 6efeaf9ee7..1dc6d54b08 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -233,7 +233,7 @@ //! # type Field = i32; //! # struct Struct { field: Field } //! impl Struct { -//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { +//! fn pin_get_field(self: Pin<&mut Self>) -> &mut Field { //! // This is okay because `field` is never considered pinned. //! unsafe { &mut self.get_unchecked_mut().field } //! } @@ -257,7 +257,7 @@ //! # type Field = i32; //! # struct Struct { field: Field } //! impl Struct { -//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { +//! fn pin_get_field(self: Pin<&mut Self>) -> Pin<&mut Field> { //! // This is okay because `field` is pinned when `self` is. //! unsafe { self.map_unchecked_mut(|s| &mut s.field) } //! } @@ -462,7 +462,7 @@ impl> Pin

{ /// can ignore the pinning invariants when unwrapping it. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub fn into_inner(pin: Pin

) -> P { pin.pointer @@ -549,7 +549,7 @@ impl Pin

{ /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { + pub fn as_ref(&self) -> Pin<&P::Target> { unsafe { Pin::new_unchecked(&*self.pointer) } } @@ -569,7 +569,7 @@ impl Pin

{ /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`Pin::into_inner`]: #method.into_inner - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub unsafe fn into_inner_unchecked(pin: Pin

) -> P { pin.pointer @@ -584,9 +584,30 @@ impl Pin

{ /// the pointee cannot move after `Pin>` got created. /// "Malicious" implementations of `Pointer::DerefMut` are likewise /// ruled out by the contract of `Pin::new_unchecked`. + /// + /// This method is useful when doing multiple calls to functions that consume the pinned type. + /// + /// # Example + /// + /// ``` + /// use std::pin::Pin; + /// + /// # struct Type {} + /// impl Type { + /// fn method(self: Pin<&mut Self>) { + /// // do something + /// } + /// + /// fn call_method_twice(mut self: Pin<&mut Self>) { + /// // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`. + /// self.as_mut().method(); + /// self.as_mut().method(); + /// } + /// } + /// ``` #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { + pub fn as_mut(&mut self) -> Pin<&mut P::Target> { unsafe { Pin::new_unchecked(&mut *self.pointer) } } @@ -596,7 +617,7 @@ impl Pin

{ /// run before being overwritten, so no pinning guarantee is violated. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn set(self: &mut Pin

, value: P::Target) + pub fn set(&mut self, value: P::Target) where P::Target: Sized, { @@ -621,7 +642,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] - pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where + pub unsafe fn map_unchecked(self, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, { let pointer = &*self.pointer; @@ -648,7 +669,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn get_ref(self: Pin<&'a T>) -> &'a T { + pub fn get_ref(self) -> &'a T { self.pointer } } @@ -657,7 +678,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> { + pub fn into_ref(self) -> Pin<&'a T> { Pin { pointer: self.pointer } } @@ -672,7 +693,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// with the same lifetime as the original `Pin`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T + pub fn get_mut(self) -> &'a mut T where T: Unpin, { self.pointer @@ -690,7 +711,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// instead. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T { + pub unsafe fn get_unchecked_mut(self) -> &'a mut T { self.pointer } @@ -710,7 +731,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] - pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where + pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, { let pointer = Pin::get_unchecked_mut(self); diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 84cf85f339..7cc279a9ef 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -46,20 +46,16 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::fmt::macros::Debug; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::hash::macros::Hash; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::{ - __rust_unstable_column, asm, assert, cfg, @@ -83,7 +79,6 @@ pub use crate::{ trace_macros, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(no_inline)] diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index f5fbd1a6b1..13ccc9b252 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1042,7 +1042,7 @@ impl *const T { (self as *const u8) == null() } - /// Cast to a pointer to a different type + /// Casts to a pointer of another type. #[stable(feature = "ptr_cast", since = "1.38.0")] #[inline] pub const fn cast(self) -> *const U { @@ -1726,7 +1726,7 @@ impl *mut T { (self as *mut u8) == null_mut() } - /// Cast to a pointer to a different type + /// Casts to a pointer of another type. #[stable(feature = "ptr_cast", since = "1.38.0")] #[inline] pub const fn cast(self) -> *mut U { diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs index ad3d1ce396..7dcd57f1f9 100644 --- a/src/libcore/ptr/non_null.rs +++ b/src/libcore/ptr/non_null.rs @@ -125,7 +125,7 @@ impl NonNull { &mut *self.as_ptr() } - /// Cast to a pointer of another type + /// Casts to a pointer of another type. #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] pub const fn cast(self) -> NonNull { diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f0d011fe6b..3521dd7997 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -122,6 +122,14 @@ impl Unique { pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Casts to a pointer of another type. + #[inline] + pub const fn cast(self) -> Unique { + unsafe { + Unique::new_unchecked(self.as_ptr() as *mut U) + } + } } #[unstable(feature = "ptr_internals", issue = "0")] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 8c60a9c1b5..ed40a5f31d 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -820,6 +820,87 @@ impl Result { } } +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.map(|&t| t) + } +} + +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.map(|&mut t| t) + } +} + +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.map(|t| t.clone()) + } +} + +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.map(|t| t.clone()) + } +} + + impl Result { /// Unwraps a result, yielding the content of an [`Ok`]. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ce5af13d4c..0c2a4e0867 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -62,7 +62,9 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_slice_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] + // SAFETY: const sound because we transmute out the length field as a usize (which it must be) + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] pub const fn len(&self) -> usize { unsafe { crate::ptr::Repr { rust: self }.raw.len @@ -79,7 +81,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_slice_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -3026,8 +3028,7 @@ macro_rules! len { if size == 0 { // This _cannot_ use `unchecked_sub` because we depend on wrapping // to represent the length of long ZST slice iterators. - let diff = ($self.end as usize).wrapping_sub(start as usize); - diff + ($self.end as usize).wrapping_sub(start as usize) } else { // We know that `start <= end`, so can do better than `offset_from`, // which needs to deal in signed. By setting appropriate flags here @@ -4637,6 +4638,22 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { Some(tail) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = start + self.chunk_size; + let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (head, nth_back) = temp.split_at_mut(start); + self.v = head; + Some(nth_back) + } + } } #[stable(feature = "chunks_exact", since = "1.31.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f20cb7bfbc..a6ec757faf 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2090,7 +2090,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_str_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn len(&self) -> usize { self.as_bytes().len() } @@ -2110,7 +2110,7 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_str_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2168,8 +2168,11 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - #[rustc_const_unstable(feature="const_str_as_bytes")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_as_bytes"))] + // SAFETY: const sound because we transmute two types with the same layout + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] pub const fn as_bytes(&self) -> &[u8] { + #[repr(C)] union Slices<'a> { str: &'a str, slice: &'a [u8], @@ -3557,7 +3560,7 @@ impl str { /// A string is a sequence of bytes. `start` in this context means the first /// position of that byte string; for a left-to-right language like English or /// Russian, this will be left side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the right side. + /// Arabic or Hebrew, this will be the right side. /// /// # Examples /// @@ -3594,7 +3597,7 @@ impl str { /// A string is a sequence of bytes. `end` in this context means the last /// position of that byte string; for a left-to-right language like English or /// Russian, this will be right side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the left side. + /// Arabic or Hebrew, this will be the left side. /// /// # Examples /// @@ -3761,7 +3764,7 @@ impl str { /// A string is a sequence of bytes. `start` in this context means the first /// position of that byte string; for a left-to-right language like English or /// Russian, this will be left side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the right side. + /// Arabic or Hebrew, this will be the right side. /// /// # Examples /// @@ -3800,7 +3803,7 @@ impl str { /// A string is a sequence of bytes. `end` in this context means the last /// position of that byte string; for a left-to-right language like English or /// Russian, this will be right side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the left side. + /// Arabic or Hebrew, this will be the left side. /// /// # Examples /// diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 8dfb19fa03..c9ccef972c 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -124,28 +124,31 @@ use crate::fmt; use crate::hint::spin_loop; -/// Signals the processor that it is entering a busy-wait spin-loop. +/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). /// /// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving /// power or switching hyper-threads. /// -/// This function is different than [`std::thread::yield_now`] which directly yields to the -/// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a -/// busy-wait spin-loop without yielding control to the system's scheduler. +/// This function is different from [`std::thread::yield_now`] which directly yields to the +/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system. /// -/// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a -/// contended lock is held by another thread executed on a different CPU and where the waiting -/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's -/// scheduler, no overhead for switching threads occurs. However, if the thread holding the -/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice -/// before switching to the thread that holds the lock. If the contending lock is held by a thread -/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to -/// use [`std::thread::yield_now`]. +/// Spin locks can be very efficient for short lock durations because they do not involve context +/// switches or interaction with the operating system. For long lock durations they become wasteful +/// however because they use CPU cycles for the entire lock duration, and using a +/// [`std::sync::Mutex`] is likely the better approach. If actively spinning for a long time is +/// required, e.g. because code polls a non-blocking API, calling [`std::thread::yield_now`] +/// or [`std::thread::sleep`] may be the best option. +/// +/// **Note**: Spin locks are based on the underlying assumption that another thread will release +/// the lock 'soon'. In order for this to work, that other thread must run on a different CPU or +/// core (at least potentially). Spin locks do not work efficiently on single CPU / core platforms. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// /// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html +/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html +/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html #[inline] #[stable(feature = "spin_loop_hint", since = "1.24.0")] pub fn spin_loop_hint() { @@ -979,9 +982,8 @@ impl AtomicPtr { /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; - /// let another_ptr = &mut 10; /// - /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed); + /// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1021,9 +1023,8 @@ impl AtomicPtr { /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; - /// let another_ptr = &mut 10; /// - /// let value = some_ptr.compare_exchange(other_ptr, another_ptr, + /// let value = some_ptr.compare_exchange(ptr, other_ptr, /// Ordering::SeqCst, Ordering::Relaxed); /// ``` #[inline] diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs index 3db70d5e76..fec17c4d1a 100644 --- a/src/libcore/task/poll.rs +++ b/src/libcore/task/poll.rs @@ -81,6 +81,34 @@ impl Poll> { } } +impl Poll>> { + /// Changes the success value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_ok(self, f: F) -> Poll>> + where F: FnOnce(T) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } + + /// Changes the error value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_err(self, f: F) -> Poll>> + where F: FnOnce(E) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] impl From for Poll { fn from(t: T) -> Poll { diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs new file mode 100644 index 0000000000..0f1e6e8945 --- /dev/null +++ b/src/libcore/tests/bool.rs @@ -0,0 +1,7 @@ +#[test] +fn test_bool_to_option() { + assert_eq!(false.then(0), None); + assert_eq!(true.then(0), Some(0)); + assert_eq!(false.then_with(|| 0), None); + assert_eq!(true.then_with(|| 0), Some(0)); +} diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index 4e624e5eb1..5e6778e222 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -1,4 +1,4 @@ -use core::cmp::Ordering::{Less, Greater, Equal}; +use core::cmp::{self, Ordering::*}; #[test] fn test_int_totalord() { @@ -28,6 +28,28 @@ fn test_ord_max_min() { assert_eq!(1.min(1), 1); } +#[test] +fn test_ord_min_max_by() { + let f = |x: &i32, y: &i32| x.abs().cmp(&y.abs()); + assert_eq!(cmp::min_by(1, -1, f), 1); + assert_eq!(cmp::min_by(1, -2, f), 1); + assert_eq!(cmp::min_by(2, -1, f), -1); + assert_eq!(cmp::max_by(1, -1, f), -1); + assert_eq!(cmp::max_by(1, -2, f), -2); + assert_eq!(cmp::max_by(2, -1, f), 2); +} + +#[test] +fn test_ord_min_max_by_key() { + let f = |x: &i32| x.abs(); + assert_eq!(cmp::min_by_key(1, -1, f), 1); + assert_eq!(cmp::min_by_key(1, -2, f), 1); + assert_eq!(cmp::min_by_key(2, -1, f), -1); + assert_eq!(cmp::max_by_key(1, -1, f), -1); + assert_eq!(cmp::max_by_key(1, -2, f), -2); + assert_eq!(cmp::max_by_key(2, -1, f), 2); +} + #[test] fn test_ordering_reverse() { assert_eq!(Less.reverse(), Greater); diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3615fab791..c9096b713f 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -57,6 +57,62 @@ fn test_multi_iter() { assert!(xs.iter().lt(xs.iter().skip(2))); } +#[test] +fn test_cmp_by() { + use core::cmp::Ordering; + + let f = |x: i32, y: i32| (x * x).cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().cmp_by(ys(), f), Ordering::Less); + assert_eq!(ys().cmp_by(xs(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(xs().map(|x| x * x), f), Ordering::Equal); + assert_eq!(xs().rev().cmp_by(ys().rev(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(ys().rev(), f), Ordering::Less); + assert_eq!(xs().cmp_by(ys().take(2), f), Ordering::Greater); +} + +#[test] +fn test_partial_cmp_by() { + use core::cmp::Ordering; + use core::f64; + + let f = |x: i32, y: i32| (x * x).partial_cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), Some(Ordering::Less)); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().map(|x| x * x), f), Some(Ordering::Equal)); + assert_eq!(xs().rev().partial_cmp_by(ys().rev(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().rev(), f), Some(Ordering::Less)); + assert_eq!(xs().partial_cmp_by(ys().take(2), f), Some(Ordering::Greater)); + + let f = |x: f64, y: f64| (x * x).partial_cmp(&y); + let xs = || [1.0, 2.0, 3.0, 4.0].iter().copied(); + let ys = || [1.0, 4.0, f64::NAN, 16.0].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), None); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); +} + +#[test] +fn test_eq_by() { + let f = |x: i32, y: i32| x * x == y; + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 9, 16].iter().copied(); + + assert!(xs().eq_by(ys(), f)); + assert!(!ys().eq_by(xs(), f)); + assert!(!xs().eq_by(xs(), f)); + assert!(!ys().eq_by(ys(), f)); + + assert!(!xs().take(3).eq_by(ys(), f)); + assert!(!xs().eq_by(ys().take(3), f)); + assert!(xs().take(3).eq_by(ys().take(3), f)); +} + #[test] fn test_counter_from_iter() { let it = (0..).step_by(5).take(10); @@ -103,6 +159,22 @@ fn test_iterator_chain_nth() { assert_eq!(it.next(), None); } +#[test] +fn test_iterator_chain_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let zs = []; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + for (i, x) in expected.iter().rev().enumerate() { + assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i)); + } + assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5)); + + let mut it = xs.iter().chain(&zs); + assert_eq!(it.nth_back(5), Some(&0)); + assert_eq!(it.next(), None); +} + #[test] fn test_iterator_chain_last() { let xs = [0, 1, 2, 3, 4, 5]; @@ -136,6 +208,54 @@ fn test_iterator_chain_find() { assert_eq!(iter.next(), None); } +#[test] +fn test_iterator_chain_size_hint() { + struct Iter { + is_empty: bool, + } + + impl Iterator for Iter { + type Item = (); + + // alternates between `None` and `Some(())` + fn next(&mut self) -> Option { + if self.is_empty { + self.is_empty = false; + None + } else { + self.is_empty = true; + Some(()) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.is_empty { + (0, Some(0)) + } else { + (1, Some(1)) + } + } + } + + impl DoubleEndedIterator for Iter { + fn next_back(&mut self) -> Option { + self.next() + } + } + + // this chains an iterator of length 0 with an iterator of length 1, + // so after calling `.next()` once, the iterator is empty and the + // state is `ChainState::Back`. `.size_hint()` should now disregard + // the size hint of the left iterator + let mut iter = Iter { is_empty: true }.chain(once(())); + assert_eq!(iter.next(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); + + let mut iter = once(()).chain(Iter { is_empty: true }); + assert_eq!(iter.next_back(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); +} + #[test] fn test_zip_nth() { let xs = [0, 1, 2, 4, 5]; @@ -265,6 +385,23 @@ fn test_iterator_step_by_nth_overflow() { assert_eq!(it.0, (usize::MAX as Bigger) * 1); } +#[test] +fn test_iterator_step_by_nth_try_fold() { + let mut it = (0..).step_by(10); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(60)); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(90)); + + let mut it = (100..).step_by(10); + assert_eq!(it.try_fold(50, i8::checked_add), None); + assert_eq!(it.next(), Some(110)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + #[test] fn test_iterator_step_by_nth_back() { let mut it = (0..16).step_by(5); @@ -290,6 +427,24 @@ fn test_iterator_step_by_nth_back() { assert_eq!(it().nth_back(42), None); } +#[test] +fn test_iterator_step_by_nth_try_rfold() { + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(70)); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(30)); + + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(50, i8::checked_add), None); + assert_eq!(it.next_back(), Some(80)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next_back(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + #[test] #[should_panic] fn test_iterator_step_by_zero() { @@ -1136,6 +1291,18 @@ fn test_cycle() { assert_eq!(empty::().cycle().fold(0, |acc, x| acc + x), 0); assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4); + + assert_eq!((0..10).cycle().take(5).sum::(), 10); + assert_eq!((0..10).cycle().take(15).sum::(), 55); + assert_eq!((0..10).cycle().take(25).sum::(), 100); + + let mut iter = (0..10).cycle(); + iter.nth(14); + assert_eq!(iter.take(8).sum::(), 38); + + let mut iter = (0..10).cycle(); + iter.nth(9); + assert_eq!(iter.take(3).sum::(), 3); } #[test] @@ -1612,6 +1779,12 @@ fn test_rposition() { assert!(v.iter().rposition(g).is_none()); } +#[test] +fn test_rev_rposition() { + let v = [0, 0, 1, 1]; + assert_eq!(v.iter().rev().rposition(|&x| x == 1), Some(1)); +} + #[test] #[should_panic] fn test_rposition_panic() { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index a3b108b2e9..3566135602 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -1,3 +1,4 @@ +#![feature(bool_to_option)] #![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] @@ -32,6 +33,8 @@ #![feature(const_fn)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] +#![feature(iter_order_by)] +#![feature(cmp_min_max_by)] extern crate test; @@ -40,6 +43,7 @@ mod any; mod array; mod ascii; mod atomic; +mod bool; mod cell; mod char; mod clone; diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 4790152512..6609bc3135 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -374,6 +374,25 @@ fn test_chunks_exact_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.chunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.chunks_exact_mut(3); + assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c3 = v3.chunks_exact_mut(10); + assert_eq!(c3.nth_back(0), None); +} + #[test] fn test_chunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs index 272727def6..a3ec9fd51f 100644 --- a/src/libcore/unicode/mod.rs +++ b/src/libcore/unicode/mod.rs @@ -13,8 +13,3 @@ pub mod derived_property { pub mod conversions { pub use crate::unicode::tables::conversions::{to_lower, to_upper}; } - -// For use in libsyntax -pub mod property { - pub use crate::unicode::tables::property::Pattern_White_Space; -} diff --git a/src/libcore/unicode/printable.py b/src/libcore/unicode/printable.py index 748917f1d3..4e8b4ecad0 100644 --- a/src/libcore/unicode/printable.py +++ b/src/libcore/unicode/printable.py @@ -60,7 +60,7 @@ def get_codepoints(f): yield Codepoint(codepoint, class_) prev_codepoint = codepoint - if class_first != None: + if class_first is not None: raise ValueError("Missing Last after First") for c in range(prev_codepoint + 1, NUM_CODEPOINTS): diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index 3fae3a46ad..5b5be48543 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -890,384 +890,9 @@ pub(crate) mod derived_property { Uppercase_table.lookup(c) } - const XID_Continue_table: &super::BoolTrie = &super::BoolTrie { - r1: [ - 0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, - 0xffffffffffffffff, 0xb8dfffffffffffff, 0xfffffffbffffd7c0, 0xffbfffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffcfb, 0xffffffffffffffff, - 0xfffeffffffffffff, 0xffffffff027fffff, 0xbffffffffffe01ff, 0x000787ffffff00b6, - 0xffffffff07ff0000, 0xffffc3ffffffffff, 0xffffffffffffffff, 0x9ffffdff9fefffff, - 0xffffffffffff0000, 0xffffffffffffe7ff, 0x0003ffffffffffff, 0x243fffffffffffff - ], - r2: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 4, 32, 33, 34, 4, 4, 4, 4, 4, 35, 36, 37, 38, 39, 40, - 41, 42, 4, 4, 4, 4, 4, 4, 4, 4, 43, 44, 45, 46, 47, 4, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 4, 61, 4, 62, 63, 64, 65, 66, 4, 4, 4, 67, 4, 4, 4, 4, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 79, 80, 4, 81, 82, 83, 84, 85, 60, 60, 60, 60, 60, 60, 60, 60, 86, - 42, 87, 88, 89, 4, 90, 91, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 52, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 93, 94, 4, 4, 4, 4, 95, 96, 4, 97, 98, 4, 99, 100, 101, 62, 4, 102, 103, - 104, 4, 105, 106, 107, 4, 108, 109, 110, 4, 111, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 112, 113, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 103, 4, 114, - 115, 116, 97, 117, 4, 118, 4, 4, 119, 120, 121, 122, 123, 124, 4, 125, 126, 127, 128, - 129 - ], - r3: &[ - 0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff80000, - 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x5003ffcfb080799f, - 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf, - 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, - 0xe3fffdfffffddfff, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf, - 0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, - 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3fffffaffffff7d6, 0x00000000f3ff3f5f, - 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, - 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, - 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0003fe00e7ffffff, - 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, - 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x001fffff001fdfff, 0x000ddfff000fffff, - 0x000003ff308fffff, 0xffffffff03ff3800, 0x01ffffffffffffff, 0xffff07ffffffffff, - 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, - 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, - 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x00ffffffffffffff, - 0x3fffffffffffe3ff, 0xe7ffffffffff01ff, 0x07fffffffff70000, 0xfbffffffffffffff, - 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, - 0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, - 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff, - 0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff, - 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x1f3efffe000000e0, 0xfffffffee67fffff, - 0xf7ffffffffffffff, 0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, - 0x0000ffffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff, - 0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0xfffffffffffff9ff, - 0xff8000000000007c, 0x000000ffffffffff, 0xe8ffffff03ff003f, 0xffff3fffffffffff, - 0x1fffffff000fffff, 0x7fffffff03ff8001, 0x007fffffffffffff, 0xfc7fffff03ff3fff, - 0x007cffff38000007, 0xffff7f7f007e7e7e, 0xffff00fff7ffffff, 0x03ff37ffffffffff, - 0xffff000fffffffff, 0x0ffffffffffff87f, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, - 0xffffffffffffffdb, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff, - 0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0x0018ffff0000ffff, - 0xaa8a00000000e000, 0x1fffffffffffffff, 0x87fffffe03ff0000, 0xffffffc007fffffe, - 0x7fffffffffffffff, 0x000000001cfcfcfc - ], - r4: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - ], - r5: &[ - 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2, - 2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33, - 33, 34, 4, 4, 4, 4, 4, 4, 4, 35, 36, 4, 37, 2, 38, 3, 39, 40, 41, 2, 42, 43, 4, 44, 45, - 46, 47, 4, 4, 2, 48, 2, 49, 4, 4, 50, 51, 2, 52, 53, 54, 55, 4, 4, 4, 3, 4, 56, 57, 4, - 4, 58, 59, 60, 61, 62, 53, 4, 4, 4, 4, 63, 64, 65, 4, 66, 67, 68, 4, 4, 4, 4, 37, 4, 4, - 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 4, 2, 70, 2, 2, 2, 71, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 53, 73, 4, 74, 17, 75, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 4, 4, 2, 77, 78, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 80, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 81, 2, 2, 2, 2, - 2, 82, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 83, 84, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 85, 86, 4, 4, 87, 4, 4, 4, 4, 4, 4, 2, 88, 89, 90, 91, 92, 2, 2, 2, 2, 93, 94, 95, - 96, 97, 98, 4, 4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 102, 4, 4, 4, 103, 104, 4, 4, 4, 4, 4, 105, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 106, 2, 107, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 108, 109, 110, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 111, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 112, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 113, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 114, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 115, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - ], - r6: &[ - 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, - 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, - 0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, - 0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, - 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, - 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, - 0xc0ffffffffffffff, 0x873ffffffeeff06f, 0x1fffffff00000000, 0x000000001fffffff, - 0x0000007ffffffeff, 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, - 0x00000000000001ff, 0x0007ffffffffffff, 0x03ff00ffffffffff, 0xffff00801fffffff, - 0x000000000001ffff, 0x007fffff00000000, 0x8000ffc00000007f, 0x03ff01ffffff0000, - 0xffdfffffffffffff, 0x004fffffffff0070, 0x0000000017ff1e1f, 0x40fffffffffbffff, - 0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xfbedfdfffff99fef, 0x001f1fcfe081399f, - 0x00000000c3ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001, - 0x0000000003ff0011, 0x01ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe7ffffff, - 0xffffffff00000000, 0x800003ffffffffff, 0xfffffcff00000000, 0x0000001bfcffffff, - 0x7fffffffffffffff, 0xffffffffffff0080, 0x0000000023ffffff, 0xff7ffffffffffdff, - 0xfffc000003ff0001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0xfffffdbf03ff00ff, - 0x000003ff01fb7fff, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, - 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, 0xe0fffff803ff000f, - 0x000000000000ffff, 0xffffffffffff87ff, 0x00000000ffff80ff, 0x0000000b00000000, - 0x00ffffffffffffff, 0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, - 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff, - 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x3fff1fffffffffff, - 0x00000000000043ff, 0x03ffffffffffffff, 0x00000000007f001f, 0x0000000003ff0fff, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, - 0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff, 0x0000ffffffffffff - ], - }; - - pub fn XID_Continue(c: char) -> bool { - XID_Continue_table.lookup(c) - } - - const XID_Start_table: &super::BoolTrie = &super::BoolTrie { - r1: [ - 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, - 0x0000000000000000, 0xb8df000000000000, 0xfffffffbffffd740, 0xffbfffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff, - 0xfffeffffffffffff, 0xffffffff027fffff, 0x00000000000001ff, 0x000787ffffff0000, - 0xffffffff00000000, 0xfffec000000007ff, 0xffffffffffffffff, 0x9c00c060002fffff, - 0x0000fffffffd0000, 0xffffffffffffe000, 0x0002003fffffffff, 0x043007fffffffc00 - ], - r2: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 23, 25, 26, 27, 28, 29, 3, 30, 31, 32, 33, 34, 34, 34, 34, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 34, 34, 34, 34, 34, 34, 34, 34, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 3, 61, 62, 63, 64, 65, 66, 67, 68, 34, 34, 34, 3, 34, 34, - 34, 34, 69, 70, 71, 72, 3, 73, 74, 3, 75, 76, 77, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 78, - 79, 34, 80, 81, 82, 83, 84, 3, 3, 3, 3, 3, 3, 3, 3, 85, 42, 86, 87, 88, 34, 89, 90, 3, - 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 53, 3, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 92, 93, 34, 34, 34, 34, 94, - 95, 96, 91, 97, 34, 98, 99, 100, 48, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 34, 113, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 114, 115, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, - 116, 34, 117, 118, 119, 120, 121, 34, 122, 34, 34, 123, 124, 125, 126, 3, 127, 34, 128, - 129, 130, 131, 132 - ], - r3: &[ - 0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000, - 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000, - 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, - 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, - 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000, - 0x27fffffffffddfe0, 0xfc00000380704000, 0x2ffbfffffc7fffe0, 0x000000000000007f, - 0x0005fffffffffffe, 0x2005ffaffffff7d6, 0x00000000f000005f, 0x0000000000000001, - 0x00001ffffffffeff, 0x0000000000001f00, 0x800007ffffffffff, 0xffe1c0623c3f0000, - 0xffffffff00004003, 0xf7ffffffffff20bf, 0xffffffffffffffff, 0xffffffff3d7f3dff, - 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0000000007ffffff, - 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, - 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x0003ffff0003dfff, 0x0001dfff0003ffff, - 0x000fffffffffffff, 0x0000000010800000, 0xffffffff00000000, 0x01ffffffffffffff, - 0xffff05ffffffffff, 0x003fffffffffffff, 0x000000007fffffff, 0x001f3fffffff0000, - 0xffff0fffffffffff, 0x00000000000003ff, 0xffffffff007fffff, 0x00000000001fffff, - 0x0000008000000000, 0x000fffffffffffe0, 0x0000000000000fe0, 0xfc00c001fffffff8, - 0x0000003fffffffff, 0x0000000fffffffff, 0x3ffffffffc00e000, 0xe7ffffffffff01ff, - 0x046fde0000000000, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, - 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, - 0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff, 0xffffffff7fffffff, - 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, - 0x000000007f7f7f7f, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, - 0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x0000ffffffffffff, - 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, - 0xffffffff3fffffff, 0xfffffffcff800000, 0xfffffffffffff9ff, 0xff8000000000007c, - 0x00000007fffff7bb, 0x000ffffffffffffc, 0x68fc000000000000, 0xffff003ffffffc00, - 0x1fffffff0000007f, 0x0007fffffffffff0, 0x7c00ffdf00008000, 0x000001ffffffffff, - 0xc47fffff00000ff7, 0x3e62ffffffffffff, 0x001c07ff38000005, 0xffff7f7f007e7e7e, - 0xffff00fff7ffffff, 0x00000007ffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, - 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffa0f8007f, 0xffffffffffffffdb, - 0x0003ffffffffffff, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff, - 0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0xaa8a000000000000, - 0x1fffffffffffffff, 0x07fffffe00000000, 0xffffffc007fffffe, 0x7fffffff3fffffff, - 0x000000001cfcfcfc - ], - r4: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - ], - r5: &[ - 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, - 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, - 32, 15, 4, 4, 4, 4, 4, 4, 4, 33, 34, 4, 35, 36, 4, 37, 38, 39, 40, 41, 42, 43, 4, 44, - 20, 45, 46, 4, 4, 5, 47, 48, 49, 4, 4, 50, 51, 48, 52, 53, 4, 54, 4, 4, 4, 55, 4, 56, - 57, 4, 4, 58, 59, 60, 61, 62, 63, 4, 4, 4, 4, 64, 65, 66, 4, 67, 68, 69, 4, 4, 4, 4, 70, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 4, 2, 50, 2, 2, 2, 72, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 63, 20, 4, 74, 48, 75, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 4, 4, 2, 76, 77, 78, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 80, 2, - 2, 2, 2, 2, 81, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 82, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 84, 85, 86, 87, 88, 2, 2, 2, 2, 89, 90, - 91, 92, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 95, 96, 4, 4, 4, 4, 4, 55, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - ], - r6: &[ - 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, - 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, - 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, - 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, - 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, - 0x003ffffffeef0001, 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff, - 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff, - 0x0007ffffffffffff, 0xffff00801fffffff, 0x000000000000003f, 0x007fffff00000000, - 0x00fffffffffffff8, 0x0000fffffffffff8, 0x000001ffffff0000, 0x0000007ffffffff8, - 0x0047ffffffff0010, 0x0007fffffffffff8, 0x000000001400001e, 0x00000ffffffbffff, - 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000080000780, - 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, - 0x0000000000000010, 0x010007ffffffffff, 0x0000000007ffffff, 0x00000fffffffffff, - 0xffffffff00000000, 0x80000000ffffffff, 0xfffffcff00000000, 0x0000000a0001ffff, - 0x0407fffffffff801, 0xfffffffff0010000, 0x00000000200003ff, 0x01ffffffffffffff, - 0x00007ffffffffdff, 0xfffc000000000001, 0x000000000000ffff, 0x0001fffffffffb7f, - 0xfffffdbf00000040, 0x00000000010003ff, 0x0007ffff00000000, 0x0000000003ffffff, - 0x000000000000000f, 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, - 0x00000000000107ff, 0x00000000fff80000, 0x0000000b00000000, 0x00ffffffffffffff, - 0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x3f801fffffffffff, - 0x0000000000004000, 0x000000000000001f, 0x000000000000080f, 0x0af7fe96ffffffef, - 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, - 0x00000001ffffffff, 0x000000003fffffff - ], - }; - - pub fn XID_Start(c: char) -> bool { - XID_Start_table.lookup(c) - } - } pub(crate) mod property { - const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { - r1: &[ - 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 - ], - r2: &[ - 0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x000003000000c000 - ], - }; - - pub fn Pattern_White_Space(c: char) -> bool { - Pattern_White_Space_table.lookup(c) - } - const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 6de5d9e033..89894f7932 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -728,7 +728,7 @@ def generate_property_module(mod, grouped_categories, category_subset): yield "pub(crate) mod %s {\n" % mod for cat in sorted(category_subset): - if cat in ("Cc", "White_Space", "Pattern_White_Space"): + if cat in ("Cc", "White_Space"): generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat]) else: generator = generate_bool_trie("%s_table" % cat, grouped_categories[cat]) @@ -841,19 +841,18 @@ def main(): unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA)) load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data) - want_derived = {"XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase", + want_derived = {"Alphabetic", "Lowercase", "Uppercase", "Cased", "Case_Ignorable", "Grapheme_Extend"} derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) props = load_properties(get_path(UnicodeFiles.PROPS), - {"White_Space", "Join_Control", "Noncharacter_Code_Point", - "Pattern_White_Space"}) + {"White_Space", "Join_Control", "Noncharacter_Code_Point"}) # Category tables for (name, categories, category_subset) in ( ("general_category", unicode_data.general_categories, ["N", "Cc"]), ("derived_property", derived, want_derived), - ("property", props, ["White_Space", "Pattern_White_Space"]) + ("property", props, ["White_Space"]) ): for fragment in generate_property_module(name, categories, category_subset): buf.write(fragment) diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index 82a9e34c06..fff4ec716d 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] syntax_pos = { path = "../libsyntax_pos" } - +rustc_lexer = { path = "../librustc_lexer" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 985abaf2c1..f9c1be20b8 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -597,12 +597,11 @@ impl<'a> Parser<'a> { } } - /// Parses a word starting at the current position. A word is considered to - /// be an alphabetic character followed by any number of alphanumeric - /// characters. + /// Parses a word starting at the current position. A word is the same as + /// Rust identifier, except that it can't start with `_` character. fn word(&mut self) -> &'a str { let start = match self.cur.peek() { - Some(&(pos, c)) if c.is_xid_start() => { + Some(&(pos, c)) if c != '_' && rustc_lexer::is_id_start(c) => { self.cur.next(); pos } @@ -611,7 +610,7 @@ impl<'a> Parser<'a> { } }; while let Some(&(pos, c)) = self.cur.peek() { - if c.is_xid_continue() { + if rustc_lexer::is_id_continue(c) { self.cur.next(); } else { return &self.input[start..pos]; diff --git a/src/libproc_macro/Cargo.toml b/src/libproc_macro/Cargo.toml index b3d0ee94f0..187bdac800 100644 --- a/src/libproc_macro/Cargo.toml +++ b/src/libproc_macro/Cargo.toml @@ -6,3 +6,6 @@ edition = "2018" [lib] path = "lib.rs" + +[dependencies] +std = { path = "../libstd" } diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index 6052b4a4d4..5c543165bc 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -468,6 +468,14 @@ pub enum ProcMacro { } impl ProcMacro { + pub fn name(&self) -> &'static str { + match self { + ProcMacro::CustomDerive { trait_name, .. } => trait_name, + ProcMacro::Attr { name, .. } => name, + ProcMacro::Bang { name, ..} => name + } + } + pub const fn custom_derive( trait_name: &'static str, attributes: &'static [&'static str], diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index c0f7714ca2..d408fef751 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -19,12 +19,15 @@ #![feature(nll)] #![feature(staged_api)] +#![feature(allow_internal_unstable)] #![feature(const_fn)] +#![feature(decl_macro)] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] #![feature(mem_take)] #![feature(non_exhaustive)] +#![feature(rustc_attrs)] #![feature(specialization)] #![recursion_limit="256"] @@ -222,11 +225,10 @@ pub mod token_stream { /// /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. /// To quote `$` itself, use `$$`. -/// -/// This is a dummy macro, the actual implementation is in `quote::quote`.` #[unstable(feature = "proc_macro_quote", issue = "54722")] -#[macro_export] -macro_rules! quote { () => {} } +#[allow_internal_unstable(proc_macro_def_site)] +#[cfg_attr(not(bootstrap), rustc_builtin_macro)] +pub macro quote ($($t:tt)*) { /* compiler built-in */ } #[unstable(feature = "proc_macro_internals", issue = "27812")] #[doc(hidden)] diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs index e3d31b78f4..144e2d6bac 100644 --- a/src/libproc_macro/quote.rs +++ b/src/libproc_macro/quote.rs @@ -57,9 +57,9 @@ macro_rules! quote { } /// Quote a `TokenStream` into a `TokenStream`. -/// This is the actual `quote!()` proc macro. +/// This is the actual implementation of the `quote!()` proc macro. /// -/// It is manually loaded in `CStore::load_macro_untracked`. +/// It is loaded by the compiler in `register_builtin_macros`. #[unstable(feature = "proc_macro_quote", issue = "54722")] pub fn quote(stream: TokenStream) -> TokenStream { if stream.is_empty() { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 0222a3dde7..0834faf132 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -15,13 +15,12 @@ bitflags = "1.0" fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } jobserver = "0.1" -lazy_static = "1.0.0" num_cpus = "1.0" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.2.0" rustc-rayon-core = "0.2.0" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } @@ -31,8 +30,8 @@ rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" -parking_lot = "0.7" -byteorder = { version = "1.1", features = ["i128"]} +parking_lot = "0.9" +byteorder = { version = "1.3" } chalk-engine = { version = "0.9.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index e8c3914e69..d4fc1b1283 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -25,6 +25,16 @@ macro_rules! arena_types { [] adt_def: rustc::ty::AdtDef, [] steal_mir: rustc::ty::steal::Steal>, [] mir: rustc::mir::Body<$tcx>, + [] steal_promoted: rustc::ty::steal::Steal< + rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + > + >, + [] promoted: rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, [] vtable_method: Option<( @@ -84,6 +94,10 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] diagnostic_items: rustc_data_structures::fx::FxHashMap< + syntax::symbol::Symbol, + rustc::hir::def_id::DefId, + >, [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, [decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>, [few] lint_levels: rustc::lint::LintLevelMap, @@ -173,7 +187,7 @@ impl ArenaAllocatable for T {} unsafe trait ArenaField<'tcx>: Sized { /// Returns a specific arena to allocate from. - /// If None is returned, the DropArena will be used. + /// If `None` is returned, the `DropArena` will be used. fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena>; } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 7eea336cbb..e76a70350b 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1,4 +1,4 @@ -use errors::{Diagnostic, DiagnosticBuilder}; +use errors::Diagnostic; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -819,7 +819,7 @@ impl DepGraph { let handle = tcx.sess.diagnostic(); for diagnostic in diagnostics { - DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit(); + handle.emit_diagnostic(&diagnostic); } // Mark the node as green now that diagnostics are emitted diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index b3eee7c346..f6564f1fcd 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1,7 +1,8 @@ // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +syntax::register_diagnostics! { E0038: r##" Trait objects like `Box` can only be constructed when certain requirements are satisfied by the trait in question. @@ -39,7 +40,7 @@ Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing this restriction. -### Method references the `Self` type in its arguments or return type +### Method references the `Self` type in its parameters or return type This happens when a trait has a method like the following: @@ -1346,6 +1347,39 @@ struct Foo { ``` "##, +E0312: r##" +Reference's lifetime of borrowed content doesn't match the expected lifetime. + +Erroneous code example: + +```compile_fail,E0312 +pub fn opt_str<'a>(maybestr: &'a Option) -> &'static str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s // Invalid lifetime! + } +} +``` + +To fix this error, either lessen the expected lifetime or find a way to not have +to use this reference outside of its current scope (by running the code directly +in the same block for example?): + +``` +// In this case, we can fix the issue by switching from "static" lifetime to 'a +pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s // Ok! + } +} +``` +"##, + E0317: r##" This error occurs when an `if` expression without an `else` block is used in a context where a type other than `()` is expected, for example a `let` @@ -2088,7 +2122,6 @@ generator can be constructed. Erroneous code example: ```edition2018,compile-fail,E0698 -#![feature(async_await)] async fn bar() -> () {} async fn foo() { @@ -2101,7 +2134,6 @@ To fix this you must bind `T` to a concrete type such as `String` so that a generator can then be constructed: ```edition2018 -#![feature(async_await)] async fn bar() -> () {} async fn foo() { @@ -2185,11 +2217,7 @@ Examples of erroneous code: static X: u32 = 42; ``` "##, - -} - - -register_diagnostics! { +; // E0006, // merged with E0005 // E0101, // replaced with E0282 // E0102, // replaced with E0282 @@ -2207,8 +2235,8 @@ register_diagnostics! { // E0304, // expected signed integer constant // E0305, // expected constant E0311, // thing may not live long enough - E0312, // lifetime of reference outlives lifetime of borrowed content - E0313, // lifetime of borrowed pointer outlives lifetime of captured variable + E0313, // lifetime of borrowed pointer outlives lifetime of captured + // variable E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime E0316, // nested quantification of lifetimes @@ -2225,15 +2253,16 @@ register_diagnostics! { E0483, // lifetime of operand does not outlive the operation E0484, // reference is not valid at the time of borrow E0485, // automatically reference is not valid at the time of borrow - E0486, // type of expression contains references that are not valid during... + E0486, // type of expression contains references that are not valid during.. E0487, // unsafe use of destructor: destructor might be called while... E0488, // lifetime of variable does not enclose its declaration E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0495, // cannot infer an appropriate lifetime due to conflicting requirements + E0495, // cannot infer an appropriate lifetime due to conflicting + // requirements E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions - E0628, // generators cannot have explicit arguments + E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments E0637, // "'_" is not a valid lifetime bound E0657, // `impl Trait` can only capture lifetimes bound at the fn level @@ -2241,7 +2270,8 @@ register_diagnostics! { E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders E0697, // closures cannot be static E0707, // multiple elided lifetimes used in arguments of `async fn` - E0708, // `async` non-`move` closures with arguments are not currently supported + E0708, // `async` non-`move` closures with parameters are not currently + // supported E0709, // multiple different lifetimes used in arguments of `async fn` E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 22124d4ee4..1df09429e5 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -4,13 +4,12 @@ //! conflicts between multiple such attributes attached to the same //! item. - -use crate::ty::TyCtxt; -use crate::ty::query::Providers; - use crate::hir; use crate::hir::def_id::DefId; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::ty::TyCtxt; +use crate::ty::query::Providers; + use std::fmt::{self, Display}; use syntax::symbol::sym; use syntax_pos::Span; @@ -336,7 +335,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { fn is_c_like_enum(item: &hir::Item) -> bool { if let hir::ItemKind::Enum(ref def, _) = item.node { for variant in &def.variants { - match variant.node.data { + match variant.data { hir::VariantData::Unit(..) => { /* continue */ } _ => { return false; } } diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index f83fbcdc26..f7d31ca06e 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -1,15 +1,17 @@ +use self::Namespace::*; + use crate::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::hir; +use crate::ty; use crate::util::nodemap::DefIdMap; + use syntax::ast; use syntax::ext::base::MacroKind; use syntax::ast::NodeId; use syntax_pos::Span; use rustc_macros::HashStable; -use crate::hir; -use crate::ty; -use std::fmt::Debug; -use self::Namespace::*; +use std::fmt::Debug; /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] @@ -115,7 +117,7 @@ impl DefKind { } } - /// An English article for the def. + /// Gets an English article for the definition. pub fn article(&self) -> &'static str { match *self { DefKind::AssocTy @@ -134,18 +136,22 @@ pub enum Res { Def(DefKind, DefId), // Type namespace + PrimTy(hir::PrimTy), SelfTy(Option /* trait */, Option /* impl */), ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` // Value namespace + SelfCtor(DefId /* impl */), // `DefId` refers to the impl Local(Id), // Macro namespace + NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` // All namespaces + Err, } @@ -330,7 +336,7 @@ impl NonMacroAttrKind { } impl Res { - /// Return the `DefId` of this `Def` if it has an id, else panic. + /// Return the `DefId` of this `Def` if it has an ID, else panic. pub fn def_id(&self) -> DefId where Id: Debug, @@ -340,7 +346,7 @@ impl Res { }) } - /// Return `Some(..)` with the `DefId` of this `Res` if it has a id, else `None`. + /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`. pub fn opt_def_id(&self) -> Option { match *self { Res::Def(_, id) => Some(id), @@ -379,7 +385,7 @@ impl Res { } } - /// An English article for the res. + /// Gets an English article for the `Res`. pub fn article(&self) -> &'static str { match *self { Res::Def(kind, _) => kind.article(), diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index c0a661908a..d0bdc14913 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -1,5 +1,4 @@ use crate::ty::{self, TyCtxt}; -use crate::hir::map::definitions::FIRST_FREE_DEF_INDEX; use rustc_data_structures::indexed_vec::Idx; use std::fmt; use std::u32; @@ -12,7 +11,7 @@ newtype_index! { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum CrateNum { - /// A special CrateNum that we use for the tcx.rcache when decoding from + /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from /// the incr. comp. cache. ReservedForIncrCompCache, Index(CrateId), @@ -27,11 +26,10 @@ impl ::std::fmt::Debug for CrateNum { } } -/// Item definitions in the currently-compiled crate would have the CrateNum -/// LOCAL_CRATE in their DefId. +/// Item definitions in the currently-compiled crate would have the `CrateNum` +/// `LOCAL_CRATE` in their `DefId`. pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); - impl Idx for CrateNum { #[inline] fn new(value: usize) -> Self { @@ -102,31 +100,6 @@ newtype_index! { } } -impl DefIndex { - // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This - // function maps the index of the macro within the crate (which is also the - // index of the macro in the CrateMetadata::proc_macros array) to the - // corresponding DefIndex. - pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex { - // DefIndex for proc macros start from FIRST_FREE_DEF_INDEX, - // because the first FIRST_FREE_DEF_INDEX indexes are reserved - // for internal use. - let def_index = DefIndex::from( - proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX) - .expect("integer overflow adding `proc_macro_index`")); - assert!(def_index != CRATE_DEF_INDEX); - def_index - } - - // This function is the reverse of from_proc_macro_index() above. - pub fn to_proc_macro_index(self: DefIndex) -> usize { - self.index().checked_sub(FIRST_FREE_DEF_INDEX) - .unwrap_or_else(|| { - bug!("using local index {:?} as proc-macro index", self) - }) - } -} - impl rustc_serialize::UseSpecializedEncodable for DefIndex {} impl rustc_serialize::UseSpecializedDecodable for DefIndex {} diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index b5c760bc9a..1f125de967 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -31,11 +31,13 @@ //! This order consistency is required in a few places in rustc, for //! example generator inference, and possibly also HIR borrowck. -use syntax::ast::{Ident, Name, Attribute}; -use syntax_pos::Span; +use super::itemlikevisit::DeepVisitor; + use crate::hir::*; use crate::hir::map::Map; -use super::itemlikevisit::DeepVisitor; + +use syntax::ast::{Ident, Name, Attribute}; +use syntax_pos::Span; #[derive(Copy, Clone)] pub enum FnKind<'a> { @@ -139,7 +141,7 @@ impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> { /// explicitly, you need to override each method. (And you also need /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) -pub trait Visitor<'v> : Sized { +pub trait Visitor<'v>: Sized { /////////////////////////////////////////////////////////////////////////// // Nested items. @@ -162,8 +164,8 @@ pub trait Visitor<'v> : Sized { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>; /// Invoked when a nested item is encountered. By default does - /// nothing unless you override `nested_visit_map` to return - /// `Some(_)`, in which case it will walk the item. **You probably + /// nothing unless you override `nested_visit_map` to return other than + /// `None`, in which case it will walk the item. **You probably /// don't want to override this method** -- instead, override /// `nested_visit_map` or use the "shallow" or "deep" visit /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only @@ -201,8 +203,8 @@ pub trait Visitor<'v> : Sized { /// Invoked to visit the body of a function, method or closure. Like /// visit_nested_item, does nothing by default unless you override - /// `nested_visit_map` to return `Some(_)`, in which case it will walk the - /// body. + /// `nested_visit_map` to return other htan `None`, in which case it will walk + /// the body. fn visit_nested_body(&mut self, id: BodyId) { let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); if let Some(body) = opt_body { @@ -210,8 +212,8 @@ pub trait Visitor<'v> : Sized { } } - fn visit_arg(&mut self, arg: &'v Arg) { - walk_arg(self, arg) + fn visit_param(&mut self, param: &'v Param) { + walk_param(self, param) } /// Visits the top-level item and (optionally) nested items / impl items. See @@ -400,7 +402,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id } pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { - walk_list!(visitor, visit_arg, &body.arguments); + walk_list!(visitor, visit_param, &body.params); visitor.visit_expr(&body.value); } @@ -433,6 +435,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime LifetimeName::Static | LifetimeName::Error | LifetimeName::Implicit | + LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => {} } } @@ -453,10 +456,10 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) } -pub fn walk_arg<'v, V: Visitor<'v>>(visitor: &mut V, arg: &'v Arg) { - visitor.visit_id(arg.hir_id); - visitor.visit_pat(&arg.pat); - walk_list!(visitor, visit_attribute, &arg.attrs); +pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param) { + visitor.visit_id(param.hir_id); + visitor.visit_pat(¶m.pat); + walk_list!(visitor, visit_attribute, ¶m.attrs); } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { @@ -577,15 +580,15 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant, generics: &'v Generics, parent_item_id: HirId) { - visitor.visit_ident(variant.node.ident); - visitor.visit_id(variant.node.id); - visitor.visit_variant_data(&variant.node.data, - variant.node.ident.name, + visitor.visit_ident(variant.ident); + visitor.visit_id(variant.id); + visitor.visit_variant_data(&variant.data, + variant.ident.name, generics, parent_item_id, variant.span); - walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); + walk_list!(visitor, visit_anon_const, &variant.disr_expr); + walk_list!(visitor, visit_attribute, &variant.attrs); } pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { @@ -602,7 +605,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_lifetime(lifetime); visitor.visit_ty(&mutable_type.ty) } - TyKind::Never => {}, + TyKind::Never => {} TyKind::Tup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } @@ -704,11 +707,12 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatKind::Struct(ref qpath, ref fields, _) => { visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); for field in fields { - visitor.visit_id(field.node.hir_id); - visitor.visit_ident(field.node.ident); - visitor.visit_pat(&field.node.pat) + visitor.visit_id(field.hir_id); + visitor.visit_ident(field.ident); + visitor.visit_pat(&field.pat) } } + PatKind::Or(ref pats) => walk_list!(visitor, visit_pat, pats), PatKind::Tuple(ref tuple_elements, _) => { walk_list!(visitor, visit_pat, tuple_elements); } diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 35b1812458..39dd46c2d2 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -1,7 +1,7 @@ use super::{Item, ImplItem, TraitItem}; use super::intravisit::Visitor; -/// The "item-like visitor" visitor defines only the top-level methods +/// The "item-like visitor" defines only the top-level methods /// that can be invoked by `Crate::visit_all_item_likes()`. Whether /// this trait is the right one to implement will depend on the /// overall pattern you need. Here are the three available patterns, @@ -18,11 +18,11 @@ use super::intravisit::Visitor; /// an item, but don't care about how item-like things are nested /// within one another. /// - Example: Examine each expression to look for its type and do some check or other. -/// - How: Implement `intravisit::Visitor` and use -/// `tcx.hir().krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within -/// your `intravisit::Visitor` impl, implement methods like -/// `visit_expr()`; don't forget to invoke -/// `intravisit::walk_visit_expr()` to keep walking the subparts. +/// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method +/// to return `NestedVisitorMap::OnlyBodies` and use +/// `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within +/// your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget +/// to invoke `intravisit::walk_expr()` to keep walking the subparts). /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Integrates well into dependency tracking. /// - Con: Don't get information about nesting between items @@ -30,10 +30,9 @@ use super::intravisit::Visitor; /// item-like things. /// - Example: Lifetime resolution, which wants to bring lifetimes declared on the /// impl into scope while visiting the impl-items, and then back out again. -/// - How: Implement `intravisit::Visitor` and override the -/// `nested_visit_map()` methods to return -/// `NestedVisitorMap::All`. Walk your crate with -/// `intravisit::walk_crate()` invoked on `tcx.hir().krate()`. +/// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method +/// to return `NestedVisitorMap::All`. Walk your crate with `intravisit::walk_crate()` +/// invoked on `tcx.hir().krate()`. /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Preserves nesting information /// - Con: Does not integrate well into dependency tracking. @@ -79,7 +78,7 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> } } -/// A parallel variant of ItemLikeVisitor +/// A parallel variant of `ItemLikeVisitor`. pub trait ParItemLikeVisitor<'hir> { fn visit_item(&self, item: &'hir Item); fn visit_trait_item(&self, trait_item: &'hir TraitItem); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index fe69c9e634..2ad5424755 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -67,19 +67,19 @@ use syntax::errors; use syntax::ext::base::SpecialDerives; use syntax::ext::hygiene::ExpnId; use syntax::print::pprust; -use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned}; +use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Token}; use syntax::visit::{self, Visitor}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { crate_root: Option, - /// Used to assign ids to HIR nodes that do not directly correspond to an AST node. + /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. sess: &'a Session, cstore: &'a dyn CrateStore, @@ -126,7 +126,7 @@ pub struct LoweringContext<'a> { /// lifetime definitions in the corresponding impl or function generics. lifetimes_to_define: Vec<(Span, ParamName)>, - /// Whether or not in-band lifetimes are being collected. This is used to + /// `true` if in-band lifetimes are being collected. This is used to /// indicate whether or not we're in a place where new lifetimes will result /// in in-band lifetime definitions, such a function or an impl header, /// including implicit lifetimes from `impl_header_lifetime_elision`. @@ -136,7 +136,10 @@ pub struct LoweringContext<'a> { /// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked /// against this list to see if it is already in-scope, or if a definition /// needs to be created for it. - in_scope_lifetimes: Vec, + /// + /// We always store a `modern()` version of the param-name in this + /// vector. + in_scope_lifetimes: Vec, current_module: NodeId, @@ -151,13 +154,13 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Obtain resolution for a `NodeId` with a single resolution. + /// Obtains resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; - /// Obtain per-namespace resolutions for `use` statement with the given `NoedId`. + /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. fn get_import_res(&mut self, id: NodeId) -> PerNS>>; - /// Obtain resolution for a label with the given `NodeId`. + /// Obtains resolution for a label with the given `NodeId`. fn get_label_res(&mut self, id: NodeId) -> Option; /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. @@ -319,7 +322,7 @@ enum ParenthesizedGenericArgs { /// `resolve_lifetime` module. Often we "fallthrough" to that code by generating /// an "elided" or "underscore" lifetime name. In the future, we probably want to move /// everything into HIR lowering. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] enum AnonymousLifetimeMode { /// For **Modern** cases, create a new anonymous region parameter /// and reference that. @@ -337,49 +340,6 @@ enum AnonymousLifetimeMode { /// Pass responsibility to `resolve_lifetime` code for all cases. PassThrough, - - /// Used in the return types of `async fn` where there exists - /// exactly one argument-position elided lifetime. - /// - /// In `async fn`, we lower the arguments types using the `CreateParameter` - /// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name. - /// If any corresponding elided lifetimes appear in the output, we need to - /// replace them with references to the fresh name assigned to the corresponding - /// elided lifetime in the arguments. - /// - /// For **Modern cases**, replace the anonymous parameter with a - /// reference to a specific freshly-named lifetime that was - /// introduced in argument - /// - /// For **Dyn Bound** cases, pass responsibility to - /// `resole_lifetime` code. - Replace(LtReplacement), -} - -/// The type of elided lifetime replacement to perform on `async fn` return types. -#[derive(Copy, Clone)] -enum LtReplacement { - /// Fresh name introduced by the single non-dyn elided lifetime - /// in the arguments of the async fn. - Some(ParamName), - - /// There is no single non-dyn elided lifetime because no lifetimes - /// appeared in the arguments. - NoLifetimes, - - /// There is no single non-dyn elided lifetime because multiple - /// lifetimes appeared in the arguments. - MultipleLifetimes, -} - -/// Calculates the `LtReplacement` to use for elided lifetimes in the return -/// type based on the fresh elided lifetimes introduced in argument position. -fn get_elided_lt_replacement(arg_position_lifetimes: &[(Span, ParamName)]) -> LtReplacement { - match arg_position_lifetimes { - [] => LtReplacement::NoLifetimes, - [(_span, param)] => LtReplacement::Some(*param), - _ => LtReplacement::MultipleLifetimes, - } } struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> } @@ -465,19 +425,44 @@ impl<'a> LoweringContext<'a> { impl<'tcx, 'interner> Visitor<'tcx> for MiscCollector<'tcx, 'interner> { fn visit_pat(&mut self, p: &'tcx Pat) { - match p.node { + if let PatKind::Paren(..) | PatKind::Rest = p.node { // Doesn't generate a HIR node - PatKind::Paren(..) | PatKind::Rest => {}, - _ => { - if let Some(owner) = self.hir_id_owner { - self.lctx.lower_node_id_with_owner(p.id, owner); - } - } - }; + } else if let Some(owner) = self.hir_id_owner { + self.lctx.lower_node_id_with_owner(p.id, owner); + } visit::walk_pat(self, p) } + // HACK(or_patterns; Centril | dlrobertson): Avoid creating + // HIR nodes for `PatKind::Or` for the top level of a `ast::Arm`. + // This is a temporary hack that should go away once we push down + // `arm.pats: HirVec>` -> `arm.pat: P` to HIR. // Centril + fn visit_arm(&mut self, arm: &'tcx Arm) { + match &arm.pat.node { + PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), + _ => self.visit_pat(&arm.pat), + } + walk_list!(self, visit_expr, &arm.guard); + self.visit_expr(&arm.body); + walk_list!(self, visit_attribute, &arm.attrs); + } + + // HACK(or_patterns; Centril | dlrobertson): Same as above. // Centril + fn visit_expr(&mut self, e: &'tcx Expr) { + if let ExprKind::Let(pat, scrutinee) = &e.node { + walk_list!(self, visit_attribute, e.attrs.iter()); + match &pat.node { + PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), + _ => self.visit_pat(&pat), + } + self.visit_expr(scrutinee); + self.visit_expr_post(e); + return; + } + visit::walk_expr(self, e) + } + fn visit_item(&mut self, item: &'tcx Item) { let hir_id = self.lctx.allocate_hir_id_counter(item.id); @@ -550,12 +535,12 @@ impl<'a> LoweringContext<'a> { &f.generic_params ); // Mirrors visit::walk_fn_decl - for argument in &f.decl.inputs { + for parameter in &f.decl.inputs { // We don't lower the ids of argument patterns self.with_hir_id_owner(None, |this| { - this.visit_pat(&argument.pat); + this.visit_pat(¶meter.pat); }); - self.visit_ty(&argument.ty) + self.visit_ty(¶meter.ty) } self.visit_fn_ret_ty(&f.decl.output) } @@ -714,7 +699,7 @@ impl<'a> LoweringContext<'a> { fn lower_res(&mut self, res: Res) -> Res { res.map_id(|id| { self.lower_node_id_generic(id, |_| { - panic!("expected node_id to be lowered already for res {:#?}", res) + panic!("expected `NodeId` to be lowered already for res {:#?}", res); }) }) } @@ -744,10 +729,9 @@ impl<'a> LoweringContext<'a> { span: Span, allow_internal_unstable: Option>, ) -> Span { - span.fresh_expansion(ExpnId::root(), ExpnInfo { - def_site: span, + span.fresh_expansion(ExpnData { allow_internal_unstable, - ..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition()) + ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition()) }) } @@ -756,10 +740,16 @@ impl<'a> LoweringContext<'a> { anonymous_lifetime_mode: AnonymousLifetimeMode, op: impl FnOnce(&mut Self) -> R, ) -> R { + debug!( + "with_anonymous_lifetime_mode(anonymous_lifetime_mode={:?})", + anonymous_lifetime_mode, + ); let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; self.anonymous_lifetime_mode = anonymous_lifetime_mode; let result = op(self); self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; + debug!("with_anonymous_lifetime_mode: restoring anonymous_lifetime_mode={:?}", + old_anonymous_lifetime_mode); result } @@ -770,7 +760,7 @@ impl<'a> LoweringContext<'a> { /// /// Presuming that in-band lifetimes are enabled, then /// `self.anonymous_lifetime_mode` will be updated to match the - /// argument while `f` is running (and restored afterwards). + /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, parent_id: DefId, @@ -865,7 +855,7 @@ impl<'a> LoweringContext<'a> { return; } - if self.in_scope_lifetimes.contains(&ident.modern()) { + if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) { return; } @@ -883,7 +873,7 @@ impl<'a> LoweringContext<'a> { /// header, we convert it to an in-band lifetime. fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName { assert!(self.is_collecting_in_band_lifetimes); - let index = self.lifetimes_to_define.len(); + let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len(); let hir_name = ParamName::Fresh(index); self.lifetimes_to_define.push((span, hir_name)); hir_name @@ -899,7 +889,7 @@ impl<'a> LoweringContext<'a> { { let old_len = self.in_scope_lifetimes.len(); let lt_def_names = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param.ident.modern()), + GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -915,7 +905,7 @@ impl<'a> LoweringContext<'a> { /// /// Presuming that in-band lifetimes are enabled, then /// `self.anonymous_lifetime_mode` will be updated to match the - /// argument while `f` is running (and restored afterwards). + /// parameter while `f` is running (and restored afterwards). fn add_in_band_defs( &mut self, generics: &Generics, @@ -1074,13 +1064,14 @@ impl<'a> LoweringContext<'a> { /// ``` /// /// returns a `hir::TypeBinding` representing `Item`. - fn lower_assoc_ty_constraint(&mut self, - c: &AssocTyConstraint, - itctx: ImplTraitContext<'_>) - -> hir::TypeBinding { - debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx); + fn lower_assoc_ty_constraint( + &mut self, + constraint: &AssocTyConstraint, + itctx: ImplTraitContext<'_>, + ) -> hir::TypeBinding { + debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - let kind = match c.kind { + let kind = match constraint.kind { AssocTyConstraintKind::Equality { ref ty } => hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }, @@ -1114,7 +1105,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, ImplTraitContext::OpaqueTy(None)), - // We are in the argument position, but not within a dyn type: + // We are in the parameter position, but not within a dyn type: // // fn foo(x: impl Iterator) // @@ -1135,7 +1126,7 @@ impl<'a> LoweringContext<'a> { impl_trait_node_id, DefPathData::ImplTrait, ExpnId::root(), - DUMMY_SP + constraint.span, ); self.with_dyn_type_scope(false, |this| { @@ -1143,7 +1134,7 @@ impl<'a> LoweringContext<'a> { &Ty { id: this.sess.next_node_id(), node: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: DUMMY_SP, + span: constraint.span, }, itctx, ); @@ -1165,10 +1156,10 @@ impl<'a> LoweringContext<'a> { }; hir::TypeBinding { - hir_id: self.lower_node_id(c.id), - ident: c.ident, + hir_id: self.lower_node_id(constraint.id), + ident: constraint.ident, kind, - span: c.span, + span: constraint.span, } } @@ -1238,7 +1229,7 @@ impl<'a> LoweringContext<'a> { unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, decl: this.lower_fn_decl(&f.decl, None, false, None), - arg_names: this.lower_fn_args_to_names(&f.decl), + param_names: this.lower_fn_params_to_names(&f.decl), })) }, ) @@ -1264,7 +1255,7 @@ impl<'a> LoweringContext<'a> { P(hir::Path { res, segments: hir_vec![hir::PathSegment::from_ident( - Ident::with_empty_ctxt(kw::SelfUpper) + Ident::with_dummy_span(kw::SelfUpper) )], span: t.span, }), @@ -1325,7 +1316,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::Universal(in_band_ty_params), ); // Set the name to `impl Bound1 + Bound2`. - let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span); + let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); in_band_ty_params.push(hir::GenericParam { hir_id: self.lower_node_id(def_node_id), name: ParamName::Plain(ident), @@ -1373,7 +1364,7 @@ impl<'a> LoweringContext<'a> { } } } - TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now."), + TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"), TyKind::CVarArgs => { // Create the implicit lifetime of the "spoofed" `VaListImpl`. let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); @@ -1396,6 +1387,13 @@ impl<'a> LoweringContext<'a> { opaque_ty_node_id: NodeId, lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds, ) -> hir::TyKind { + debug!( + "lower_opaque_impl_trait(fn_def_id={:?}, opaque_ty_node_id={:?}, span={:?})", + fn_def_id, + opaque_ty_node_id, + span, + ); + // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop // desugaring that explicitly states that we don't want to track that. @@ -1423,6 +1421,14 @@ impl<'a> LoweringContext<'a> { &hir_bounds, ); + debug!( + "lower_opaque_impl_trait: lifetimes={:#?}", lifetimes, + ); + + debug!( + "lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs, + ); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let opaque_ty_item = hir::OpaqueTy { generics: hir::Generics { @@ -1438,7 +1444,7 @@ impl<'a> LoweringContext<'a> { origin: hir::OpaqueTyOrigin::FnReturn, }; - trace!("exist ty from impl trait def-index: {:#?}", opaque_ty_def_index); + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); let opaque_ty_id = lctx.generate_opaque_type( opaque_ty_node_id, opaque_ty_item, @@ -1486,6 +1492,13 @@ impl<'a> LoweringContext<'a> { parent_index: DefIndex, bounds: &hir::GenericBounds, ) -> (HirVec, HirVec) { + debug!( + "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ + parent_index={:?}, \ + bounds={:#?})", + opaque_ty_id, parent_index, bounds, + ); + // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. @@ -1573,6 +1586,11 @@ impl<'a> LoweringContext<'a> { } } hir::LifetimeName::Param(_) => lifetime.name, + + // Refers to some other lifetime that is "in + // scope" within the type. + hir::LifetimeName::ImplicitObjectLifetimeDefault => return, + hir::LifetimeName::Error | hir::LifetimeName::Static => return, }; @@ -1598,7 +1616,7 @@ impl<'a> LoweringContext<'a> { let (name, kind) = match name { hir::LifetimeName::Underscore => ( - hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)), + hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)), hir::LifetimeParamKind::Elided, ), hir::LifetimeName::Param(param_name) => ( @@ -1875,10 +1893,13 @@ impl<'a> LoweringContext<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` if data.inputs.len() > 0 { + let split = snippet.find('(').unwrap(); + let trait_name = &snippet[0..split]; + let args = &snippet[split + 1 .. snippet.len() - 1]; err.span_suggestion( data.span, "use angle brackets instead", - format!("<{}>", &snippet[1..snippet.len() - 1]), + format!("{}<{}>", trait_name, args), Applicability::MaybeIncorrect, ); } @@ -1953,8 +1974,7 @@ impl<'a> LoweringContext<'a> { err.emit(); } AnonymousLifetimeMode::PassThrough | - AnonymousLifetimeMode::ReportError | - AnonymousLifetimeMode::Replace(_) => { + AnonymousLifetimeMode::ReportError => { self.sess.buffer_lint_with_diagnostic( ELIDED_LIFETIMES_IN_PATHS, CRATE_NODE_ID, @@ -2043,7 +2063,7 @@ impl<'a> LoweringContext<'a> { bindings: hir_vec![ hir::TypeBinding { hir_id: this.next_id(), - ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), kind: hir::TypeBindingKind::Equality { ty: output .as_ref() @@ -2101,12 +2121,12 @@ impl<'a> LoweringContext<'a> { } } - fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { + fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { decl.inputs .iter() - .map(|arg| match arg.pat.node { + .map(|param| match param.pat.node { PatKind::Ident(_, ident, _) => ident, - _ => Ident::new(kw::Invalid, arg.pat.span), + _ => Ident::new(kw::Invalid, param.pat.span), }) .collect() } @@ -2141,31 +2161,24 @@ impl<'a> LoweringContext<'a> { // Remember how many lifetimes were already around so that we can // only look at the lifetime parameters introduced by the arguments. - let lifetime_count_before_args = self.lifetimes_to_define.len(); let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| { decl.inputs .iter() - .map(|arg| { + .map(|param| { if let Some((_, ibty)) = &mut in_band_ty_params { - this.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty)) + this.lower_ty_direct(¶m.ty, ImplTraitContext::Universal(ibty)) } else { - this.lower_ty_direct(&arg.ty, ImplTraitContext::disallowed()) + this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed()) } }) .collect::>() }); let output = if let Some(ret_id) = make_ret_async { - // Calculate the `LtReplacement` to use for any return-position elided - // lifetimes based on the elided lifetime parameters introduced in the args. - let lt_replacement = get_elided_lt_replacement( - &self.lifetimes_to_define[lifetime_count_before_args..] - ); self.lower_async_fn_ret_ty( &decl.output, in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0, ret_id, - lt_replacement, ) } else { match decl.output { @@ -2220,7 +2233,7 @@ impl<'a> LoweringContext<'a> { // // type OpaqueTy = impl Future; // - // `inputs`: lowered types of arguments to the function (used to collect lifetimes) + // `inputs`: lowered types of parameters to the function (used to collect lifetimes) // `output`: unlowered output type (`T` in `-> T`) // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created @@ -2230,8 +2243,15 @@ impl<'a> LoweringContext<'a> { output: &FunctionRetTy, fn_def_id: DefId, opaque_ty_node_id: NodeId, - elided_lt_replacement: LtReplacement, ) -> hir::FunctionRetTy { + debug!( + "lower_async_fn_ret_ty(\ + output={:?}, \ + fn_def_id={:?}, \ + opaque_ty_node_id={:?})", + output, fn_def_id, opaque_ty_node_id, + ); + let span = output.span(); let opaque_ty_span = self.mark_span_with_reason( @@ -2248,9 +2268,65 @@ impl<'a> LoweringContext<'a> { self.allocate_hir_id_counter(opaque_ty_node_id); + // When we create the opaque type for this async fn, it is going to have + // to capture all the lifetimes involved in the signature (including in the + // return type). This is done by introducing lifetime parameters for: + // + // - all the explicitly declared lifetimes from the impl and function itself; + // - all the elided lifetimes in the fn arguments; + // - all the elided lifetimes in the return type. + // + // So for example in this snippet: + // + // ```rust + // impl<'a> Foo<'a> { + // async fn bar<'b>(&self, x: &'b Vec, y: &str) -> &u32 { + // // ^ '0 ^ '1 ^ '2 + // // elided lifetimes used below + // } + // } + // ``` + // + // we would create an opaque type like: + // + // ``` + // type Bar<'a, 'b, '0, '1, '2> = impl Future; + // ``` + // + // and we would then desugar `bar` to the equivalent of: + // + // ```rust + // impl<'a> Foo<'a> { + // fn bar<'b, '0, '1>(&'0 self, x: &'b Vec, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_> + // } + // ``` + // + // Note that the final parameter to `Bar` is `'_`, not `'2` -- + // this is because the elided lifetimes from the return type + // should be figured out using the ordinary elision rules, and + // this desugaring achieves that. + // + // The variable `input_lifetimes_count` tracks the number of + // lifetime parameters to the opaque type *not counting* those + // lifetimes elided in the return type. This includes those + // that are explicitly declared (`in_scope_lifetimes`) and + // those elided lifetimes we found in the arguments (current + // content of `lifetimes_to_define`). Next, we will process + // the return type, which will cause `lifetimes_to_define` to + // grow. + let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); + let (opaque_ty_id, lifetime_params) = self.with_hir_id_owner(opaque_ty_node_id, |this| { + // We have to be careful to get elision right here. The + // idea is that we create a lifetime parameter for each + // lifetime in the return type. So, given a return type + // like `async fn foo(..) -> &[&u32]`, we lower to `impl + // Future`. + // + // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and + // hence the elision takes place at the fn site. let future_bound = this.with_anonymous_lifetime_mode( - AnonymousLifetimeMode::Replace(elided_lt_replacement), + AnonymousLifetimeMode::CreateParameter, |this| this.lower_async_fn_output_type_to_future_bound( output, fn_def_id, @@ -2258,6 +2334,8 @@ impl<'a> LoweringContext<'a> { ), ); + debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + // Calculate all the lifetimes that should be captured // by the opaque type. This should include all in-scope // lifetime parameters, including those defined in-band. @@ -2267,10 +2345,14 @@ impl<'a> LoweringContext<'a> { let lifetime_params: Vec<(Span, ParamName)> = this.in_scope_lifetimes .iter().cloned() - .map(|ident| (ident.span, ParamName::Plain(ident))) + .map(|name| (name.ident().span, name)) .chain(this.lifetimes_to_define.iter().cloned()) .collect(); + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); + let generic_params = lifetime_params .iter().cloned() @@ -2304,19 +2386,52 @@ impl<'a> LoweringContext<'a> { (opaque_ty_id, lifetime_params) }); - let generic_args = - lifetime_params - .iter().cloned() - .map(|(span, hir_name)| { - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span, - name: hir::LifetimeName::Param(hir_name), - }) + // As documented above on the variable + // `input_lifetimes_count`, we need to create the lifetime + // arguments to our opaque type. Continuing with our example, + // we're creating the type arguments for the return type: + // + // ``` + // Bar<'a, 'b, '0, '1, '_> + // ``` + // + // For the "input" lifetime parameters, we wish to create + // references to the parameters themselves, including the + // "implicit" ones created from parameter types (`'a`, `'b`, + // '`0`, `'1`). + // + // For the "output" lifetime parameters, we just want to + // generate `'_`. + let mut generic_args: Vec<_> = + lifetime_params[..input_lifetimes_count] + .iter() + .map(|&(span, hir_name)| { + // Input lifetime like `'a` or `'1`: + GenericArg::Lifetime(hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::Param(hir_name), }) - .collect(); + }) + .collect(); + generic_args.extend( + lifetime_params[input_lifetimes_count..] + .iter() + .map(|&(span, _)| { + // Output lifetime like `'_`. + GenericArg::Lifetime(hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::Implicit, + }) + }) + ); - let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args); + // Create the `Foo<...>` refernece itself. Note that the `type + // Foo = impl Trait` is, internally, created as a child of the + // async fn, so the *type parameters* are inherited. It's + // only the lifetime parameters that we must supply. + let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into()); hir::FunctionRetTy::Return(P(hir::Ty { node: opaque_ty_ref, @@ -2350,7 +2465,7 @@ impl<'a> LoweringContext<'a> { let future_params = P(hir::GenericArgs { args: hir_vec![], bindings: hir_vec![hir::TypeBinding { - ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), kind: hir::TypeBindingKind::Equality { ty: output_ty, }, @@ -2412,11 +2527,6 @@ impl<'a> LoweringContext<'a> { } AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span), - - AnonymousLifetimeMode::Replace(replacement) => { - let hir_id = self.lower_node_id(l.id); - self.replace_elided_lifetime(hir_id, span, replacement) - } }, ident => { self.maybe_collect_in_band_lifetime(ident); @@ -2439,39 +2549,6 @@ impl<'a> LoweringContext<'a> { } } - /// Replace a return-position elided lifetime with the elided lifetime - /// from the arguments. - fn replace_elided_lifetime( - &mut self, - hir_id: hir::HirId, - span: Span, - replacement: LtReplacement, - ) -> hir::Lifetime { - let multiple_or_none = match replacement { - LtReplacement::Some(name) => { - return hir::Lifetime { - hir_id, - span, - name: hir::LifetimeName::Param(name), - }; - } - LtReplacement::MultipleLifetimes => "multiple", - LtReplacement::NoLifetimes => "none", - }; - - let mut err = crate::middle::resolve_lifetime::report_missing_lifetime_specifiers( - self.sess, - span, - 1, - ); - err.note(&format!( - "return-position elided lifetimes require exactly one \ - input-position elided lifetime, found {}.", multiple_or_none)); - err.emit(); - - hir::Lifetime { hir_id, span, name: hir::LifetimeName::Error } - } - fn lower_generic_params( &mut self, params: &[GenericParam], @@ -2507,6 +2584,12 @@ impl<'a> LoweringContext<'a> { hir::LifetimeName::Implicit | hir::LifetimeName::Underscore | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), + hir::LifetimeName::ImplicitObjectLifetimeDefault => { + span_bug!( + param.ident.span, + "object-lifetime-default should not occur here", + ); + } hir::LifetimeName::Error => ParamName::Error, }; @@ -2519,15 +2602,6 @@ impl<'a> LoweringContext<'a> { (param_name, kind) } GenericParamKind::Type { ref default, .. } => { - // Don't expose `Self` (recovered "keyword used as ident" parse error). - // `rustc::ty` expects `Self` to be only used for a trait's `Self`. - // Instead, use `gensym("Self")` to create a distinct name that looks the same. - let ident = if param.ident.name == kw::SelfUpper { - param.ident.gensym() - } else { - param.ident - }; - let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); if !add_bounds.is_empty() { let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter(); @@ -2546,7 +2620,7 @@ impl<'a> LoweringContext<'a> { .next(), }; - (hir::ParamName::Plain(ident), kind) + (hir::ParamName::Plain(param.ident), kind) } GenericParamKind::Const { ref ty } => { (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { @@ -2611,12 +2685,8 @@ impl<'a> LoweringContext<'a> { bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect() } - fn lower_block_with_stmts( - &mut self, - b: &Block, - targeted_by_break: bool, - mut stmts: Vec, - ) -> P { + fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { + let mut stmts = vec![]; let mut expr = None; for (index, stmt) in b.stmts.iter().enumerate() { @@ -2641,8 +2711,11 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { - self.lower_block_with_stmts(b, targeted_by_break, vec![]) + /// Lowers a block directly to an expression, presuming that it + /// has no attributes and is not targeted by a `break`. + fn lower_block_expr(&mut self, b: &Block) -> hir::Expr { + let block = self.lower_block(b, false); + self.expr_block(block, ThinVec::new()) } fn lower_pat(&mut self, p: &Pat) -> P { @@ -2664,6 +2737,9 @@ impl<'a> LoweringContext<'a> { let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); hir::PatKind::TupleStruct(qpath, pats, ddpos) } + PatKind::Or(ref pats) => { + hir::PatKind::Or(pats.iter().map(|x| self.lower_pat(x)).collect()) + } PatKind::Path(ref qself, ref path) => { let qpath = self.lower_qpath( p.id, @@ -2685,16 +2761,12 @@ impl<'a> LoweringContext<'a> { let fs = fields .iter() - .map(|f| { - Spanned { - span: f.span, - node: hir::FieldPat { - hir_id: self.next_id(), - ident: f.node.ident, - pat: self.lower_pat(&f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } + .map(|f| hir::FieldPat { + hir_id: self.next_id(), + ident: f.ident, + pat: self.lower_pat(&f.pat), + is_shorthand: f.is_shorthand, + span: f.span, }) .collect(); hir::PatKind::Struct(qpath, fs, etc) @@ -2929,7 +3001,7 @@ impl<'a> LoweringContext<'a> { } StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))), StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))), - StmtKind::Mac(..) => panic!("Shouldn't exist here"), + StmtKind::Mac(..) => panic!("shouldn't exist here"), }; smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), @@ -3117,7 +3189,7 @@ impl<'a> LoweringContext<'a> { hir::Path { span, - res: res.map_id(|_| panic!("unexpected node_id")), + res: res.map_id(|_| panic!("unexpected `NodeId`")), segments: segments.into(), } } @@ -3174,10 +3246,6 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), - - AnonymousLifetimeMode::Replace(replacement) => { - self.new_replacement_lifetime(replacement, span) - } } } @@ -3231,10 +3299,6 @@ impl<'a> LoweringContext<'a> { // This is the normal case. AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), - AnonymousLifetimeMode::Replace(replacement) => { - self.new_replacement_lifetime(replacement, span) - } - AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), } } @@ -3266,23 +3330,15 @@ impl<'a> LoweringContext<'a> { // This is the normal case. AnonymousLifetimeMode::PassThrough => {} - - // We don't need to do any replacement here as this lifetime - // doesn't refer to an elided lifetime elsewhere in the function - // signature. - AnonymousLifetimeMode::Replace(_) => {} } - self.new_implicit_lifetime(span) - } - - fn new_replacement_lifetime( - &mut self, - replacement: LtReplacement, - span: Span, - ) -> hir::Lifetime { - let hir_id = self.next_id(); - self.replace_elided_lifetime(hir_id, span, replacement) + let r = hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::ImplicitObjectLifetimeDefault, + }; + debug!("elided_dyn_bound: r={:?}", r); + r } fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime { diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index d273006fbe..990728fa0e 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -68,7 +68,7 @@ impl LoweringContext<'_> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::AddrOf(m, ohs) } - ExprKind::Let(ref pats, ref scrutinee) => self.lower_expr_let(e.span, pats, scrutinee), + ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee), ExprKind::If(ref cond, ref then, ref else_opt) => { self.lower_expr_if(e.span, cond, then, else_opt.as_deref()) } @@ -90,10 +90,7 @@ impl LoweringContext<'_> { ), ExprKind::Async(capture_clause, closure_node_id, ref block) => { self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| { - this.with_new_scopes(|this| { - let block = this.lower_block(block, false); - this.expr_block(block, ThinVec::new()) - }) + this.with_new_scopes(|this| this.lower_block_expr(block)) }) } ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), @@ -227,16 +224,11 @@ impl LoweringContext<'_> { } } - /// Emit an error and lower `ast::ExprKind::Let(pats, scrutinee)` into: + /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into: /// ```rust /// match scrutinee { pats => true, _ => false } /// ``` - fn lower_expr_let( - &mut self, - span: Span, - pats: &[AstP], - scrutinee: &Expr - ) -> hir::ExprKind { + fn lower_expr_let(&mut self, span: Span, pat: &Pat, scrutinee: &Expr) -> hir::ExprKind { // If we got here, the `let` expression is not allowed. self.sess .struct_span_err(span, "`let` expressions are not supported here") @@ -246,23 +238,23 @@ impl LoweringContext<'_> { // For better recovery, we emit: // ``` - // match scrutinee { pats => true, _ => false } + // match scrutinee { pat => true, _ => false } // ``` // While this doesn't fully match the user's intent, it has key advantages: // 1. We can avoid using `abort_if_errors`. - // 2. We can typeck both `pats` and `scrutinee`. - // 3. `pats` is allowed to be refutable. + // 2. We can typeck both `pat` and `scrutinee`. + // 3. `pat` is allowed to be refutable. // 4. The return type of the block is `bool` which seems like what the user wanted. let scrutinee = self.lower_expr(scrutinee); let then_arm = { - let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect(); + let pat = self.lower_pat_top_hack(pat); let expr = self.expr_bool(span, true); - self.arm(pats, P(expr)) + self.arm(pat, P(expr)) }; let else_arm = { - let pats = hir_vec![self.pat_wild(span)]; + let pat = self.pat_wild(span); let expr = self.expr_bool(span, false); - self.arm(pats, P(expr)) + self.arm(hir_vec![pat], P(expr)) }; hir::ExprKind::Match( P(scrutinee), @@ -289,15 +281,13 @@ impl LoweringContext<'_> { let else_arm = self.arm(hir_vec![else_pat], P(else_expr)); // Handle then + scrutinee: - let then_blk = self.lower_block(then, false); - let then_expr = self.expr_block(then_blk, ThinVec::new()); - let (then_pats, scrutinee, desugar) = match cond.node { + let then_expr = self.lower_block_expr(then); + let (then_pat, scrutinee, desugar) = match cond.node { // ` => `: - ExprKind::Let(ref pats, ref scrutinee) => { + ExprKind::Let(ref pat, ref scrutinee) => { let scrutinee = self.lower_expr(scrutinee); - let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect(); - let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause }; - (pats, scrutinee, desugar) + let pat = self.lower_pat_top_hack(pat); + (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause }) } // `true => `: _ => { @@ -312,13 +302,11 @@ impl LoweringContext<'_> { // to preserve drop semantics since `if cond { ... }` does not // let temporaries live outside of `cond`. let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); - - let desugar = hir::MatchSource::IfDesugar { contains_else_clause }; - let pats = hir_vec![self.pat_bool(span, true)]; - (pats, cond, desugar) + let pat = self.pat_bool(span, true); + (hir_vec![pat], cond, hir::MatchSource::IfDesugar { contains_else_clause }) } }; - let then_arm = self.arm(then_pats, P(then_expr)); + let then_arm = self.arm(then_pat, P(then_expr)); hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar) } @@ -343,10 +331,9 @@ impl LoweringContext<'_> { }; // Handle then + scrutinee: - let then_blk = self.lower_block(body, false); - let then_expr = self.expr_block(then_blk, ThinVec::new()); - let (then_pats, scrutinee, desugar, source) = match cond.node { - ExprKind::Let(ref pats, ref scrutinee) => { + let then_expr = self.lower_block_expr(body); + let (then_pat, scrutinee, desugar, source) = match cond.node { + ExprKind::Let(ref pat, ref scrutinee) => { // to: // // [opt_ident]: loop { @@ -356,16 +343,15 @@ impl LoweringContext<'_> { // } // } let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee)); - let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect(); - let desugar = hir::MatchSource::WhileLetDesugar; - (pats, scrutinee, desugar, hir::LoopSource::WhileLet) + let pat = self.lower_pat_top_hack(pat); + (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet) } _ => { // We desugar: `'label: while $cond $body` into: // // ``` // 'label: loop { - // match DropTemps($cond) { + // match drop-temps { $cond } { // true => $body, // _ => break, // } @@ -383,14 +369,12 @@ impl LoweringContext<'_> { // to preserve drop semantics since `while cond { ... }` does not // let temporaries live outside of `cond`. let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); - - let desugar = hir::MatchSource::WhileDesugar; // `true => `: - let pats = hir_vec![self.pat_bool(span, true)]; - (pats, cond, desugar, hir::LoopSource::While) + let pat = self.pat_bool(span, true); + (hir_vec![pat], cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While) } }; - let then_arm = self.arm(then_pats, P(then_expr)); + let then_arm = self.arm(then_pat, P(then_expr)); // `match { ... }` let match_expr = self.expr_match( @@ -440,7 +424,7 @@ impl LoweringContext<'_> { hir::Arm { hir_id: self.next_id(), attrs: self.lower_attrs(&arm.attrs), - pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), + pats: self.lower_pat_top_hack(&arm.pat), guard: match arm.guard { Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))), _ => None, @@ -450,6 +434,16 @@ impl LoweringContext<'_> { } } + /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns + /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready + /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. + fn lower_pat_top_hack(&mut self, pat: &Pat) -> HirVec> { + match pat.node { + PatKind::Or(ref ps) => ps.iter().map(|x| self.lower_pat(x)).collect(), + _ => hir_vec![self.lower_pat(pat)], + } + } + pub(super) fn make_async_expr( &mut self, capture_clause: CaptureBy, @@ -508,14 +502,13 @@ impl LoweringContext<'_> { /// Desugar `.await` into: /// ```rust - /// { - /// let mut pinned = ; - /// loop { + /// match { + /// mut pinned => loop { /// match ::std::future::poll_with_tls_context(unsafe { - /// ::std::pin::Pin::new_unchecked(&mut pinned) + /// <::std::pin::Pin>::new_unchecked(&mut pinned) /// }) { /// ::std::task::Poll::Ready(result) => break result, - /// ::std::task::Poll::Pending => {}, + /// ::std::task::Poll::Pending => {} /// } /// yield (); /// } @@ -550,21 +543,12 @@ impl LoweringContext<'_> { self.allow_gen_future.clone(), ); - // let mut pinned = ; - let expr = P(self.lower_expr(expr)); - let pinned_ident = Ident::with_empty_ctxt(sym::pinned); + let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( span, pinned_ident, hir::BindingAnnotation::Mutable, ); - let pinned_let = self.stmt_let_pat( - ThinVec::new(), - span, - Some(expr), - pinned_pat, - hir::LocalSource::AwaitDesugar, - ); // ::std::future::poll_with_tls_context(unsafe { // ::std::pin::Pin::new_unchecked(&mut pinned) @@ -593,7 +577,7 @@ impl LoweringContext<'_> { let loop_node_id = self.sess.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { - let x_ident = Ident::with_empty_ctxt(sym::result); + let x_ident = Ident::with_dummy_span(sym::result); let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); let ready_pat = self.pat_std_enum( @@ -622,7 +606,7 @@ impl LoweringContext<'_> { self.arm(hir_vec![pending_pat], empty_block) }; - let match_stmt = { + let inner_match_stmt = { let match_expr = self.expr_match( span, poll_expr, @@ -644,10 +628,11 @@ impl LoweringContext<'_> { let loop_block = P(self.block_all( span, - hir_vec![match_stmt, yield_stmt], + hir_vec![inner_match_stmt, yield_stmt], None, )); + // loop { .. } let loop_expr = P(hir::Expr { hir_id: loop_hir_id, node: hir::ExprKind::Loop( @@ -659,10 +644,14 @@ impl LoweringContext<'_> { attrs: ThinVec::new(), }); - hir::ExprKind::Block( - P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))), - None, - ) + // mut pinned => loop { ... } + let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr); + + // match { + // mut pinned => loop { .. } + // } + let expr = P(self.lower_expr(expr)); + hir::ExprKind::Match(expr, hir_vec![pinned_arm], hir::MatchSource::AwaitDesugar) } fn lower_expr_closure( @@ -677,6 +666,7 @@ impl LoweringContext<'_> { let fn_decl = self.lower_fn_decl(decl, None, false, None); self.with_new_scopes(|this| { + let prev = this.current_item; this.current_item = Some(fn_decl_span); let mut generator_kind = None; let body_id = this.lower_fn_body(decl, |this| { @@ -690,8 +680,10 @@ impl LoweringContext<'_> { generator_kind, movability, ); + let capture_clause = this.lower_capture_clause(capture_clause); + this.current_item = prev; hir::ExprKind::Closure( - this.lower_capture_clause(capture_clause), + capture_clause, fn_decl, body_id, fn_decl_span, @@ -721,7 +713,7 @@ impl LoweringContext<'_> { self.sess, fn_decl_span, E0628, - "generators cannot have explicit arguments" + "generators cannot have explicit parameters" ); self.sess.abort_if_errors(); } @@ -772,7 +764,7 @@ impl LoweringContext<'_> { this.sess, fn_decl_span, E0708, - "`async` non-`move` closures with arguments are not currently supported", + "`async` non-`move` closures with parameters are not currently supported", ) .help( "consider using `let` statements to manually capture \ @@ -981,7 +973,6 @@ impl LoweringContext<'_> { volatile: asm.volatile, alignstack: asm.alignstack, dialect: asm.dialect, - ctxt: asm.ctxt, }; let outputs = asm.outputs @@ -1067,9 +1058,9 @@ impl LoweringContext<'_> { ); head.span = desugared_span; - let iter = Ident::with_empty_ctxt(sym::iter); + let iter = Ident::with_dummy_span(sym::iter); - let next_ident = Ident::with_empty_ctxt(sym::__next); + let next_ident = Ident::with_dummy_span(sym::__next); let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( desugared_span, next_ident, @@ -1078,7 +1069,7 @@ impl LoweringContext<'_> { // `::std::option::Option::Some(val) => __next = val` let pat_arm = { - let val_ident = Ident::with_empty_ctxt(sym::val); + let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); @@ -1244,7 +1235,7 @@ impl LoweringContext<'_> { // `Ok(val) => #[allow(unreachable_code)] val,` let ok_arm = { - let val_ident = Ident::with_empty_ctxt(sym::val); + let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = P(self.expr_ident_with_attrs( span, @@ -1253,14 +1244,13 @@ impl LoweringContext<'_> { ThinVec::from(attrs.clone()), )); let ok_pat = self.pat_ok(span, val_pat); - self.arm(hir_vec![ok_pat], val_expr) }; // `Err(err) => #[allow(unreachable_code)] // return Try::from_error(From::from(err)),` let err_arm = { - let err_ident = Ident::with_empty_ctxt(sym::err); + let err_ident = Ident::with_dummy_span(sym::err); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { let from_path = &[sym::convert, sym::From, sym::from]; @@ -1315,7 +1305,7 @@ impl LoweringContext<'_> { /// `{ let _t = $expr; _t }` but should provide better compile-time performance. /// /// The drop order can be important in e.g. `if expr { .. }`. - fn expr_drop_temps( + pub(super) fn expr_drop_temps( &mut self, span: Span, expr: P, @@ -1484,7 +1474,10 @@ impl LoweringContext<'_> { } } - fn arm(&mut self, pats: hir::HirVec>, expr: P) -> hir::Arm { + /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns + /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready + /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. + fn arm(&mut self, pats: HirVec>, expr: P) -> hir::Arm { hir::Arm { hir_id: self.next_id(), attrs: hir_vec![], diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 6b717e7519..61be40a6b9 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -60,10 +60,12 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { fn visit_item(&mut self, item: &'tcx Item) { let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { - if let Some(hir_item) = lctx.lower_item(item) { - item_hir_id = Some(hir_item.hir_id); - lctx.insert_item(hir_item); - } + lctx.without_in_scope_lifetime_defs(|lctx| { + if let Some(hir_item) = lctx.lower_item(item) { + item_hir_id = Some(hir_item.hir_id); + lctx.insert_item(hir_item); + } + }) }); if let Some(hir_id) = item_hir_id { @@ -123,7 +125,7 @@ impl LoweringContext<'_> { _ => &[], }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()), + hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -134,6 +136,28 @@ impl LoweringContext<'_> { res } + // Clears (and restores) the `in_scope_lifetimes` field. Used when + // visiting nested items, which never inherit in-scope lifetimes + // from their surrounding environment. + fn without_in_scope_lifetime_defs( + &mut self, + f: impl FnOnce(&mut LoweringContext<'_>) -> T, + ) -> T { + let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); + + // this vector is only used when walking over impl headers, + // input types, and the like, and should not be non-empty in + // between items + assert!(self.lifetimes_to_define.is_empty()); + + let res = f(self); + + assert!(self.in_scope_lifetimes.is_empty()); + self.in_scope_lifetimes = old_in_scope_lifetimes; + + res + } + pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, @@ -694,9 +718,9 @@ impl LoweringContext<'_> { AnonymousLifetimeMode::PassThrough, |this, _| { ( - // Disallow impl Trait in foreign items + // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, None, false, None), - this.lower_fn_args_to_names(fdec), + this.lower_fn_params_to_names(fdec), ) }, ); @@ -708,7 +732,7 @@ impl LoweringContext<'_> { self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m)) } ForeignItemKind::Ty => hir::ForeignItemKind::Type, - ForeignItemKind::Macro(_) => panic!("shouldn't exist here"), + ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, vis: self.lower_visibility(&i.vis, None), span: i.span, @@ -726,21 +750,16 @@ impl LoweringContext<'_> { } fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P { - P(hir::GlobalAsm { - asm: ga.asm, - ctxt: ga.ctxt, - }) + P(hir::GlobalAsm { asm: ga.asm }) } fn lower_variant(&mut self, v: &Variant) -> hir::Variant { - Spanned { - node: hir::VariantKind { - ident: v.node.ident, - id: self.lower_node_id(v.node.id), - attrs: self.lower_attrs(&v.node.attrs), - data: self.lower_variant_data(&v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), - }, + hir::Variant { + attrs: self.lower_attrs(&v.attrs), + data: self.lower_variant_data(&v.data), + disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), + id: self.lower_node_id(v.id), + ident: v.ident, span: v.span, } } @@ -808,7 +827,7 @@ impl LoweringContext<'_> { ), ), TraitItemKind::Method(ref sig, None) => { - let names = self.lower_fn_args_to_names(&sig.decl); + let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( &i.generics, sig, @@ -1009,10 +1028,10 @@ impl LoweringContext<'_> { } } - fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { + fn record_body(&mut self, params: HirVec, value: hir::Expr) -> hir::BodyId { let body = hir::Body { generator_kind: self.generator_kind, - arguments, + params, value, }; let id = body.id(); @@ -1022,21 +1041,21 @@ impl LoweringContext<'_> { fn lower_body( &mut self, - f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), + f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), ) -> hir::BodyId { let prev_gen_kind = self.generator_kind.take(); - let (arguments, result) = f(self); - let body_id = self.record_body(arguments, result); + let (parameters, result) = f(self); + let body_id = self.record_body(parameters, result); self.generator_kind = prev_gen_kind; body_id } - fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { - hir::Arg { - attrs: self.lower_attrs(&arg.attrs), - hir_id: self.lower_node_id(arg.id), - pat: self.lower_pat(&arg.pat), - span: arg.span, + fn lower_param(&mut self, param: &Param) -> hir::Param { + hir::Param { + attrs: self.lower_attrs(¶m.attrs), + hir_id: self.lower_node_id(param.id), + pat: self.lower_pat(¶m.pat), + span: param.span, } } @@ -1046,16 +1065,13 @@ impl LoweringContext<'_> { body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::BodyId { self.lower_body(|this| ( - decl.inputs.iter().map(|x| this.lower_arg(x)).collect(), + decl.inputs.iter().map(|x| this.lower_param(x)).collect(), body(this), )) } fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId { - self.lower_fn_body(decl, |this| { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - }) + self.lower_fn_body(decl, |this| this.lower_block_expr(body)) } pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId { @@ -1074,17 +1090,16 @@ impl LoweringContext<'_> { }; self.lower_body(|this| { - let mut arguments: Vec = Vec::new(); + let mut parameters: Vec = Vec::new(); let mut statements: Vec = Vec::new(); - // Async function arguments are lowered into the closure body so that they are + // Async function parameters are lowered into the closure body so that they are // captured and so that the drop order matches the equivalent non-async functions. // // from: // // async fn foo(: , : , : ) { - // async move { - // } + // // } // // into: @@ -1097,18 +1112,26 @@ impl LoweringContext<'_> { // let = __arg1; // let __arg0 = __arg0; // let = __arg0; + // drop-temps { } // see comments later in fn for details // } // } // // If `` is a simple ident, then it is lowered to a single // `let = ;` statement as an optimization. - for (index, argument) in decl.inputs.iter().enumerate() { - let argument = this.lower_arg(argument); - let span = argument.pat.span; + // + // Note that the body is embedded in `drop-temps`; an + // equivalent desugaring would be `return { + // };`. The key point is that we wish to drop all the + // let-bound variables and temporaries created in the body + // (and its tail expression!) before we drop the + // parameters (c.f. rust-lang/rust#64512). + for (index, parameter) in decl.inputs.iter().enumerate() { + let parameter = this.lower_param(parameter); + let span = parameter.pat.span; // Check if this is a binding pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement. In this case, we do not rename the argument. - let (ident, is_simple_argument) = match argument.pat.node { + // `let = __argN;` statement. In this case, we do not rename the parameter. + let (ident, is_simple_parameter) = match parameter.pat.node { hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) => (ident, true), _ => { @@ -1123,32 +1146,32 @@ impl LoweringContext<'_> { let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None); - // Construct an argument representing `__argN: ` to replace the argument of the + // Construct a parameter representing `__argN: ` to replace the parameter of the // async function. // - // If this is the simple case, this argument will end up being the same as the - // original argument, but with a different pattern id. + // If this is the simple case, this parameter will end up being the same as the + // original parameter, but with a different pattern id. let mut stmt_attrs = ThinVec::new(); - stmt_attrs.extend(argument.attrs.iter().cloned()); - let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident); - let new_argument = hir::Arg { - attrs: argument.attrs, - hir_id: argument.hir_id, - pat: new_argument_pat, - span: argument.span, + stmt_attrs.extend(parameter.attrs.iter().cloned()); + let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident); + let new_parameter = hir::Param { + attrs: parameter.attrs, + hir_id: parameter.hir_id, + pat: new_parameter_pat, + span: parameter.span, }; - if is_simple_argument { + if is_simple_parameter { // If this is the simple case, then we only insert one statement that is // `let = ;`. We re-use the original argument's pattern so that // `HirId`s are densely assigned. - let expr = this.expr_ident(desugared_span, ident, new_argument_id); + let expr = this.expr_ident(desugared_span, ident, new_parameter_id); let stmt = this.stmt_let_pat( stmt_attrs, desugared_span, Some(P(expr)), - argument.pat, + parameter.pat, hir::LocalSource::AsyncFn ); statements.push(stmt); @@ -1160,7 +1183,7 @@ impl LoweringContext<'_> { // let = __argN; // ``` // - // The first statement moves the argument into the closure and thus ensures + // The first statement moves the parameter into the closure and thus ensures // that the drop order is correct. // // The second statement creates the bindings that the user wrote. @@ -1170,7 +1193,7 @@ impl LoweringContext<'_> { // statement. let (move_pat, move_id) = this.pat_ident_binding_mode( desugared_span, ident, hir::BindingAnnotation::Mutable); - let move_expr = this.expr_ident(desugared_span, ident, new_argument_id); + let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_stmt = this.stmt_let_pat( ThinVec::new(), desugared_span, @@ -1180,13 +1203,13 @@ impl LoweringContext<'_> { ); // Construct the `let = __argN;` statement. We re-use the original - // argument's pattern so that `HirId`s are densely assigned. + // parameter's pattern so that `HirId`s are densely assigned. let pattern_expr = this.expr_ident(desugared_span, ident, move_id); let pattern_stmt = this.stmt_let_pat( stmt_attrs, desugared_span, Some(P(pattern_expr)), - argument.pat, + parameter.pat, hir::LocalSource::AsyncFn ); @@ -1194,16 +1217,44 @@ impl LoweringContext<'_> { statements.push(pattern_stmt); }; - arguments.push(new_argument); + parameters.push(new_parameter); } let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, body.span, |this| { - let body = this.lower_block_with_stmts(body, false, statements); - this.expr_block(body, ThinVec::new()) + // Create a block from the user's function body: + let user_body = this.lower_block_expr(body); + + // Transform into `drop-temps { }`, an expression: + let desugared_span = this.mark_span_with_reason( + DesugaringKind::Async, + user_body.span, + None, + ); + let user_body = this.expr_drop_temps( + desugared_span, + P(user_body), + ThinVec::new(), + ); + + // As noted above, create the final block like + // + // ``` + // { + // let $param_pattern = $raw_param; + // ... + // drop-temps { } + // } + // ``` + let body = this.block_all( + desugared_span, + statements.into(), + Some(P(user_body)), + ); + this.expr_block(P(body), ThinVec::new()) }); - (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new())) + (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new())) }) } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b6807f7d3b..4179cf2ff8 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -186,7 +186,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum).as_str(); + let name = cstore.crate_name_untracked(cnum).as_interned_str(); let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); let hash = cstore.crate_hash_untracked(cnum); (name, disambiguator, hash) @@ -340,7 +340,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { /// their outer items. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { - panic!("visit_nested_xxx must be manually implemented in this visitor") + panic!("`visit_nested_xxx` must be manually implemented in this visitor"); } fn visit_nested_item(&mut self, item: ItemId) { @@ -363,11 +363,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.currently_in_body = prev_in_body; } - fn visit_arg(&mut self, arg: &'hir Arg) { - let node = Node::Arg(arg); - self.insert(arg.pat.span, arg.hir_id, node); - self.with_parent(arg.hir_id, |this| { - intravisit::walk_arg(this, arg); + fn visit_param(&mut self, param: &'hir Param) { + let node = Node::Param(param); + self.insert(param.pat.span, param.hir_id, node); + self.with_parent(param.hir_id, |this| { + intravisit::walk_param(this, param); }); } @@ -544,11 +544,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) { - self.insert(v.span, v.node.id, Node::Variant(v)); - self.with_parent(v.node.id, |this| { + self.insert(v.span, v.id, Node::Variant(v)); + self.with_parent(v.id, |this| { // Register the constructor of this variant. - if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() { - this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data)); + if let Some(ctor_hir_id) = v.data.ctor_hir_id() { + this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data)); } intravisit::walk_variant(this, v, g, item_id); }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 2964b130dd..d1cc7a8ce9 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -31,7 +31,7 @@ impl<'a> DefCollector<'a> { self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span) } - pub fn with_parent(&mut self, parent_def: DefIndex, f: F) { + fn with_parent(&mut self, parent_def: DefIndex, f: F) { let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); f(self); self.parent_def = orig_parent_def; @@ -74,7 +74,23 @@ impl<'a> DefCollector<'a> { }) } - fn visit_macro_invoc(&mut self, id: NodeId) { + fn collect_field(&mut self, field: &'a StructField, index: Option) { + if field.is_placeholder { + self.visit_macro_invoc(field.id); + } else { + let name = field.ident.map(|ident| ident.name) + .or_else(|| index.map(sym::integer)) + .unwrap_or_else(|| { + let node_id = NodeId::placeholder_from_expn_id(self.expansion); + sym::integer(self.definitions.placeholder_field_indices[&node_id]) + }) + .as_interned_str(); + let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span); + self.with_parent(def, |this| visit::walk_struct_field(this, field)); + } + } + + pub fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } @@ -154,31 +170,38 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }); } - fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { - let def = self.create_def(v.node.id, - DefPathData::TypeNs(v.node.ident.as_interned_str()), + fn visit_variant(&mut self, v: &'a Variant) { + if v.is_placeholder { + return self.visit_macro_invoc(v.id); + } + let def = self.create_def(v.id, + DefPathData::TypeNs(v.ident.as_interned_str()), v.span); self.with_parent(def, |this| { - if let Some(ctor_hir_id) = v.node.data.ctor_id() { + if let Some(ctor_hir_id) = v.data.ctor_id() { this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); } - visit::walk_variant(this, v, g, item_id) + visit::walk_variant(this, v) }); } - fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident, - _: &'a Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, data: &'a VariantData) { + // The assumption here is that non-`cfg` macro expansion cannot change field indices. + // It currently holds because only inert attributes are accepted on fields, + // and every such attribute expands into a single field after it's resolved. for (index, field) in data.fields().iter().enumerate() { - let name = field.ident.map(|ident| ident.name) - .unwrap_or_else(|| sym::integer(index)); - let def = self.create_def(field.id, - DefPathData::ValueNs(name.as_interned_str()), - field.span); - self.with_parent(def, |this| this.visit_struct_field(field)); + self.collect_field(field, Some(index)); + if field.is_placeholder && field.ident.is_none() { + self.definitions.placeholder_field_indices.insert(field.id, index); + } } } fn visit_generic_param(&mut self, param: &'a GenericParam) { + if param.is_placeholder { + self.visit_macro_invoc(param.id); + return; + } let name = param.ident.as_interned_str(); let def_path_data = match param.kind { GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), @@ -295,4 +318,42 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } } } + + fn visit_arm(&mut self, arm: &'a Arm) { + if arm.is_placeholder { + self.visit_macro_invoc(arm.id) + } else { + visit::walk_arm(self, arm) + } + } + + fn visit_field(&mut self, f: &'a Field) { + if f.is_placeholder { + self.visit_macro_invoc(f.id) + } else { + visit::walk_field(self, f) + } + } + + fn visit_field_pattern(&mut self, fp: &'a FieldPat) { + if fp.is_placeholder { + self.visit_macro_invoc(fp.id) + } else { + visit::walk_field_pattern(self, fp) + } + } + + fn visit_param(&mut self, p: &'a Param) { + if p.is_placeholder { + self.visit_macro_invoc(p.id) + } else { + visit::walk_param(self, p) + } + } + + // This method is called only when we are visiting an individual field + // after expanding an attribute on it. + fn visit_struct_field(&mut self, field: &'a StructField) { + self.collect_field(field, None); + } } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 8ee8c6d0e8..187bc59332 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -7,10 +7,12 @@ use crate::hir; use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX}; use crate::ich::Fingerprint; +use crate::session::CrateDisambiguator; +use crate::util::nodemap::NodeMap; + use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; -use crate::session::CrateDisambiguator; use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; @@ -18,12 +20,11 @@ use syntax::ast; use syntax::ext::hygiene::ExpnId; use syntax::symbol::{Symbol, sym, InternedString}; use syntax_pos::{Span, DUMMY_SP}; -use crate::util::nodemap::NodeMap; -/// The DefPathTable maps DefIndexes to DefKeys and vice versa. -/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey -/// stores the DefIndex of its parent. -/// There is one DefPathTable for each crate. +/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. +/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` +/// stores the `DefIndex` of its parent. +/// There is one `DefPathTable` for each crate. #[derive(Clone, Default, RustcDecodable, RustcEncodable)] pub struct DefPathTable { index_to_key: Vec, @@ -103,6 +104,8 @@ pub struct Definitions { /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// we know what parent node that fragment should be attached to thanks to this table. invocation_parents: FxHashMap, + /// Indices of unnamed struct or variant fields with unresolved attributes. + pub(super) placeholder_field_indices: NodeMap, } /// A unique identifier that we can use to lookup a definition @@ -121,7 +124,7 @@ impl DefKey { fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash { let mut hasher = StableHasher::new(); - // We hash a 0u8 here to disambiguate between regular DefPath hashes, + // We hash a `0u8` here to disambiguate between regular `DefPath` hashes, // and the special "root_parent" below. 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); @@ -145,8 +148,7 @@ impl DefKey { crate_disambiguator: CrateDisambiguator) -> DefPathHash { let mut hasher = StableHasher::new(); - // Disambiguate this from a regular DefPath hash, - // see compute_stable_hash() above. + // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above. 1u8.hash(&mut hasher); crate_name.hash(&mut hasher); crate_disambiguator.hash(&mut hasher); @@ -155,10 +157,10 @@ impl DefKey { } /// A pair of `DefPathData` and an integer disambiguator. The integer is -/// normally 0, but in the event that there are multiple defs with the +/// normally `0`, but in the event that there are multiple defs with the /// same `parent` and `data`, we use this field to disambiguate /// between them. This introduces some artificial ordering dependency -/// but means that if you have (e.g.) two impls for the same type in +/// but means that if you have, e.g., two impls for the same type in /// the same module, they do get distinct `DefId`s. #[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { @@ -277,29 +279,34 @@ impl DefPath { pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. - /// The crate root (marker) + + /// The crate root (marker). CrateRoot, - // Catch-all for random DefId things like `DUMMY_NODE_ID` + // Catch-all for random `DefId` things like `DUMMY_NODE_ID`. Misc, + // Different kinds of items and item-like things: - /// An impl + + /// An impl. Impl, - /// Something in the type NS + /// Something in the type namespace. TypeNs(InternedString), - /// Something in the value NS + /// Something in the value namespace. ValueNs(InternedString), - /// Something in the macro NS + /// Something in the macro namespace. MacroNs(InternedString), - /// Something in the lifetime NS + /// Something in the lifetime namespace. LifetimeNs(InternedString), - /// A closure expression + /// A closure expression. ClosureExpr, - // Subportions of items - /// Implicit ctor for a unit or tuple-like struct or enum variant. + + // Subportions of items: + + /// Implicit constructor for a unit or tuple-like struct or enum variant. Ctor, - /// A constant expression (see {ast,hir}::AnonConst). + /// A constant expression (see `{ast,hir}::AnonConst`). AnonConst, - /// An `impl Trait` type node + /// An `impl Trait` type node. ImplTrait, /// Identifies a piece of crate metadata that is global to a whole crate /// (as opposed to just one item). `GlobalMetaData` components are only @@ -411,10 +418,6 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - /// - /// After the initial definitions are created the first `FIRST_FREE_DEF_INDEX` indexes - /// are taken, so the "user" indexes will be allocated starting with `FIRST_FREE_DEF_INDEX` - /// in ascending order. pub fn create_root_def(&mut self, crate_name: &str, crate_disambiguator: CrateDisambiguator) @@ -439,7 +442,7 @@ impl Definitions { self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); self.set_invocation_parent(ExpnId::root(), root_index); - // Allocate some other DefIndices that always must exist. + // Allocate some other `DefIndex`es that always must exist. GlobalMetaDataKind::allocate_def_indices(self); root_index @@ -462,7 +465,7 @@ impl Definitions { data, self.table.def_key(self.node_to_def_index[&node_id])); - // The root node must be created with create_root_def() + // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); // Find the next free disambiguator for this key. @@ -490,9 +493,9 @@ impl Definitions { assert_eq!(index.index(), self.def_index_to_node.len()); self.def_index_to_node.push(node_id); - // Some things for which we allocate DefIndices don't correspond to - // anything in the AST, so they don't have a NodeId. For these cases - // we don't need a mapping from NodeId to DefIndex. + // Some things for which we allocate `DefIndex`es don't correspond to + // anything in the AST, so they don't have a `NodeId`. For these cases + // we don't need a mapping from `NodeId` to `DefIndex`. if node_id != ast::DUMMY_NODE_ID { debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); self.node_to_def_index.insert(node_id, index); @@ -502,7 +505,7 @@ impl Definitions { self.expansions_that_defined.insert(index, expn_id); } - // The span is added if it isn't dummy + // The span is added if it isn't dummy. if !span.is_dummy() { self.def_index_to_span.insert(index, span); } @@ -510,12 +513,12 @@ impl Definitions { index } - /// Initialize the `ast::NodeId` to `HirId` mapping once it has been generated during + /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { assert!(self.node_to_hir_id.is_empty(), - "Trying initialize NodeId -> HirId mapping twice"); + "trying to initialize `NodeId` -> `HirId` mapping twice"); self.node_to_hir_id = mapping; } @@ -537,7 +540,7 @@ impl Definitions { pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) { let old_parent = self.invocation_parents.insert(invoc_id, parent); - assert!(old_parent.is_none(), "parent def-index is reset for an invocation"); + assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation"); } } @@ -589,22 +592,9 @@ impl DefPathData { } } -/// Evaluates to the number of tokens passed to it. -/// -/// Logarithmic counting: every one or two recursive expansions, the number of -/// tokens to count is divided by two, instead of being reduced by one. -/// Therefore, the recursion depth is the binary logarithm of the number of -/// tokens to count, and the expanded tree is likewise very small. -macro_rules! count { - () => (0usize); - ($one:tt) => (1usize); - ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); - ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); -} - -// We define the GlobalMetaDataKind enum with this macro because we want to +// We define the `GlobalMetaDataKind` enum with this macro because we want to // make sure that we exhaustively iterate over all variants when registering -// the corresponding DefIndices in the DefTable. +// the corresponding `DefIndex`es in the `DefTable`. macro_rules! define_global_metadata_kind { (pub enum GlobalMetaDataKind { $($variant:ident),* @@ -614,8 +604,6 @@ macro_rules! define_global_metadata_kind { $($variant),* } - pub const FIRST_FREE_DEF_INDEX: usize = 1 + count!($($variant)*); - impl GlobalMetaDataKind { fn allocate_def_indices(definitions: &mut Definitions) { $({ @@ -628,7 +616,7 @@ macro_rules! define_global_metadata_kind { DUMMY_SP ); - // Make sure calling def_index does not crash. + // Make sure calling `def_index` does not crash. instance.def_index(&definitions.table); })* } @@ -642,7 +630,7 @@ macro_rules! define_global_metadata_kind { } }; - // These DefKeys are all right after the root, + // These `DefKey`s are all right after the root, // so a linear search is fine. let index = def_path_table.index_to_key .iter() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b85738dd29..5cec8a593f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -5,10 +5,15 @@ pub use self::definitions::{ }; use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; - +use crate::hir::*; +use crate::hir::DefKind; use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId}; - +use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir::print::Nested; use crate::middle::cstore::CrateStoreDyn; +use crate::ty::query::Providers; +use crate::util::nodemap::FxHashMap; +use crate::util::common::time; use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; @@ -18,15 +23,7 @@ use syntax::source_map::Spanned; use syntax::ext::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; -use crate::hir::*; -use crate::hir::DefKind; -use crate::hir::itemlikevisit::ItemLikeVisitor; -use crate::hir::print::Nested; -use crate::util::nodemap::FxHashMap; -use crate::util::common::time; - use std::result::Result::Err; -use crate::ty::query::Providers; pub mod blocks; mod collector; @@ -360,7 +357,7 @@ impl<'hir> Map<'hir> { Node::Pat(_) | Node::Binding(_) | Node::Local(_) | - Node::Arg(_) | + Node::Param(_) | Node::Arm(_) | Node::Lifetime(_) | Node::Visibility(_) | @@ -514,8 +511,7 @@ impl<'hir> Map<'hir> { &self.forest.krate.attrs } - pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) - { + pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) { let hir_id = self.as_local_hir_id(module).unwrap(); self.read(hir_id); match self.find_entry(hir_id).unwrap().node { @@ -525,7 +521,7 @@ impl<'hir> Map<'hir> { .. }) => (m, span, hir_id), Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), - _ => panic!("not a module") + node => panic!("not a module: {:?}", node), } } @@ -628,7 +624,7 @@ impl<'hir> Map<'hir> { .unwrap_or(hir_id) } - /// Check if the node is an argument. An argument is a local variable whose + /// Checks if the node is an argument. An argument is a local variable whose /// immediate parent is an item or a closure. pub fn is_argument(&self, id: HirId) -> bool { match self.find(id) { @@ -649,14 +645,46 @@ impl<'hir> Map<'hir> { } } - pub fn is_const_scope(&self, hir_id: HirId) -> bool { - self.walk_parent_nodes(hir_id, |node| match *node { - Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true, - Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(), + /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. + /// Used exclusively for diagnostics, to avoid suggestion function calls. + pub fn is_const_context(&self, hir_id: HirId) -> bool { + let parent_id = self.get_parent_item(hir_id); + match self.get(parent_id) { + Node::Item(&Item { + node: ItemKind::Const(..), + .. + }) + | Node::TraitItem(&TraitItem { + node: TraitItemKind::Const(..), + .. + }) + | Node::ImplItem(&ImplItem { + node: ImplItemKind::Const(..), + .. + }) + | Node::AnonConst(_) + | Node::Item(&Item { + node: ItemKind::Static(..), + .. + }) => true, + Node::Item(&Item { + node: ItemKind::Fn(_, header, ..), + .. + }) => header.constness == Constness::Const, + _ => false, + } + } + + /// Wether `hir_id` corresponds to a `mod` or a crate. + pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { + match self.lookup(hir_id) { + Some(Entry { node: Node::Item(Item { node: ItemKind::Mod(_), .. }), .. }) | + Some(Entry { node: Node::Crate, .. }) => true, _ => false, - }, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false) + } } + /// If there is some error when walking the parents (e.g., a node does not /// have a parent in the map or a node can't be found), then we return the /// last good `HirId` we found. Note that reaching the crate root (`id == 0`), @@ -702,7 +730,7 @@ impl<'hir> Map<'hir> { /// ``` /// fn foo(x: usize) -> bool { /// if x == 1 { - /// true // `get_return_block` gets passed the `id` corresponding + /// true // If `get_return_block` gets passed the `id` corresponding /// } else { // to this, it will return `foo`'s `HirId`. /// false /// } @@ -712,7 +740,7 @@ impl<'hir> Map<'hir> { /// ``` /// fn foo(x: usize) -> bool { /// loop { - /// true // `get_return_block` gets passed the `id` corresponding + /// true // If `get_return_block` gets passed the `id` corresponding /// } // to this, it will return `None`. /// false /// } @@ -885,7 +913,7 @@ impl<'hir> Map<'hir> { _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)) } } - Some(Node::Variant(variant)) => &variant.node.data, + Some(Node::Variant(variant)) => &variant.data, Some(Node::Ctor(data)) => data, _ => bug!("expected struct or variant, found {}", self.node_to_string(id)) } @@ -918,7 +946,7 @@ impl<'hir> Map<'hir> { Node::ForeignItem(fi) => fi.ident.name, Node::ImplItem(ii) => ii.ident.name, Node::TraitItem(ti) => ti.ident.name, - Node::Variant(v) => v.node.ident.name, + Node::Variant(v) => v.ident.name, Node::Field(f) => f.ident.name, Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, @@ -933,13 +961,13 @@ impl<'hir> Map<'hir> { pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { - Some(Node::Arg(a)) => Some(&a.attrs[..]), + Some(Node::Param(a)) => Some(&a.attrs[..]), Some(Node::Local(l)) => Some(&l.attrs[..]), Some(Node::Item(i)) => Some(&i.attrs[..]), Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]), Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]), - Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]), + Some(Node::Variant(ref v)) => Some(&v.attrs[..]), Some(Node::Field(ref f)) => Some(&f.attrs[..]), Some(Node::Expr(ref e)) => Some(&*e.attrs), Some(Node::Stmt(ref s)) => Some(s.node.attrs()), @@ -963,9 +991,9 @@ impl<'hir> Map<'hir> { self.map.iter().enumerate().filter_map(|(i, local_map)| { local_map.as_ref().map(|m| (i, m)) }).flat_map(move |(array_index, local_map)| { - // Iterate over each valid entry in the local map + // Iterate over each valid entry in the local map. local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { - // Reconstruct the HirId based on the 3 indices we used to find it + // Reconstruct the `HirId` based on the 3 indices we used to find it. HirId { owner: DefIndex::from(array_index), local_id: i, @@ -997,7 +1025,7 @@ impl<'hir> Map<'hir> { pub fn span(&self, hir_id: HirId) -> Span { self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { - Some(Node::Arg(arg)) => arg.span, + Some(Node::Param(param)) => param.span, Some(Node::Item(item)) => item.span, Some(Node::ForeignItem(foreign_item)) => foreign_item.span, Some(Node::TraitItem(trait_method)) => trait_method.span, @@ -1133,7 +1161,7 @@ impl Named for Spanned { fn name(&self) -> Name { self.node.name() } impl Named for Item { fn name(&self) -> Name { self.ident.name } } impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } -impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } } +impl Named for Variant { fn name(&self) -> Name { self.ident.name } } impl Named for StructField { fn name(&self) -> Name { self.ident.name } } impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } @@ -1176,7 +1204,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, definitions, }; - time(sess, "validate hir map", || { + time(sess, "validate HIR map", || { hir_id_validator::check_crate(&map); }); @@ -1192,7 +1220,7 @@ impl<'hir> print::PpAnn for Map<'hir> { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) } } } @@ -1200,7 +1228,7 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Arg(a) => self.print_arg(&a), + Node::Param(a) => self.print_param(&a), Node::Item(a) => self.print_item(&a), Node::ForeignItem(a) => self.print_foreign_item(&a), Node::TraitItem(a) => self.print_trait_item(a), @@ -1216,9 +1244,9 @@ impl<'a> print::State<'a> { Node::Pat(a) => self.print_pat(&a), Node::Arm(a) => self.print_arm(&a), Node::Block(a) => { - // containing cbox, will be closed by print-block at } + // Containing cbox, will be closed by print-block at `}`. self.cbox(print::INDENT_UNIT); - // head-ibox, will be closed by print-block after { + // Head-ibox, will be closed by print-block after `{`. self.ibox(0); self.print_block(&a) } @@ -1226,8 +1254,8 @@ impl<'a> print::State<'a> { Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => bug!("cannot print Node::GenericParam"), Node::Field(_) => bug!("cannot print StructField"), - // these cases do not carry enough information in the - // hir_map to reconstruct their full structure for pretty + // These cases do not carry enough information in the + // `hir_map` to reconstruct their full structure for pretty // printing. Node::Ctor(..) => bug!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), @@ -1242,8 +1270,8 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { let id_str = if include_id { &id_str[..] } else { "" }; let path_str = || { - // This functionality is used for debugging, try to use TyCtxt to get - // the user-friendly path, otherwise fall back to stringifying DefPath. + // This functionality is used for debugging, try to use `TyCtxt` to get + // the user-friendly path, otherwise fall back to stringifying `DefPath`. crate::ty::tls::with_opt(|tcx| { if let Some(tcx) = tcx { let def_id = map.local_def_id(id); @@ -1310,7 +1338,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { } Some(Node::Variant(ref variant)) => { format!("variant {} in {}{}", - variant.node.ident, + variant.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { @@ -1342,8 +1370,8 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Pat(_)) => { format!("pat {}{}", map.hir_to_pretty_string(id), id_str) } - Some(Node::Arg(_)) => { - format!("arg {}{}", map.hir_to_pretty_string(id), id_str) + Some(Node::Param(_)) => { + format!("param {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Arm(_)) => { format!("arm {}{}", map.hir_to_pretty_string(id), id_str) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3d049fe4cc..92a8c00804 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -13,27 +13,24 @@ pub use self::UnsafeSource::*; use crate::hir::def::{Res, DefKind}; use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use crate::hir::ptr::P; -use crate::util::nodemap::{NodeMap, FxHashSet}; use crate::mir::mono::Linkage; +use crate::ty::AdtKind; +use crate::ty::query::Providers; +use crate::util::nodemap::{NodeMap, FxHashSet}; use errors::FatalError; use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan}; use syntax::source_map::Spanned; -use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::{InlineAttr, OptimizeAttr}; -use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::{Symbol, kw}; use syntax::tokenstream::TokenStream; use syntax::util::parser::ExprPrecedence; -use crate::ty::AdtKind; -use crate::ty::query::Providers; - +use rustc_target::spec::abi::Abi; use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; use rustc_data_structures::thin_vec::ThinVec; use rustc_macros::HashStable; - use rustc_serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::{BTreeSet, BTreeMap}; use std::fmt; @@ -100,7 +97,8 @@ impl rustc_serialize::UseSpecializedEncodable for HirId { } = *self; owner.encode(s)?; - local_id.encode(s) + local_id.encode(s)?; + Ok(()) } } @@ -122,7 +120,7 @@ impl fmt::Display for HirId { } } -// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module +// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module. mod item_local_id_inner { use rustc_data_structures::indexed_vec::Idx; use rustc_macros::HashStable; @@ -192,7 +190,7 @@ pub enum ParamName { Fresh(usize), /// Indicates an illegal name was given and an error has been - /// repored (so we should squelch other derived errors). Occurs + /// reported (so we should squelch other derived errors). Occurs /// when, e.g., `'_` is used in the wrong place. Error, } @@ -202,7 +200,7 @@ impl ParamName { match *self { ParamName::Plain(ident) => ident, ParamName::Fresh(_) | - ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime), + ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime), } } @@ -222,6 +220,19 @@ pub enum LifetimeName { /// User wrote nothing (e.g., the lifetime in `&u32`). Implicit, + /// Implicit lifetime in a context like `dyn Foo`. This is + /// distinguished from implicit lifetimes elsewhere because the + /// lifetime that they default to must appear elsewhere within the + /// enclosing type. This means that, in an `impl Trait` context, we + /// don't have to create a parameter for them. That is, `impl + /// Trait` expands to an opaque type like `type + /// Foo<'a> = impl Trait`, but `impl Trait` expands to `type Foo = impl Trait`. The latter uses `ImplicitObjectLifetimeDefault` so + /// that surrounding code knows not to create a lifetime + /// parameter. + ImplicitObjectLifetimeDefault, + /// Indicates an error during lowering (usually `'_` in wrong place) /// that was already reported. Error, @@ -236,16 +247,20 @@ pub enum LifetimeName { impl LifetimeName { pub fn ident(&self) -> Ident { match *self { - LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(), - LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime), - LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime), + LifetimeName::ImplicitObjectLifetimeDefault + | LifetimeName::Implicit + | LifetimeName::Error => Ident::invalid(), + LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), + LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), LifetimeName::Param(param_name) => param_name.ident(), } } pub fn is_elided(&self) -> bool { match self { - LifetimeName::Implicit | LifetimeName::Underscore => true, + LifetimeName::ImplicitObjectLifetimeDefault + | LifetimeName::Implicit + | LifetimeName::Underscore => true, // It might seem surprising that `Fresh(_)` counts as // *not* elided -- but this is because, as far as the code @@ -730,7 +745,7 @@ pub struct Crate { // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: HirVec, - // N.B., we use a BTreeMap here so that `visit_all_items` iterates + // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates // over the ids in increasing order. In principle it should not // matter what order we visit things in, but in *practice* it // does, because it can affect the order in which errors are @@ -877,11 +892,12 @@ impl Pat { match self.node { PatKind::Binding(.., Some(ref p)) => p.walk_(it), PatKind::Struct(_, ref fields, _) => { - fields.iter().all(|field| field.node.pat.walk_(it)) + fields.iter().all(|field| field.pat.walk_(it)) } PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { s.iter().all(|p| p.walk_(it)) } + PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)), PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { s.walk_(it) } @@ -923,6 +939,7 @@ pub struct FieldPat { /// The pattern the field is destructured to. pub pat: P, pub is_shorthand: bool, + pub span: Span, } /// Explicit binding annotations given in the HIR for a binding. Note @@ -968,13 +985,17 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(QPath, HirVec>, bool), + Struct(QPath, HirVec, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// `0 <= position <= subpats.len()` TupleStruct(QPath, HirVec>, Option), + /// An or-pattern `A | B | C`. + /// Invariant: `pats.len() >= 2`. + Or(HirVec>), + /// A path pattern for an unit struct/variant or a (maybe-associated) constant. Path(QPath), @@ -1008,7 +1029,7 @@ pub enum Mutability { } impl Mutability { - /// Returns `MutMutable` only if both arguments are mutable. + /// Returns `MutMutable` only if both `self` and `other` are mutable. pub fn and(self, other: Self) -> Self { match self { MutMutable => other, @@ -1302,7 +1323,7 @@ pub struct BodyId { /// /// Here, the `Body` associated with `foo()` would contain: /// -/// - an `arguments` array containing the `(x, y)` pattern +/// - an `params` array containing the `(x, y)` pattern /// - a `value` containing the `x + y` expression (maybe wrapped in a block) /// - `generator_kind` would be `None` /// @@ -1310,7 +1331,7 @@ pub struct BodyId { /// map using `body_owner_def_id()`. #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Body { - pub arguments: HirVec, + pub params: HirVec, pub value: Expr, pub generator_kind: Option, } @@ -1381,13 +1402,13 @@ pub struct AnonConst { pub body: BodyId, } -/// An expression +/// An expression. #[derive(RustcEncodable, RustcDecodable)] pub struct Expr { - pub span: Span, + pub hir_id: HirId, pub node: ExprKind, pub attrs: ThinVec, - pub hir_id: HirId, + pub span: Span, } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -1541,7 +1562,7 @@ pub enum ExprKind { Match(P, HirVec, MatchSource), /// A closure (e.g., `move |a, b, c| {a + b + c}`). /// - /// The final span is the span of the argument block `|...|`. + /// The `Span` is the argument block `|...|`. /// /// This may also be a generator literal or an `async block` as indicated by the /// `Option`. @@ -1622,7 +1643,7 @@ pub enum LocalSource { /// A desugared `for _ in _ { .. }` loop. ForLoopDesugar, /// When lowering async functions, we create locals within the `async move` so that - /// all arguments are dropped after the future is polled. + /// all parameters are dropped after the future is polled. /// /// ```ignore (pseudo-Rust) /// async fn foo( @ x: Type) { @@ -1918,7 +1939,7 @@ pub struct BareFnTy { pub abi: Abi, pub generic_params: HirVec, pub decl: P, - pub arg_names: HirVec, + pub param_names: HirVec, } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2003,13 +2024,11 @@ pub struct InlineAsm { pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, - #[stable_hasher(ignore)] // This is used for error reporting - pub ctxt: SyntaxContext, } -/// Represents an argument in a function header. +/// Represents a parameter in a function header. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] -pub struct Arg { +pub struct Param { pub attrs: HirVec, pub hir_id: HirId, pub pat: P, @@ -2019,9 +2038,9 @@ pub struct Arg { /// Represents the header (not the body) of a function declaration. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct FnDecl { - /// The types of the function's arguments. + /// The types of the function's parameters. /// - /// Additional argument data is stored in the function's [body](Body::arguments). + /// Additional argument data is stored in the function's [body](Body::parameters). pub inputs: HirVec, pub output: FunctionRetTy, pub c_variadic: bool, @@ -2183,8 +2202,6 @@ pub struct ForeignMod { #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GlobalAsm { pub asm: Symbol, - #[stable_hasher(ignore)] // This is used for error reporting - pub ctxt: SyntaxContext, } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2193,7 +2210,7 @@ pub struct EnumDef { } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] -pub struct VariantKind { +pub struct Variant { /// Name of the variant. #[stable_hasher(project(name))] pub ident: Ident, @@ -2205,10 +2222,10 @@ pub struct VariantKind { pub data: VariantData, /// Explicit discriminant (e.g., `Foo = 1`). pub disr_expr: Option, + /// Span + pub span: Span } -pub type Variant = Spanned; - #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. @@ -2404,37 +2421,37 @@ pub enum ItemKind { /// /// or just /// - /// `use foo::bar::baz;` (with `as baz` implicitly on the right) + /// `use foo::bar::baz;` (with `as baz` implicitly on the right). Use(P, UseKind), - /// A `static` item + /// A `static` item. Static(P, Mutability, BodyId), - /// A `const` item + /// A `const` item. Const(P, BodyId), - /// A function declaration + /// A function declaration. Fn(P, FnHeader, Generics, BodyId), - /// A module + /// A module. Mod(Mod), - /// An external module + /// An external module. ForeignMod(ForeignMod), - /// Module-level inline assembly (from global_asm!) + /// Module-level inline assembly (from `global_asm!`). GlobalAsm(P), - /// A type alias, e.g., `type Foo = Bar` + /// A type alias, e.g., `type Foo = Bar`. TyAlias(P, Generics), - /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;` + /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. OpaqueTy(OpaqueTy), - /// An enum definition, e.g., `enum Foo {C, D}` + /// An enum definition, e.g., `enum Foo {C, D}`. Enum(EnumDef, Generics), - /// A struct definition, e.g., `struct Foo {x: A}` + /// A struct definition, e.g., `struct Foo {x: A}`. Struct(VariantData, Generics), - /// A union definition, e.g., `union Foo {x: A, y: B}` + /// A union definition, e.g., `union Foo {x: A, y: B}`. Union(VariantData, Generics), - /// A trait definition + /// A trait definition. Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec), - /// A trait alias + /// A trait alias. TraitAlias(Generics, GenericBounds), - /// An implementation, eg `impl Trait for Foo { .. }` + /// An implementation, e.g., `impl Trait for Foo { .. }`. Impl(Unsafety, ImplPolarity, Defaultness, @@ -2703,7 +2720,7 @@ impl CodegenFnAttrs { #[derive(Copy, Clone, Debug)] pub enum Node<'hir> { - Arg(&'hir Arg), + Param(&'hir Param), Item(&'hir Item), ForeignItem(&'hir ForeignItem), TraitItem(&'hir TraitItem), @@ -2733,3 +2750,15 @@ pub enum Node<'hir> { Crate, } + +impl Node<'_> { + pub fn ident(&self) -> Option { + match self { + Node::TraitItem(TraitItem { ident, .. }) | + Node::ImplItem(ImplItem { ident, .. }) | + Node::ForeignItem(ForeignItem { ident, .. }) | + Node::Item(Item { ident, .. }) => Some(*ident), + _ => None, + } + } +} diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 11ba512053..cfbfb5eceb 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -33,7 +33,7 @@ pub enum Nested { TraitItem(hir::TraitItemId), ImplItem(hir::ImplItemId), Body(hir::BodyId), - BodyArgPat(hir::BodyId, usize) + BodyParamPat(hir::BodyId, usize) } pub trait PpAnn { @@ -62,7 +62,7 @@ impl PpAnn for hir::Crate { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) } } } @@ -318,7 +318,7 @@ impl<'a> State<'a> { } hir::TyKind::BareFn(ref f) => { self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params, - &f.arg_names[..]); + &f.param_names[..]); } hir::TyKind::Def(..) => {}, hir::TyKind::Path(ref qpath) => { @@ -737,7 +737,7 @@ impl<'a> State<'a> { for v in variants { self.space_if_not_bol(); self.maybe_print_comment(v.span.lo()); - self.print_outer_attributes(&v.node.attrs); + self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); self.s.word(","); @@ -829,8 +829,8 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant) { self.head(""); let generics = hir::Generics::empty(); - self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false); - if let Some(ref d) = v.node.disr_expr { + self.print_struct(&v.data, &generics, v.ident.name, v.span, false); + if let Some(ref d) = v.disr_expr { self.s.space(); self.word_space("="); self.print_anon_const(d); @@ -1290,14 +1290,14 @@ impl<'a> State<'a> { hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => { self.print_capture_clause(capture_clause); - self.print_closure_args(&decl, body); + self.print_closure_params(&decl, body); self.s.space(); - // this is a bare expression + // This is a bare expression. self.ann.nested(self, Nested::Body(body)); self.end(); // need to close a box - // a box will be closed by print_expr, but we didn't want an overall + // A box will be closed by `print_expr`, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. self.ibox(0); @@ -1307,9 +1307,9 @@ impl<'a> State<'a> { self.print_ident(label.ident); self.word_space(":"); } - // containing cbox, will be closed by print-block at } + // containing cbox, will be closed by print-block at `}` self.cbox(INDENT_UNIT); - // head-box, will be closed by print-block after { + // head-box, will be closed by print-block after `{` self.ibox(0); self.print_block(&blk); } @@ -1457,7 +1457,7 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) { - self.print_ident(ast::Ident::with_empty_ctxt(name)) + self.print_ident(ast::Ident::with_dummy_span(name)) } pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) { @@ -1670,14 +1670,14 @@ impl<'a> State<'a> { &fields[..], |s, f| { s.cbox(INDENT_UNIT); - if !f.node.is_shorthand { - s.print_ident(f.node.ident); + if !f.is_shorthand { + s.print_ident(f.ident); s.word_nbsp(":"); } - s.print_pat(&f.node.pat); + s.print_pat(&f.pat); s.end() }, - |f| f.node.pat.span); + |f| f.pat.span); if etc { if !fields.is_empty() { self.word_space(","); @@ -1687,6 +1687,9 @@ impl<'a> State<'a> { self.s.space(); self.s.word("}"); } + PatKind::Or(ref pats) => { + self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p)); + } PatKind::Tuple(ref elts, ddpos) => { self.popen(); if let Some(ddpos) = ddpos { @@ -1756,7 +1759,7 @@ impl<'a> State<'a> { self.word_space(","); } if let PatKind::Wild = p.node { - // Print nothing + // Print nothing. } else { self.print_pat(&p); } @@ -1772,7 +1775,7 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Pat(pat)) } - pub fn print_arg(&mut self, arg: &hir::Arg) { + pub fn print_param(&mut self, arg: &hir::Param) { self.print_outer_attributes(&arg.attrs); self.print_pat(&arg.pat); } @@ -1861,7 +1864,7 @@ impl<'a> State<'a> { s.s.word(":"); s.s.space(); } else if let Some(body_id) = body_id { - s.ann.nested(s, Nested::BodyArgPat(body_id, i)); + s.ann.nested(s, Nested::BodyParamPat(body_id, i)); s.s.word(":"); s.s.space(); } @@ -1878,17 +1881,17 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause) } - fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) { + fn print_closure_params(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) { self.s.word("|"); let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); - s.ann.nested(s, Nested::BodyArgPat(body_id, i)); + s.ann.nested(s, Nested::BodyParamPat(body_id, i)); i += 1; if let hir::TyKind::Infer = ty.node { - // Print nothing + // Print nothing. } else { s.s.word(":"); s.s.space(); @@ -2218,7 +2221,6 @@ impl<'a> State<'a> { } } -// Dup'ed from parse::classify, but adapted for the HIR. /// Does this expression require a semicolon to be treated /// as a statement? The negation of this: 'can this expression /// be used as a statement without a semicolon' -- is used @@ -2226,6 +2228,8 @@ impl<'a> State<'a> { /// if true {...} else {...} /// |x| 5 /// isn't parsed as (if true {...} else {...} | x) | 5 +// +// Duplicated from `parse::classify`, but adapted for the HIR. fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { match e.node { hir::ExprKind::Match(..) | @@ -2235,7 +2239,7 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { } } -/// this statement requires a semicolon after it. +/// This statement requires a semicolon after it. /// note that in one case (stmt_semi), we've already /// seen the semicolon, and thus don't need another. fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool { @@ -2274,7 +2278,7 @@ fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp { } } -/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any +/// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { @@ -2284,7 +2288,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { hir::ExprKind::Assign(ref lhs, ref rhs) | hir::ExprKind::AssignOp(_, ref lhs, ref rhs) | hir::ExprKind::Binary(_, ref lhs, ref rhs) => { - // X { y: 1 } + X { y: 2 } + // `X { y: 1 } + X { y: 2 }` contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } hir::ExprKind::Unary(_, ref x) | @@ -2292,12 +2296,12 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { hir::ExprKind::Type(ref x, _) | hir::ExprKind::Field(ref x, _) | hir::ExprKind::Index(ref x, _) => { - // &X { y: 1 }, X { y: 1 }.y + // `&X { y: 1 }, X { y: 1 }.y` contains_exterior_struct_lit(&x) } hir::ExprKind::MethodCall(.., ref exprs) => { - // X { y: 1 }.bar(...) + // `X { y: 1 }.bar(...)` contains_exterior_struct_lit(&exprs[0]) } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index ae7d82c202..182a9ade8c 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -12,7 +12,6 @@ use std::hash as std_hash; use std::cell::RefCell; use syntax::ast; - use syntax::source_map::SourceMap; use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::Symbol; @@ -20,9 +19,9 @@ use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene; -use rustc_data_structures::stable_hasher::{HashStable, - StableHasher, StableHasherResult, - ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + HashStable, StableHasher, StableHasherResult, ToStableHashKey, +}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use smallvec::SmallVec; @@ -32,9 +31,9 @@ fn compute_ignored_attr_names() -> FxHashSet { } /// This is the context state available during incr. comp. hashing. It contains -/// enough information to transform DefIds and HirIds into stable DefPaths (i.e. -/// a reference to the TyCtxt) and it holds a few caches for speeding up various -/// things (e.g., each DefId/DefPath is only hashed once). +/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., +/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various +/// things (e.g., each `DefId`/`DefPath` is only hashed once). #[derive(Clone)] pub struct StableHashingContext<'a> { sess: &'a Session, @@ -46,7 +45,7 @@ pub struct StableHashingContext<'a> { node_id_hashing_mode: NodeIdHashingMode, // Very often, we are hashing something that does not need the - // CachingSourceMapView, so we initialize it lazily. + // `CachingSourceMapView`, so we initialize it lazily. raw_source_map: &'a SourceMap, caching_source_map: Option>, } @@ -57,24 +56,24 @@ pub enum NodeIdHashingMode { HashDefPath, } -/// The BodyResolver allows to map a BodyId to the corresponding hir::Body. -/// We could also just store a plain reference to the hir::Crate but we want +/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. +/// We could also just store a plain reference to the `hir::Crate` but we want /// to avoid that the crate is used to get untracked access to all of the HIR. #[derive(Clone, Copy)] struct BodyResolver<'tcx>(&'tcx hir::Crate); impl<'tcx> BodyResolver<'tcx> { - // Return a reference to the hir::Body with the given BodyId. - // DOES NOT DO ANY TRACKING, use carefully. + /// Returns a reference to the `hir::Body` with the given `BodyId`. + /// **Does not do any tracking**; use carefully. fn body(self, id: hir::BodyId) -> &'tcx hir::Body { self.0.body(id) } } impl<'a> StableHashingContext<'a> { - // The `krate` here is only used for mapping BodyIds to Bodies. - // Don't use it for anything else or you'll run the risk of - // leaking data out of the tracking system. + /// The `krate` here is only used for mapping `BodyId`s to `Body`s. + /// Don't use it for anything else or you'll run the risk of + /// leaking data out of the tracking system. #[inline] pub fn new(sess: &'a Session, krate: &'a hir::Crate, @@ -217,9 +216,7 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { } } -impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> { -} - +impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} impl<'a> HashStable> for hir::BodyId { fn hash_stable(&self, @@ -292,16 +289,15 @@ impl<'a> ToStableHashKey> for ast::NodeId { } impl<'a> HashStable> for Span { - - // Hash a span in a stable way. We can't directly hash the span's BytePos - // fields (that would be similar to hashing pointers, since those are just - // offsets into the SourceMap). Instead, we hash the (file name, line, column) - // triple, which stays the same even if the containing SourceFile has moved - // within the SourceMap. - // Also note that we are hashing byte offsets for the column, not unicode - // codepoint offsets. For the purpose of the hash that's sufficient. - // Also, hashing filenames is expensive so we avoid doing it twice when the - // span starts and ends in the same file, which is almost always the case. + /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` + /// fields (that would be similar to hashing pointers, since those are just + /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column) + /// triple, which stays the same even if the containing `SourceFile` has moved + /// within the `SourceMap`. + /// Also note that we are hashing byte offsets for the column, not unicode + /// codepoint offsets. For the purpose of the hash that's sufficient. + /// Also, hashing filenames is expensive so we avoid doing it twice when the + /// span starts and ends in the same file, which is almost always the case. fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -340,7 +336,7 @@ impl<'a> HashStable> for Span { } std_hash::Hash::hash(&TAG_VALID_SPAN, hasher); - // We truncate the stable_id hash and line and col numbers. The chances + // We truncate the stable ID hash and line and column numbers. The chances // of causing a collision this way should be minimal. std_hash::Hash::hash(&(file_lo.name_hash as u64), hasher); @@ -350,7 +346,7 @@ impl<'a> HashStable> for Span { let line_col_len = col | line | len; std_hash::Hash::hash(&line_col_len, hasher); - if span.ctxt == SyntaxContext::empty() { + if span.ctxt == SyntaxContext::root() { TAG_NO_EXPANSION.hash_stable(hcx, hasher); } else { TAG_EXPANSION.hash_stable(hcx, hasher); @@ -370,7 +366,7 @@ impl<'a> HashStable> for Span { } let mut hasher = StableHasher::new(); - expn_id.expn_info().hash_stable(hcx, &mut hasher); + expn_id.expn_data().hash_stable(hcx, &mut hasher); let sub_hash: Fingerprint = hasher.finish(); let sub_hash = sub_hash.to_smaller_hash(); cache.borrow_mut().insert(expn_id, sub_hash); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 30d76f240d..6e6492d042 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -5,8 +5,10 @@ use crate::hir; use crate::hir::map::DefPathHash; use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; -use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, - StableHasher, StableHasherResult}; + +use rustc_data_structures::stable_hasher::{ + HashStable, ToStableHashKey, StableHasher, StableHasherResult, +}; use smallvec::SmallVec; use std::mem; use syntax::ast; @@ -82,9 +84,9 @@ for hir::ItemLocalId { } } -// The following implementations of HashStable for ItemId, TraitItemId, and -// ImplItemId deserve special attention. Normally we do not hash NodeIds within -// the HIR, since they just signify a HIR nodes own path. But ItemId et al +// The following implementations of HashStable for `ItemId`, `TraitItemId`, and +// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within +// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al // are used when another item in the HIR is *referenced* and we certainly // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". @@ -131,7 +133,6 @@ impl<'a> HashStable> for hir::ImplItemId { } } - impl_stable_hash_for!(struct ast::Label { ident }); @@ -153,8 +154,6 @@ impl<'a> HashStable> for hir::Ty { } } -impl_stable_hash_for_spanned!(hir::FieldPat); - impl_stable_hash_for_spanned!(hir::BinOpKind); impl_stable_hash_for!(struct hir::Stmt { @@ -187,8 +186,6 @@ impl<'a> HashStable> for hir::Expr { impl_stable_hash_for_spanned!(usize); -impl_stable_hash_for_spanned!(ast::Ident); - impl_stable_hash_for!(struct ast::Ident { name, span, @@ -245,7 +242,7 @@ impl<'a> HashStable> for hir::ImplItem { } } -impl_stable_hash_for!(enum ::syntax::ast::CrateSugar { +impl_stable_hash_for!(enum ast::CrateSugar { JustCrate, PubCrate, }); @@ -304,7 +301,7 @@ impl<'a> HashStable> for hir::Mod { } } -impl_stable_hash_for_spanned!(hir::VariantKind); +impl_stable_hash_for_spanned!(hir::Variant); impl<'a> HashStable> for hir::Item { @@ -335,13 +332,13 @@ impl<'a> HashStable> for hir::Body { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { - arguments, + params, value, generator_kind, } = self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { - arguments.hash_stable(hcx, hasher); + params.hash_stable(hcx, hasher); value.hash_stable(hcx, hasher); generator_kind.hash_stable(hcx, hasher); }); @@ -369,8 +366,7 @@ impl<'a> HashStable> for hir::def_id::DefIndex { } } -impl<'a> ToStableHashKey> -for hir::def_id::DefIndex { +impl<'a> ToStableHashKey> for hir::def_id::DefIndex { type KeyType = DefPathHash; #[inline] diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index daa69efe28..a33181e592 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -9,7 +9,7 @@ use std::mem; use syntax::ast; use syntax::feature_gate; use syntax::parse::token; -use syntax::symbol::{InternedString, LocalInternedString}; +use syntax::symbol::InternedString; use syntax::tokenstream; use syntax_pos::SourceFile; @@ -39,27 +39,6 @@ impl<'a> ToStableHashKey> for InternedString { } } -impl<'a> HashStable> for LocalInternedString { - #[inline] - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - let s: &str = &**self; - s.hash_stable(hcx, hasher); - } -} - -impl<'a> ToStableHashKey> for LocalInternedString { - type KeyType = LocalInternedString; - - #[inline] - fn to_stable_hash_key(&self, - _: &StableHashingContext<'a>) - -> LocalInternedString { - self.clone() - } -} - impl<'a> HashStable> for ast::Name { #[inline] fn hash_stable(&self, @@ -398,11 +377,11 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency { Opaque, }); -impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { - call_site, +impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData { kind, + parent -> _, + call_site, def_site, - default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, @@ -412,9 +391,17 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind { Root, Macro(kind, descr), + AstPass(kind), Desugaring(kind) }); +impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass { + StdImports, + TestHarness, + ProcMacroHarness, + PluginMacroDefs, +}); + impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind { CondTemporary, Async, diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 0ddc9211f9..f230c53728 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -168,25 +168,21 @@ impl<'a> HashStable> for mir::interpret::AllocId { } } -// Allocations treat their relocations specially -impl<'a> HashStable> for mir::interpret::Allocation { +// `Relocations` with default type parameters is a sorted map. +impl<'a, Tag> HashStable> +for mir::interpret::Relocations +where + Tag: HashStable>, +{ fn hash_stable( &self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher, ) { - let mir::interpret::Allocation { - bytes, relocations, undef_mask, align, mutability, - extra: _, - } = self; - bytes.hash_stable(hcx, hasher); - relocations.len().hash_stable(hcx, hasher); - for reloc in relocations.iter() { + self.len().hash_stable(hcx, hasher); + for reloc in self.iter() { reloc.hash_stable(hcx, hasher); } - undef_mask.hash_stable(hcx, hasher); - align.hash_stable(hcx, hasher); - mutability.hash_stable(hcx, hasher); } } @@ -208,7 +204,7 @@ impl<'a> HashStable> for ty::TyVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // TyVid values are confined to an inference context and hence + // `TyVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) } @@ -218,7 +214,7 @@ impl<'a> HashStable> for ty::IntVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // IntVid values are confined to an inference context and hence + // `IntVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) } @@ -228,7 +224,7 @@ impl<'a> HashStable> for ty::FloatVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // FloatVid values are confined to an inference context and hence + // `FloatVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 4a9b68f243..966c581017 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -30,6 +30,7 @@ use super::sub::Sub; use super::type_variable::TypeVariableValue; use super::unify_key::{ConstVarValue, ConstVariableValue}; use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use super::unify_key::replace_if_possible; use crate::hir::def_id::DefId; use crate::mir::interpret::ConstValue; @@ -127,6 +128,12 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { where R: TypeRelation<'tcx>, { + debug!("{}.consts({:?}, {:?})", relation.tag(), a, b); + if a == b { return Ok(a); } + + let a = replace_if_possible(self.const_unification_table.borrow_mut(), a); + let b = replace_if_possible(self.const_unification_table.borrow_mut(), b); + let a_is_expected = relation.a_is_expected(); match (a.val, b.val) { diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 5dfa0d29da..6065387647 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -1,14 +1,12 @@ -use super::combine::{CombineFields, RelationDir, const_unification_error}; +use super::combine::{CombineFields, RelationDir}; use super::Subtype; use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, TyCtxt, InferConst}; +use crate::ty::{self, Ty, TyCtxt}; use crate::ty::TyVar; use crate::ty::subst::SubstsRef; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use crate::mir::interpret::ConstValue; -use crate::infer::unify_key::replace_if_possible; /// Ensures `a` is made equal to `b`. Returns `a` on success. pub struct Equate<'combine, 'infcx, 'tcx> { @@ -97,7 +95,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { self.tag(), a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); self.fields.infcx.borrow_region_constraints() .make_eqregion(origin, a, b); Ok(a) @@ -108,39 +106,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } - - let infcx = self.fields.infcx; - let a = replace_if_possible(infcx.const_unification_table.borrow_mut(), a); - let b = replace_if_possible(infcx.const_unification_table.borrow_mut(), b); - let a_is_expected = self.a_is_expected(); - - match (a.val, b.val) { - (ConstValue::Infer(InferConst::Var(a_vid)), - ConstValue::Infer(InferConst::Var(b_vid))) => { - infcx.const_unification_table - .borrow_mut() - .unify_var_var(a_vid, b_vid) - .map_err(|e| const_unification_error(a_is_expected, e))?; - return Ok(a); - } - - (ConstValue::Infer(InferConst::Var(a_id)), _) => { - self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?; - return Ok(a); - } - - (_, ConstValue::Infer(InferConst::Var(b_id))) => { - self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?; - return Ok(a); - } - - _ => {} - } - - self.fields.infcx.super_combine_consts(self, a, b)?; - Ok(a) + self.fields.infcx.super_combine_consts(self, a, b) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 2ffcd2c4ac..0b6740d7bb 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,8 @@ use crate::hir::def_id::DefId; use crate::hir::Node; use crate::infer::opaque_types; use crate::middle::region; -use crate::traits::{ObligationCause, ObligationCauseCode}; +use crate::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; +use crate::traits::{ObligationCauseCode}; use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; @@ -624,13 +625,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } } - ObligationCauseCode::MatchExpressionArm { + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { source, ref prior_arms, last_ty, discrim_hir_id, .. - } => match source { + }) => match source { hir::MatchSource::IfLetDesugar { .. } => { let msg = "`if let` arms have incompatible types"; err.span_label(cause.span, msg); @@ -681,7 +682,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } }, - ObligationCauseCode::IfExpression { then, outer, semicolon } => { + ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => { err.span_label(then, "expected because of this"); outer.map(|sp| err.span_label(sp, "if and else have incompatible types")); if let Some(sp) = semicolon { @@ -1118,7 +1119,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Some((expected, found)) => Some((expected, found)), None => { // Derived error. Cancel the emitter. - self.tcx.sess.diagnostic().cancel(diag); + diag.cancel(); return; } }; @@ -1136,12 +1137,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { (&TypeError::Sorts(ref values), false, true) => { + let sort_string = | a_type: Ty<'tcx> | + if let ty::Opaque(def_id, _) = a_type.sty { + format!(" (opaque type at {})", self.tcx.sess.source_map() + .mk_substr_filename(self.tcx.def_span(def_id))) + } else { + format!(" ({})", a_type.sort_string(self.tcx)) + }; diag.note_expected_found_extra( &"type", expected, found, - &format!(" ({})", values.expected.sort_string(self.tcx)), - &format!(" ({})", values.found.sort_string(self.tcx)), + &sort_string(values.expected), + &sort_string(values.found), ); } (_, false, _) => { @@ -1329,7 +1337,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(did); // Account for the case where `did` corresponds to `Self`, which doesn't have // the expected type argument. - if !param.is_self() { + if !(generics.has_self && param.index == 0) { let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir(); hir.as_local_hir_id(type_param.def_id).map(|id| { @@ -1337,7 +1345,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let mut has_bounds = false; - if let Node::GenericParam(ref param) = hir.get(id) { + if let Node::GenericParam(param) = hir.get(id) { has_bounds = !param.bounds.is_empty(); } let sp = hir.span(id); @@ -1615,19 +1623,21 @@ impl<'tcx> ObligationCause<'tcx> { use crate::traits::ObligationCauseCode::*; match self.code { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), - MatchExpressionArm { source, .. } => Error0308(match source { - hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types", - hir::MatchSource::TryDesugar => { - "try expression alternatives have incompatible types" - } - _ => "match arms have incompatible types", - }), + MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => + Error0308(match source { + hir::MatchSource::IfLetDesugar { .. } => + "`if let` arms have incompatible types", + hir::MatchSource::TryDesugar => { + "try expression alternatives have incompatible types" + } + _ => "match arms have incompatible types", + }), IfExpression { .. } => Error0308("if and else have incompatible types"), IfExpressionWithNoElse => Error0317("if may be missing an else clause"), MainFunctionType => Error0580("main function has wrong type"), StartFunctionType => Error0308("start function has wrong type"), IntrinsicType => Error0308("intrinsic has wrong type"), - MethodReceiver => Error0308("mismatched method receiver"), + MethodReceiver => Error0308("mismatched `self` parameter type"), // In the case where we have no more specific thing to // say, also take a look at the error code, maybe we can @@ -1636,6 +1646,9 @@ impl<'tcx> ObligationCause<'tcx> { TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => { Error0644("closure/generator type that references itself") } + TypeError::IntrinsicCast => { + Error0308("cannot coerce intrinsics to function pointers") + } _ => Error0308("mismatched types"), }, } @@ -1646,11 +1659,11 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { CompareImplMethodObligation { .. } => "method type is compatible with trait", ExprAssignable => "expression is assignable", - MatchExpressionArm { source, .. } => match source { + MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source { hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types", _ => "match arms have compatible types", }, - IfExpression { .. } => "if and else have compatible types", + IfExpression { .. } => "if and else have incompatible types", IfExpressionWithNoElse => "if missing an else returns ()", MainFunctionType => "`main` function has the correct type", StartFunctionType => "`start` function has the correct type", diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 770d515577..7068fe3601 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -1,5 +1,5 @@ use crate::hir::def::Namespace; -use crate::hir::{self, Local, Pat, Body, HirId}; +use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::infer::InferCtxt; use crate::infer::type_variable::TypeVariableOriginKind; @@ -7,7 +7,7 @@ use crate::ty::{self, Ty, Infer, TyVar}; use crate::ty::print::Print; use syntax::source_map::DesugaringKind; use syntax_pos::Span; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; struct FindLocalByTypeVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, @@ -16,9 +16,26 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { found_local_pattern: Option<&'tcx Pat>, found_arg_pattern: Option<&'tcx Pat>, found_ty: Option>, + found_closure: Option<&'tcx ExprKind>, } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { + fn new( + infcx: &'a InferCtxt<'a, 'tcx>, + target_ty: Ty<'tcx>, + hir_map: &'a hir::map::Map<'tcx>, + ) -> Self { + Self { + infcx, + target_ty, + hir_map, + found_local_pattern: None, + found_arg_pattern: None, + found_ty: None, + found_closure: None, + } + } + fn node_matches_type(&mut self, hir_id: HirId) -> Option> { let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { tables.borrow().node_type_opt(hir_id) @@ -61,17 +78,71 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { } fn visit_body(&mut self, body: &'tcx Body) { - for argument in &body.arguments { + for param in &body.params { if let (None, Some(ty)) = ( self.found_arg_pattern, - self.node_matches_type(argument.hir_id), + self.node_matches_type(param.hir_id), ) { - self.found_arg_pattern = Some(&*argument.pat); + self.found_arg_pattern = Some(&*param.pat); self.found_ty = Some(ty); } } intravisit::walk_body(self, body); } + + fn visit_expr(&mut self, expr: &'tcx Expr) { + if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = ( + &expr.node, + self.node_matches_type(expr.hir_id), + ) { + self.found_closure = Some(&expr.node); + } + intravisit::walk_expr(self, expr); + } +} + +/// Suggest giving an appropriate return type to a closure expression. +fn closure_return_type_suggestion( + span: Span, + err: &mut DiagnosticBuilder<'_>, + output: &FunctionRetTy, + body: &Body, + name: &str, + ret: &str, +) { + let (arrow, post) = match output { + FunctionRetTy::DefaultReturn(_) => ("-> ", " "), + _ => ("", ""), + }; + let suggestion = match body.value.node { + ExprKind::Block(..) => { + vec![(output.span(), format!("{}{}{}", arrow, ret, post))] + } + _ => { + vec![ + (output.span(), format!("{}{}{}{{ ", arrow, ret, post)), + (body.value.span.shrink_to_hi(), " }".to_string()), + ] + } + }; + err.multipart_suggestion( + "give this closure an explicit return type without `_` placeholders", + suggestion, + Applicability::HasPlaceholders, + ); + err.span_label(span, InferCtxt::missing_type_msg(&name)); +} + +/// Given a closure signature, return a `String` containing a list of all its argument types. +fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { + fn_sig.inputs() + .skip_binder() + .iter() + .next() + .map(|args| args.tuple_fields() + .map(|arg| arg.to_string()) + .collect::>().join(", ")) + .unwrap_or_default() } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { @@ -79,12 +150,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, ty: Ty<'tcx>, highlight: Option, - ) -> String { + ) -> (String, Option) { if let ty::Infer(ty::TyVar(ty_vid)) = ty.sty { let ty_vars = self.type_variables.borrow(); - if let TypeVariableOriginKind::TypeParameterDefinition(name) = - ty_vars.var_origin(ty_vid).kind { - return name.to_string(); + let var_origin = ty_vars.var_origin(ty_vid); + if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { + return (name.to_string(), Some(var_origin.span)); } } @@ -94,7 +165,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ty.print(printer); - s + (s, None) } pub fn need_type_info_err( @@ -104,18 +175,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let name = self.extract_type_name(&ty, None); - - let mut err_span = span; + let (name, name_sp) = self.extract_type_name(&ty, None); - let mut local_visitor = FindLocalByTypeVisitor { - infcx: &self, - target_ty: ty, - hir_map: &self.tcx.hir(), - found_local_pattern: None, - found_arg_pattern: None, - found_ty: None, - }; + let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); @@ -136,6 +198,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let expr = self.tcx.hir().expect_expr(body_id.hir_id); local_visitor.visit_expr(expr); } + let err_span = if let Some(pattern) = local_visitor.found_arg_pattern { + pattern.span + } else if let Some(span) = name_sp { + // `span` here lets us point at `sum` instead of the entire right hand side expr: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | ^^^ cannot infer type for `S` + span + } else { + span + }; + + let is_named_and_not_impl_trait = |ty: Ty<'_>| { + &ty.to_string() != "_" && + // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527 + (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) + }; + + let ty_msg = match local_visitor.found_ty { + Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + let fn_sig = substs.closure_sig(*def_id, self.tcx); + let args = closure_args(&fn_sig); + let ret = fn_sig.output().skip_binder().to_string(); + format!(" for the closure `fn({}) -> {}`", args, ret) + } + Some(ty) if is_named_and_not_impl_trait(ty) => { + let ty = ty_to_string(ty); + format!(" for `{}`", ty) + } + _ => String::new(), + }; // When `name` corresponds to a type argument, show the path of the full type we're // trying to infer. In the following example, `ty_msg` contains @@ -150,27 +245,58 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | consider giving `b` the explicit type `std::result::Result`, where // | the type parameter `E` is specified // ``` - let (ty_msg, suffix) = match &local_visitor.found_ty { - Some(ty) if &ty.to_string() != "_" && name == "_" => { + let mut err = struct_span_err!( + self.tcx.sess, + err_span, + E0282, + "type annotations needed{}", + ty_msg, + ); + + let suffix = match local_visitor.found_ty { + Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + let fn_sig = substs.closure_sig(*def_id, self.tcx); + let ret = fn_sig.output().skip_binder().to_string(); + + if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure { + if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) { + closure_return_type_suggestion( + span, + &mut err, + &decl.output, + &body, + &name, + &ret, + ); + // We don't want to give the other suggestions when the problem is the + // closure return type. + return err; + } + } + + // This shouldn't be reachable, but just in case we leave a reasonable fallback. + let args = closure_args(&fn_sig); + // This suggestion is incomplete, as the user will get further type inference + // errors due to the `_` placeholders and the introduction of `Box`, but it does + // nudge them in the right direction. + format!("a boxed closure type like `Box {}>`", args, ret) + } + Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => { let ty = ty_to_string(ty); - (format!(" for `{}`", ty), - format!("the explicit type `{}`, with the type parameters specified", ty)) + format!("the explicit type `{}`, with the type parameters specified", ty) } - Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => { + Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => { let ty = ty_to_string(ty); - (format!(" for `{}`", ty), - format!( - "the explicit type `{}`, where the type parameter `{}` is specified", + format!( + "the explicit type `{}`, where the type parameter `{}` is specified", ty, name, - )) + ) } - _ => (String::new(), "a type".to_owned()), + _ => "a type".to_string(), }; - let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))]; if let Some(pattern) = local_visitor.found_arg_pattern { - err_span = pattern.span; // We don't want to show the default label for closures. // // So, before clearing, the output would look something like this: @@ -187,39 +313,48 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // ^ consider giving this closure parameter the type `[_; 0]` // with the type parameter `_` specified // ``` - labels.clear(); - labels.push(( + err.span_label( pattern.span, format!("consider giving this closure parameter {}", suffix), - )); + ); } else if let Some(pattern) = local_visitor.found_local_pattern { - if let Some(simple_ident) = pattern.simple_ident() { + let msg = if let Some(simple_ident) = pattern.simple_ident() { match pattern.span.desugaring_kind() { - None => labels.push(( - pattern.span, - format!("consider giving `{}` {}", simple_ident, suffix), - )), - Some(DesugaringKind::ForLoop) => labels.push(( - pattern.span, - "the element type for this iterator is not specified".to_owned(), - )), - _ => {} + None => { + format!("consider giving `{}` {}", simple_ident, suffix) + } + Some(DesugaringKind::ForLoop) => { + "the element type for this iterator is not specified".to_string() + } + _ => format!("this needs {}", suffix), } } else { - labels.push((pattern.span, format!("consider giving this pattern {}", suffix))); - } - }; - - let mut err = struct_span_err!( - self.tcx.sess, - err_span, - E0282, - "type annotations needed{}", - ty_msg, - ); - - for (target_span, label_message) in labels { - err.span_label(target_span, label_message); + format!("consider giving this pattern {}", suffix) + }; + err.span_label(pattern.span, msg); + } + // Instead of the following: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | --^^^--------- cannot infer type for `S` + // | + // = note: type must be known at this point + // We want: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | ^^^ cannot infer type for `S` + // | + // = note: type must be known at this point + let span = name_sp.unwrap_or(span); + if !err.span.span_labels().iter().any(|span_label| { + span_label.label.is_some() && span_label.span == span + }) && local_visitor.found_arg_pattern.is_none() + { // Avoid multiple labels pointing at `span`. + err.span_label(span, InferCtxt::missing_type_msg(&name)); } err @@ -232,7 +367,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let name = self.extract_type_name(&ty, None); + let name = self.extract_type_name(&ty, None).0; let mut err = struct_span_err!( self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind, ); diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 6bd2c04d51..979815fa7f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -2,7 +2,7 @@ //! where both the regions are anonymous. use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::error_reporting::nice_region_error::util::AnonymousArgInfo; +use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::util::common::ErrorReported; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -59,13 +59,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let ty_sub = self.find_anon_type(sub, &bregion_sub)?; debug!( - "try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}", + "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}", ty_sub, sup, bregion_sup ); debug!( - "try_report_anon_anon_conflict: found_arg2={:?} sub={:?} br2={:?}", + "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}", ty_sup, sub, bregion_sub @@ -74,24 +74,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let (ty_sup, ty_fndecl_sup) = ty_sup; let (ty_sub, ty_fndecl_sub) = ty_sub; - let AnonymousArgInfo { - arg: anon_arg_sup, .. - } = self.find_arg_with_region(sup, sup)?; - let AnonymousArgInfo { - arg: anon_arg_sub, .. - } = self.find_arg_with_region(sub, sub)?; + let AnonymousParamInfo { + param: anon_param_sup, .. + } = self.find_param_with_region(sup, sup)?; + let AnonymousParamInfo { + param: anon_param_sub, .. + } = self.find_param_with_region(sub, sub)?; let sup_is_ret_type = self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup); let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - let span_label_var1 = match anon_arg_sup.pat.simple_ident() { + let span_label_var1 = match anon_param_sup.pat.simple_ident() { Some(simple_ident) => format!(" from `{}`", simple_ident), None => String::new(), }; - let span_label_var2 = match anon_arg_sub.pat.simple_ident() { + let span_label_var2 = match anon_param_sub.pat.simple_ident() { Some(simple_ident) => format!(" into `{}`", simple_ident), None => String::new(), }; diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 51bee49b70..604115cfc3 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -6,7 +6,7 @@ use crate::ty; use errors::{Applicability, DiagnosticBuilder}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - /// When given a `ConcreteFailure` for a function with arguments containing a named region and + /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. pub(super) fn try_report_named_anon_conflict(&self) -> Option> { let (span, sub, sup) = self.get_regions(); @@ -24,23 +24,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one.//scope_def_id - let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) + let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub) && self.tcx().is_suitable_region(sup).is_some() - && self.find_arg_with_region(sup, sub).is_some() + && self.find_param_with_region(sup, sub).is_some() { ( sub, sup, - self.find_arg_with_region(sup, sub).unwrap(), + self.find_param_with_region(sup, sub).unwrap(), self.tcx().is_suitable_region(sup).unwrap(), ) } else if self.is_named_region(sup) && self.tcx().is_suitable_region(sub).is_some() - && self.find_arg_with_region(sub, sup).is_some() + && self.find_param_with_region(sub, sup).is_some() { ( sup, sub, - self.find_arg_with_region(sub, sup).unwrap(), + self.find_param_with_region(sub, sup).unwrap(), self.tcx().is_suitable_region(sub).unwrap(), ) } else { @@ -49,20 +49,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { debug!("try_report_named_anon_conflict: named = {:?}", named); debug!( - "try_report_named_anon_conflict: anon_arg_info = {:?}", - anon_arg_info + "try_report_named_anon_conflict: anon_param_info = {:?}", + anon_param_info ); debug!( "try_report_named_anon_conflict: region_info = {:?}", region_info ); - let (arg, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( - anon_arg_info.arg, - anon_arg_info.arg_ty, - anon_arg_info.arg_ty_span, - anon_arg_info.bound_region, - anon_arg_info.is_first, + let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( + anon_param_info.param, + anon_param_info.param_ty, + anon_param_info.param_ty_span, + anon_param_info.bound_region, + anon_param_info.is_first, region_info.def_id, region_info.is_impl_item, ); @@ -95,7 +95,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - let (error_var, span_label_var) = match arg.pat.simple_ident() { + let (error_var, span_label_var) = match param.pat.simple_ident() { Some(simple_ident) => ( format!("the type of `{}`", simple_ident), format!("the type of `{}`", simple_ident), diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index b4fb018920..bfa8353ca3 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -30,7 +30,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -50,7 +50,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -70,7 +70,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -92,7 +92,7 @@ impl NiceRegionError<'me, 'tcx> { _, _, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -108,7 +108,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -125,7 +125,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -142,7 +142,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -192,23 +192,28 @@ impl NiceRegionError<'me, 'tcx> { vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs ); - let mut err = self.tcx().sess.struct_span_err( - cause.span(self.tcx()), - &format!( - "implementation of `{}` is not general enough", - self.tcx().def_path_str(trait_def_id), - ), + let span = cause.span(self.tcx()); + let msg = format!( + "implementation of `{}` is not general enough", + self.tcx().def_path_str(trait_def_id), + ); + let mut err = self.tcx().sess.struct_span_err(span, &msg); + err.span_label( + self.tcx().def_span(trait_def_id), + format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)), ); - match cause.code { - ObligationCauseCode::ItemObligation(def_id) => { - err.note(&format!( - "Due to a where-clause on `{}`,", - self.tcx().def_path_str(def_id), - )); - } - _ => (), - } + let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code { + err.span_label(span, "doesn't satisfy where-clause"); + err.span_label( + self.tcx().def_span(def_id), + &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)), + ); + true + } else { + err.span_label(span, &msg); + false + }; let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef { def_id: trait_def_id, @@ -295,6 +300,7 @@ impl NiceRegionError<'me, 'tcx> { expected_has_vid, actual_has_vid, any_self_ty_has_vid, + leading_ellipsis, ); err @@ -318,6 +324,7 @@ impl NiceRegionError<'me, 'tcx> { expected_has_vid: Option, actual_has_vid: Option, any_self_ty_has_vid: bool, + leading_ellipsis: bool, ) { // HACK(eddyb) maybe move this in a more central location. #[derive(Copy, Clone)] @@ -392,13 +399,15 @@ impl NiceRegionError<'me, 'tcx> { let mut note = if passive_voice { format!( - "`{}` would have to be implemented for the type `{}`", + "{}`{}` would have to be implemented for the type `{}`", + if leading_ellipsis { "..." } else { "" }, expected_trait_ref, expected_trait_ref.map(|tr| tr.self_ty()), ) } else { format!( - "`{}` must implement `{}`", + "{}`{}` must implement `{}`", + if leading_ellipsis { "..." } else { "" }, expected_trait_ref.map(|tr| tr.self_ty()), expected_trait_ref, ) @@ -407,20 +416,20 @@ impl NiceRegionError<'me, 'tcx> { match (has_sub, has_sup) { (Some(n1), Some(n2)) => { let _ = write!(note, - ", for any two lifetimes `'{}` and `'{}`", + ", for any two lifetimes `'{}` and `'{}`...", std::cmp::min(n1, n2), std::cmp::max(n1, n2), ); } (Some(n), _) | (_, Some(n)) => { let _ = write!(note, - ", for any lifetime `'{}`", + ", for any lifetime `'{}`...", n, ); } (None, None) => if let Some(n) = expected_has_vid { let _ = write!(note, - ", for some specific lifetime `'{}`", + ", for some specific lifetime `'{}`...", n, ); }, @@ -439,13 +448,13 @@ impl NiceRegionError<'me, 'tcx> { let mut note = if passive_voice { format!( - "but `{}` is actually implemented for the type `{}`", + "...but `{}` is actually implemented for the type `{}`", actual_trait_ref, actual_trait_ref.map(|tr| tr.self_ty()), ) } else { format!( - "but `{}` actually implements `{}`", + "...but `{}` actually implements `{}`", actual_trait_ref.map(|tr| tr.self_ty()), actual_trait_ref, ) diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index f33f917392..668c99da00 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -10,37 +10,37 @@ use syntax_pos::Span; // The struct contains the information about the anonymous region // we are searching for. #[derive(Debug)] -pub(super) struct AnonymousArgInfo<'tcx> { - // the argument corresponding to the anonymous region - pub arg: &'tcx hir::Arg, - // the type corresponding to the anonymopus region argument - pub arg_ty: Ty<'tcx>, +pub(super) struct AnonymousParamInfo<'tcx> { + // the parameter corresponding to the anonymous region + pub param: &'tcx hir::Param, + // the type corresponding to the anonymopus region parameter + pub param_ty: Ty<'tcx>, // the ty::BoundRegion corresponding to the anonymous region pub bound_region: ty::BoundRegion, - // arg_ty_span contains span of argument type - pub arg_ty_span : Span, + // param_ty_span contains span of parameter type + pub param_ty_span : Span, // corresponds to id the argument is the first parameter // in the declaration pub is_first: bool, } impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - // This method walks the Type of the function body arguments using + // This method walks the Type of the function body parameters using // `fold_regions()` function and returns the - // &hir::Arg of the function argument corresponding to the anonymous + // &hir::Param of the function parameter corresponding to the anonymous // region and the Ty corresponding to the named region. // Currently only the case where the function declaration consists of // one named region and one anonymous region is handled. // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` - // Here, we would return the hir::Arg for y, we return the type &'a + // Here, we would return the hir::Param for y, we return the type &'a // i32, which is the type of y but with the anonymous region replaced // with 'a, the corresponding bound region and is_first which is true if - // the hir::Arg is the first argument in the function declaration. - pub(super) fn find_arg_with_region( + // the hir::Param is the first parameter in the function declaration. + pub(super) fn find_param_with_region( &self, anon_region: Region<'tcx>, replace_region: Region<'tcx>, - ) -> Option> { + ) -> Option> { let (id, bound_region) = match *anon_region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), ty::ReEarlyBound(ebr) => ( @@ -57,16 +57,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let owner_id = hir.body_owner(body_id); let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); if let Some(tables) = self.tables { - body.arguments + body.params .iter() .enumerate() - .filter_map(|(index, arg)| { + .filter_map(|(index, param)| { // May return None; sometimes the tables are not yet populated. let ty_hir_id = fn_decl.inputs[index].hir_id; - let arg_ty_span = hir.span(ty_hir_id); - let ty = tables.node_type_opt(arg.hir_id)?; + let param_ty_span = hir.span(ty_hir_id); + let ty = tables.node_type_opt(param.hir_id)?; let mut found_anon_region = false; - let new_arg_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { + let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { if *r == *anon_region { found_anon_region = true; replace_region @@ -76,10 +76,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }); if found_anon_region { let is_first = index == 0; - Some(AnonymousArgInfo { - arg: arg, - arg_ty: new_arg_ty, - arg_ty_span : arg_ty_span, + Some(AnonymousParamInfo { + param: param, + param_ty: new_param_ty, + param_ty_span : param_ty_span, bound_region: bound_region, is_first: is_first, }) diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index caed428889..115ffea97b 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sup: Region<'tcx>) -> DiagnosticBuilder<'tcx> { match origin { - infer::Subtype(trace) => { + infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error(trace, &terr); self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "..."); @@ -450,7 +450,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> DiagnosticBuilder<'tcx> { // I can't think how to do better than this right now. -nikomatsakis match placeholder_origin { - infer::Subtype(trace) => { + infer::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; self.report_and_explain_type_error(trace, &terr) } diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 2cef521176..37de54a7e8 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -57,7 +57,7 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b)) } @@ -66,11 +66,6 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), a, b); - if a == b { - return Ok(a); - } - self.fields.infcx.super_combine_consts(self, a, b) } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index e20372f151..a1a94865e7 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -57,7 +57,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b)) } @@ -66,11 +66,6 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), a, b); - if a == b { - return Ok(a); - } - self.fields.infcx.super_combine_consts(self, a, b) } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e1d77a97c1..c5712cc994 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -254,7 +254,7 @@ pub struct TypeTrace<'tcx> { #[derive(Clone, Debug)] pub enum SubregionOrigin<'tcx> { /// Arose from a subtyping relation - Subtype(TypeTrace<'tcx>), + Subtype(Box>), /// Stack-allocated closures cannot outlive innermost loop /// or function so as to ensure we only require finite stack @@ -340,6 +340,10 @@ pub enum SubregionOrigin<'tcx> { }, } +// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(SubregionOrigin<'_>, 32); + /// Places that type/region parameters can appear. #[derive(Clone, Copy, Debug)] pub enum ParameterOrigin { @@ -1321,13 +1325,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { T: TypeFoldable<'tcx>, { if !value.needs_infer() { - return value.clone(); // avoid duplicated subst-folding + return value.clone(); // Avoid duplicated subst-folding. } let mut r = resolve::OpportunisticVarResolver::new(self); value.fold_with(&mut r) } - /// Returns first unresolved variable contained in `T`. In the + /// Returns the first unresolved variable contained in `T`. In the /// process of visiting `T`, this will resolve (where possible) /// type variables in `T`, but it never constructs the final, /// resolved type, so it's more efficient than @@ -1460,9 +1464,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); - // this can get called from typeck (by euv), and moves_by_default + // This can get called from typeck (by euv), and `moves_by_default` // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. @@ -1482,7 +1486,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { closure_kind_ty.to_opt_closure_kind() } - /// Obtain the signature of a closure. For closures, unlike + /// Obtains the signature of a closure. For closures, unlike /// `tcx.fn_sig(def_id)`, this method will work during the /// type-checking of the enclosing function and return the closure /// signature in its partially inferred state. @@ -1558,11 +1562,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { ShallowResolver { infcx } } - // We have this force-inlined variant of `shallow_resolve` for the one - // callsite that is extremely hot. All other callsites use the normal - // variant. - #[inline(always)] - pub fn inlined_shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { + pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { match typ.sty { ty::Infer(ty::TyVar(v)) => { // Not entirely obvious: if `typ` is a type variable, @@ -1597,6 +1597,42 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { _ => typ, } } + + // `resolver.shallow_resolve_changed(ty)` is equivalent to + // `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always + // inlined, despite being large, because it has a single call site that is + // extremely hot. + #[inline(always)] + pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool { + match typ.sty { + ty::Infer(ty::TyVar(v)) => { + use self::type_variable::TypeVariableValue; + + // See the comment in `shallow_resolve()`. + match self.infcx.type_variables.borrow_mut().probe(v) { + TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ, + TypeVariableValue::Unknown { .. } => false, + } + } + + ty::Infer(ty::IntVar(v)) => { + match self.infcx.int_unification_table.borrow_mut().probe_value(v) { + Some(v) => v.to_type(self.infcx.tcx) != typ, + None => false, + } + } + + ty::Infer(ty::FloatVar(v)) => { + match self.infcx.float_unification_table.borrow_mut().probe_value(v) { + Some(v) => v.to_type(self.infcx.tcx) != typ, + None => false, + } + } + + _ => false, + } + } + } impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { @@ -1605,7 +1641,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.inlined_shallow_resolve(ty) + self.shallow_resolve(ty) } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 5c62f76e3b..c9fd3392a9 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -127,8 +127,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> { debug!( "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \ - param_env={:?})", - value, parent_def_id, body_id, param_env, + param_env={:?}, value_span={:?})", + value, parent_def_id, body_id, param_env, value_span, ); let mut instantiator = Instantiator { infcx: self, @@ -1108,9 +1108,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). if let Some(opaque_defn) = self.opaque_types.get(&def_id) { + debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } let span = tcx.def_span(def_id); + debug!("fold_opaque_ty {:?} {:?}", self.value_span, span); let ty_var = infcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index cd1d206b5f..67c97ef5d8 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -1,13 +1,11 @@ use super::SubregionOrigin; -use super::combine::{CombineFields, RelationDir, const_unification_error}; +use super::combine::{CombineFields, RelationDir}; use crate::traits::Obligation; -use crate::ty::{self, Ty, TyCtxt, InferConst}; +use crate::ty::{self, Ty, TyCtxt}; use crate::ty::TyVar; use crate::ty::fold::TypeFoldable; use crate::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; -use crate::infer::unify_key::replace_if_possible; -use crate::mir::interpret::ConstValue; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -130,7 +128,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { // FIXME -- we have more fine-grained information available // from the "cause" field, we could perhaps give more tailored // error messages. - let origin = SubregionOrigin::Subtype(self.fields.trace.clone()); + let origin = SubregionOrigin::Subtype(box self.fields.trace.clone()); self.fields.infcx.borrow_region_constraints() .make_subregion(origin, a, b); @@ -142,41 +140,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - debug!("{}.consts({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } - - let infcx = self.fields.infcx; - let a = replace_if_possible(infcx.const_unification_table.borrow_mut(), a); - let b = replace_if_possible(infcx.const_unification_table.borrow_mut(), b); - - // Consts can only be equal or unequal to each other: there's no subtyping - // relation, so we're just going to perform equating here instead. - let a_is_expected = self.a_is_expected(); - match (a.val, b.val) { - (ConstValue::Infer(InferConst::Var(a_vid)), - ConstValue::Infer(InferConst::Var(b_vid))) => { - infcx.const_unification_table - .borrow_mut() - .unify_var_var(a_vid, b_vid) - .map_err(|e| const_unification_error(a_is_expected, e))?; - return Ok(a); - } - - (ConstValue::Infer(InferConst::Var(a_id)), _) => { - self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?; - return Ok(a); - } - - (_, ConstValue::Infer(InferConst::Var(b_id))) => { - self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?; - return Ok(a); - } - - _ => {} - } - - self.fields.infcx.super_combine_consts(self, a, b)?; - Ok(a) + self.fields.infcx.super_combine_consts(self, a, b) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8d4cd51e46..7a01ae6b6d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -45,7 +45,6 @@ #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] #![feature(range_is_empty)] -#![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(specialization)] #![feature(unboxed_closures)] @@ -62,12 +61,12 @@ #![feature(log_syntax)] #![feature(mem_take)] #![feature(associated_type_bounds)] +#![feature(rustc_attrs)] #![recursion_limit="512"] #[macro_use] extern crate bitflags; extern crate getopts; -#[macro_use] extern crate lazy_static; #[macro_use] extern crate scoped_tls; #[cfg(windows)] extern crate libc; @@ -87,8 +86,6 @@ mod tests; #[macro_use] mod macros; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. pub mod error_codes; #[macro_use] @@ -96,7 +93,6 @@ pub mod query; #[macro_use] pub mod arena; -pub mod cfg; pub mod dep_graph; pub mod hir; pub mod ich; @@ -109,6 +105,7 @@ pub mod middle { pub mod cstore; pub mod dead; pub mod dependency_format; + pub mod diagnostic_items; pub mod entry; pub mod exported_symbols; pub mod free_region; @@ -141,6 +138,3 @@ pub mod util { // Allows macros to refer to this crate as `::rustc` extern crate self as rustc; - -// Build the diagnostics array at the end so that the metadata includes error use sites. -__build_diagnostic_array! { librustc, DIAGNOSTICS } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index dd290572d7..5906a6388a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -7,7 +7,7 @@ use crate::lint::{LintPass, LateLintPass, LintArray}; use crate::middle::stability; use crate::session::Session; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use syntax::ast; use syntax::source_map::Span; use syntax::symbol::Symbol; @@ -524,7 +524,7 @@ pub(crate) fn add_elided_lifetime_in_path_suggestion( }; db.span_suggestion( replace_span, - &format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }), + &format!("indicate the anonymous lifetime{}", pluralise!(n)), suggestion, Applicability::MachineApplicable ); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index de812410e8..c658120b95 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -16,32 +16,32 @@ use self::TargetLint::*; -use std::slice; -use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; +use crate::hir; +use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use crate::hir::intravisit as hir_visit; +use crate::hir::intravisit::Visitor; +use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData}; use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::levels::{LintLevelSets, LintLevelsBuilder}; use crate::middle::privacy::AccessLevels; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use crate::session::{config, early_error, Session}; use crate::ty::{self, print::Printer, subst::Kind, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; use crate::util::nodemap::FxHashMap; use crate::util::common::time; +use errors::DiagnosticBuilder; +use std::slice; use std::default::Default as StdDefault; +use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; +use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; -use errors::DiagnosticBuilder; -use crate::hir; -use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use crate::hir::intravisit as hir_visit; -use crate::hir::intravisit::Visitor; -use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; +use syntax_pos::{MultiSpan, Span, symbol::Symbol}; /// Information about the registered lints. /// @@ -405,7 +405,7 @@ impl LintStore { pub fn check_lint_name( &self, lint_name: &str, - tool_name: Option, + tool_name: Option, ) -> CheckLintNameResult<'_> { let complete_name = if let Some(tool_name) = tool_name { format!("{}::{}", tool_name, lint_name) @@ -966,10 +966,10 @@ for LateContextAndPass<'a, 'tcx, T> { self.context.tables = old_tables; } - fn visit_arg(&mut self, arg: &'tcx hir::Arg) { - self.with_lint_attrs(arg.hir_id, &arg.attrs, |cx| { - lint_callback!(cx, check_arg, arg); - hir_visit::walk_arg(cx, arg); + fn visit_param(&mut self, param: &'tcx hir::Param) { + self.with_lint_attrs(param.hir_id, ¶m.attrs, |cx| { + lint_callback!(cx, check_param, param); + hir_visit::walk_param(cx, param); }); } @@ -1040,13 +1040,13 @@ for LateContextAndPass<'a, 'tcx, T> { fn visit_variant_data(&mut self, s: &'tcx hir::VariantData, - name: ast::Name, - g: &'tcx hir::Generics, - item_id: hir::HirId, + _: ast::Name, + _: &'tcx hir::Generics, + _: hir::HirId, _: Span) { - lint_callback!(self, check_struct_def, s, name, g, item_id); + lint_callback!(self, check_struct_def, s); hir_visit::walk_struct_def(self, s); - lint_callback!(self, check_struct_def_post, s, name, g, item_id); + lint_callback!(self, check_struct_def_post, s); } fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { @@ -1060,10 +1060,10 @@ for LateContextAndPass<'a, 'tcx, T> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| { - lint_callback!(cx, check_variant, v, g); + self.with_lint_attrs(v.id, &v.attrs, |cx| { + lint_callback!(cx, check_variant, v); hir_visit::walk_variant(cx, v, g, item_id); - lint_callback!(cx, check_variant_post, v, g); + lint_callback!(cx, check_variant_post, v); }) } @@ -1163,10 +1163,10 @@ for LateContextAndPass<'a, 'tcx, T> { } impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { - fn visit_arg(&mut self, arg: &'a ast::Arg) { - self.with_lint_attrs(arg.id, &arg.attrs, |cx| { - run_early_pass!(cx, check_arg, arg); - ast_visit::walk_arg(cx, arg); + fn visit_param(&mut self, param: &'a ast::Param) { + self.with_lint_attrs(param.id, ¶m.attrs, |cx| { + run_early_pass!(cx, check_param, param); + ast_visit::walk_param(cx, param); }); } @@ -1214,18 +1214,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_fn_post, fk, decl, span, id); } - fn visit_variant_data(&mut self, - s: &'a ast::VariantData, - ident: ast::Ident, - g: &'a ast::Generics, - item_id: ast::NodeId, - _: Span) { - run_early_pass!(self, check_struct_def, s, ident, g, item_id); + fn visit_variant_data(&mut self, s: &'a ast::VariantData) { + run_early_pass!(self, check_struct_def, s); if let Some(ctor_hir_id) = s.ctor_id() { self.check_id(ctor_hir_id); } ast_visit::walk_struct_def(self, s); - run_early_pass!(self, check_struct_def_post, s, ident, g, item_id); + run_early_pass!(self, check_struct_def_post, s); } fn visit_struct_field(&mut self, s: &'a ast::StructField) { @@ -1235,11 +1230,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }) } - fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) { - self.with_lint_attrs(item_id, &v.node.attrs, |cx| { - run_early_pass!(cx, check_variant, v, g); - ast_visit::walk_variant(cx, v, g, item_id); - run_early_pass!(cx, check_variant_post, v, g); + fn visit_variant(&mut self, v: &'a ast::Variant) { + self.with_lint_attrs(v.id, &v.attrs, |cx| { + run_early_pass!(cx, check_variant, v); + ast_visit::walk_variant(cx, v); + run_early_pass!(cx, check_variant_post, v); }) } @@ -1345,7 +1340,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // part of `walk_mac`, and (b) we should be calling // `visit_path`, *but* that would require a `NodeId`, and I // want to get #53686 fixed quickly. -nmatsakis - ast_visit::walk_path(self, &mac.node.path); + ast_visit::walk_path(self, &mac.path); run_early_pass!(self, check_mac, mac); } @@ -1355,7 +1350,7 @@ struct LateLintPassObjects<'a> { lints: &'a mut [LateLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() @@ -1525,7 +1520,7 @@ struct EarlyLintPassObjects<'a> { lints: &'a mut [EarlyLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 0b514f5927..13834eaf40 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -9,7 +9,6 @@ use errors::Applicability; use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Ident, Item, ItemKind}; use syntax::symbol::{sym, Symbol}; -use syntax_pos::ExpnInfo; declare_tool_lint! { pub rustc::DEFAULT_HASH_TYPES, @@ -23,7 +22,7 @@ pub struct DefaultHashTypes { impl DefaultHashTypes { // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself - #[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] + #[allow(rustc::default_hash_types)] pub fn new() -> Self { let mut map = FxHashMap::default(); map.insert(sym::HashMap, sym::FxHashMap); @@ -108,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { .help("try using `Ty` instead") .emit(); } else { - if ty.span.ctxt().outer_expn_info().is_some() { + if ty.span.from_expansion() { return; } if let Some(t) = is_ty_or_ty_ctxt(cx, ty) { @@ -160,29 +159,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool { - if segment.ident.name == sym::TyKind { - if let Some(res) = segment.res { - if let Some(did) = res.opt_def_id() { - return cx.match_def_path(did, TYKIND_PATH); - } + if let Some(res) = segment.res { + if let Some(did) = res.opt_def_id() { + return cx.tcx.is_diagnostic_item(sym::TyKind, did); } } false } -const TYKIND_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::sty, sym::TyKind]; -const TY_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::Ty]; -const TYCTXT_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::context, sym::TyCtxt]; - fn is_ty_or_ty_ctxt(cx: &LateContext<'_, '_>, ty: &Ty) -> Option { match &ty.node { TyKind::Path(qpath) => { if let QPath::Resolved(_, path) = qpath { let did = path.res.opt_def_id()?; - if cx.match_def_path(did, TY_PATH) { + if cx.tcx.is_diagnostic_item(sym::Ty, did) { return Some(format!("Ty{}", gen_args(path.segments.last().unwrap()))); - } else if cx.match_def_path(did, TYCTXT_PATH) { + } else if cx.tcx.is_diagnostic_item(sym::TyCtxt, did) { return Some(format!("TyCtxt{}", gen_args(path.segments.last().unwrap()))); } } @@ -228,30 +221,20 @@ impl EarlyLintPass for LintPassImpl { if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { - match &lint_pass.path.span.ctxt().outer_expn_info() { - Some(info) if is_lint_pass_expansion(info) => {} - _ => { - cx.struct_span_lint( - LINT_PASS_IMPL_WITHOUT_MACRO, - lint_pass.path.span, - "implementing `LintPass` by hand", - ) - .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") - .emit(); - } + let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); + let call_site = expn_data.call_site; + if expn_data.kind.descr() != sym::impl_lint_pass && + call_site.ctxt().outer_expn_data().kind.descr() != sym::declare_lint_pass { + cx.struct_span_lint( + LINT_PASS_IMPL_WITHOUT_MACRO, + lint_pass.path.span, + "implementing `LintPass` by hand", + ) + .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") + .emit(); } } } } } } - -fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool { - if expn_info.kind.descr() == sym::impl_lint_pass { - true - } else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() { - info.kind.descr() == sym::declare_lint_pass - } else { - false - } -} diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 139f434311..cbc6dbdba7 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -291,7 +291,7 @@ impl<'a> LintLevelsBuilder<'a> { continue; } - Some(tool_ident.as_str()) + Some(tool_ident.name) } else { None }; diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 8ddf460349..5b490b7012 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -206,7 +206,7 @@ macro_rules! declare_lint_pass { macro_rules! late_lint_methods { ($macro:path, $args:tt, [$hir:tt]) => ( $macro!($args, [$hir], [ - fn check_arg(a: &$hir hir::Arg); + fn check_param(a: &$hir hir::Param); fn check_body(a: &$hir hir::Body); fn check_body_post(a: &$hir hir::Body); fn check_name(a: Span, b: ast::Name); @@ -248,21 +248,11 @@ macro_rules! late_lint_methods { fn check_trait_item_post(a: &$hir hir::TraitItem); fn check_impl_item(a: &$hir hir::ImplItem); fn check_impl_item_post(a: &$hir hir::ImplItem); - fn check_struct_def( - a: &$hir hir::VariantData, - b: ast::Name, - c: &$hir hir::Generics, - d: hir::HirId - ); - fn check_struct_def_post( - a: &$hir hir::VariantData, - b: ast::Name, - c: &$hir hir::Generics, - d: hir::HirId - ); + fn check_struct_def(a: &$hir hir::VariantData); + fn check_struct_def_post(a: &$hir hir::VariantData); fn check_struct_field(a: &$hir hir::StructField); - fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics); - fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics); + fn check_variant(a: &$hir hir::Variant); + fn check_variant_post(a: &$hir hir::Variant); fn check_lifetime(a: &$hir hir::Lifetime); fn check_path(a: &$hir hir::Path, b: hir::HirId); fn check_attribute(a: &$hir ast::Attribute); @@ -359,7 +349,7 @@ macro_rules! declare_combined_late_lint_pass { macro_rules! early_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ - fn check_arg(a: &ast::Arg); + fn check_param(a: &ast::Param); fn check_ident(a: ast::Ident); fn check_crate(a: &ast::Crate); fn check_crate_post(a: &ast::Crate); @@ -395,21 +385,11 @@ macro_rules! early_lint_methods { fn check_trait_item_post(a: &ast::TraitItem); fn check_impl_item(a: &ast::ImplItem); fn check_impl_item_post(a: &ast::ImplItem); - fn check_struct_def( - a: &ast::VariantData, - b: ast::Ident, - c: &ast::Generics, - d: ast::NodeId - ); - fn check_struct_def_post( - a: &ast::VariantData, - b: ast::Ident, - c: &ast::Generics, - d: ast::NodeId - ); + fn check_struct_def(a: &ast::VariantData); + fn check_struct_def_post(a: &ast::VariantData); fn check_struct_field(a: &ast::StructField); - fn check_variant(a: &ast::Variant, b: &ast::Generics); - fn check_variant_post(a: &ast::Variant, b: &ast::Generics); + fn check_variant(a: &ast::Variant); + fn check_variant_post(a: &ast::Variant); fn check_lifetime(a: &ast::Lifetime); fn check_path(a: &ast::Path, b: ast::NodeId); fn check_attribute(a: &ast::Attribute); @@ -666,6 +646,30 @@ pub fn struct_lint_level<'a>(sess: &'a Session, (Level::Forbid, None) => sess.struct_err(msg), }; + // Check for future incompatibility lints and issue a stronger warning. + let lints = sess.lint_store.borrow(); + let lint_id = LintId::of(lint); + let future_incompatible = lints.future_incompatible(lint_id); + + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel(); + // Don't continue further, since we don't want to have + // `diag_span_note_once` called for a diagnostic that isn't emitted. + return err; + } + } + let name = lint.name_lower(); match src { LintSource::Default => { @@ -715,10 +719,6 @@ pub fn struct_lint_level<'a>(sess: &'a Session, err.code(DiagnosticId::Lint(name)); - // Check for future incompatibility lints and issue a stronger warning. - let lints = sess.lint_store.borrow(); - let lint_id = LintId::of(lint); - let future_incompatible = lints.future_incompatible(lint_id); if let Some(future_incompatible) = future_incompatible { const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ @@ -743,22 +743,6 @@ pub fn struct_lint_level<'a>(sess: &'a Session, err.note(&citation); } - // If this code originates in a foreign macro, aka something that this crate - // did not itself author, then it's likely that there's nothing this crate - // can do about it. We probably want to skip the lint entirely. - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - // Any suggestions made here are likely to be incorrect, so anything we - // emit shouldn't be automatically fixed by rustfix. - err.allow_suggestions(false); - - // If this is a future incompatible lint it'll become a hard error, so - // we have to emit *something*. Also allow lints to whitelist themselves - // on a case-by-case basis for emission in a foreign macro. - if future_incompatible.is_none() && !lint.report_in_external_macro { - err.cancel() - } - } - return err } @@ -812,9 +796,9 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } - fn visit_arg(&mut self, arg: &'tcx hir::Arg) { - self.with_lint_attrs(arg.hir_id, &arg.attrs, |builder| { - intravisit::walk_arg(builder, arg); + fn visit_param(&mut self, param: &'tcx hir::Param) { + self.with_lint_attrs(param.hir_id, ¶m.attrs, |builder| { + intravisit::walk_param(builder, param); }); } @@ -846,7 +830,7 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| { + self.with_lint_attrs(v.id, &v.attrs, |builder| { intravisit::walk_variant(builder, v, g, item_id); }) } @@ -885,23 +869,18 @@ pub fn provide(providers: &mut Providers<'_>) { /// This is used to test whether a lint should not even begin to figure out whether it should /// be reported on the current node. pub fn in_external_macro(sess: &Session, span: Span) -> bool { - let info = match span.ctxt().outer_expn_info() { - Some(info) => info, - // no ExpnInfo means this span doesn't come from a macro - None => return false, - }; - - match info.kind { + let expn_data = span.ctxt().outer_expn_data(); + match expn_data.kind { ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, - ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { - if info.def_site.is_dummy() { - // dummy span for the def_site means it's an external macro + if expn_data.def_site.is_dummy() { + // Dummy span for the `def_site` means it's an external macro. return true; } - match sess.source_map().span_to_snippet(info.def_site) { + match sess.source_map().span_to_snippet(expn_data.def_site) { Ok(code) => !code.starts_with("macro_rules"), - // no snippet = external macro or compiler-builtin expansion + // No snippet means external macro or compiler-builtin expansion. Err(_) => true, } } @@ -909,12 +888,10 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { } } -/// Returns whether `span` originates in a derive macro's expansion +/// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(span: Span) -> bool { - if let Some(info) = span.ctxt().outer_expn_info() { - if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind { - return true; - } + if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind { + return true; } false } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index d37b2367ae..de84fcd716 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -178,8 +178,7 @@ pub trait MetadataLoader { -> Result; } -/// A store of Rust crates, through with their metadata -/// can be accessed. +/// A store of Rust crates, through which their metadata can be accessed. /// /// Note that this trait should probably not be expanding today. All new /// functionality should be driven through queries instead! diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 55fa261f1e..d4805a7c78 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -17,8 +17,7 @@ use crate::util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; -use syntax::{ast, source_map}; -use syntax::attr; +use syntax::{ast, attr}; use syntax::symbol::sym; use syntax_pos; @@ -31,10 +30,11 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { Some(Node::Item(..)) | Some(Node::ImplItem(..)) | Some(Node::ForeignItem(..)) | - Some(Node::TraitItem(..)) => - true, - _ => - false + Some(Node::TraitItem(..)) | + Some(Node::Variant(..)) | + Some(Node::AnonConst(..)) | + Some(Node::Pat(..)) => true, + _ => false } } @@ -76,7 +76,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { self.check_def_id(res.def_id()); } _ if self.in_pat => {}, - Res::PrimTy(..) | Res::SelfTy(..) | Res::SelfCtor(..) | + Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {} Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => { let variant_id = self.tcx.parent(ctor_def_id).unwrap(); @@ -93,6 +93,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { self.check_def_id(variant_id); } } + Res::SelfTy(t, i) => { + if let Some(t) = t { + self.check_def_id(t); + } + if let Some(i) = i { + self.check_def_id(i); + } + } Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {} _ => { self.check_def_id(res.def_id()); @@ -119,17 +127,16 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, - pats: &[source_map::Spanned]) { + fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, pats: &[hir::FieldPat]) { let variant = match self.tables.node_type(lhs.hir_id).sty { ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; for pat in pats { - if let PatKind::Wild = pat.node.pat.node { + if let PatKind::Wild = pat.pat.node { continue; } - let index = self.tcx.field_index(pat.node.hir_id, self.tables); + let index = self.tcx.field_index(pat.hir_id, self.tables); self.insert_def_id(variant.fields[index].did); } } @@ -273,7 +280,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { let res = self.tables.qpath_res(path, pat.hir_id); self.handle_field_pattern_match(pat, res, fields); } - PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { + PatKind::Path(ref qpath) => { let res = self.tables.qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -300,6 +307,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } intravisit::walk_ty(self, ty); } + + fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + self.live_symbols.insert(c.hir_id); + intravisit::walk_anon_const(self, c); + } } fn has_allow_dead_code_or_lang_attr( @@ -366,12 +378,12 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { match item.node { hir::ItemKind::Enum(ref enum_def, _) => { if allow_dead_code { - self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id)); + self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id)); } for variant in &enum_def.variants { - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { - self.struct_constructors.insert(ctor_hir_id, variant.node.id); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { + self.struct_constructors.insert(ctor_hir_id, variant.id); } } } @@ -497,7 +509,7 @@ impl DeadVisitor<'tcx> { && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs) } - fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool { + fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool { !self.symbol_is_live(variant.id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id, @@ -596,8 +608,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { variant: &'tcx hir::Variant, g: &'tcx hir::Generics, id: hir::HirId) { - if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name, + if self.should_warn_about_variant(&variant) { + self.warn_dead_code(variant.id, variant.span, variant.ident.name, "variant", "constructed"); } else { intravisit::walk_variant(self, variant, g, id); diff --git a/src/librustc/middle/diagnostic_items.rs b/src/librustc/middle/diagnostic_items.rs new file mode 100644 index 0000000000..dfae169b27 --- /dev/null +++ b/src/librustc/middle/diagnostic_items.rs @@ -0,0 +1,123 @@ +//! Detecting diagnostic items. +//! +//! Diagnostic items are items that are not language-inherent, but can reasonably be expected to +//! exist for diagnostic purposes. This allows diagnostic authors to refer to specific items +//! directly, without having to guess module paths and crates. +//! Examples are: +//! +//! * Traits like `Debug`, that have no bearing on language semantics +//! +//! * Compiler internal types like `Ty` and `TyCtxt` + +use crate::hir::def_id::{DefId, LOCAL_CRATE}; +use crate::ty::TyCtxt; +use crate::util::nodemap::FxHashMap; + +use syntax::ast; +use syntax::symbol::{Symbol, sym}; +use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir; + +struct DiagnosticItemCollector<'tcx> { + // items from this crate + items: FxHashMap, + tcx: TyCtxt<'tcx>, +} + +impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> { + fn visit_item(&mut self, item: &hir::Item) { + self.observe_item(&item.attrs, item.hir_id); + } + + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + self.observe_item(&trait_item.attrs, trait_item.hir_id); + } + + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + self.observe_item(&impl_item.attrs, impl_item.hir_id); + } +} + +impl<'tcx> DiagnosticItemCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> { + DiagnosticItemCollector { + tcx, + items: Default::default(), + } + } + + fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) { + if let Some(name) = extract(attrs) { + let def_id = self.tcx.hir().local_def_id(hir_id); + // insert into our table + collect_item(self.tcx, &mut self.items, name, def_id); + } + } +} + +fn collect_item( + tcx: TyCtxt<'_>, + items: &mut FxHashMap, + name: Symbol, + item_def_id: DefId, +) { + // Check for duplicates. + if let Some(original_def_id) = items.insert(name, item_def_id) { + if original_def_id != item_def_id { + let mut err = match tcx.hir().span_if_local(item_def_id) { + Some(span) => tcx.sess.struct_span_err( + span, + &format!("duplicate diagnostic item found: `{}`.", name)), + None => tcx.sess.struct_err(&format!( + "duplicate diagnostic item in crate `{}`: `{}`.", + tcx.crate_name(item_def_id.krate), + name)), + }; + if let Some(span) = tcx.hir().span_if_local(original_def_id) { + span_note!(&mut err, span, "first defined here."); + } else { + err.note(&format!("first defined in crate `{}`.", + tcx.crate_name(original_def_id.krate))); + } + err.emit(); + } + } +} + +/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. +fn extract(attrs: &[ast::Attribute]) -> Option { + attrs.iter().find_map(|attr| { + if attr.check_name(sym::rustc_diagnostic_item) { + attr.value_str() + } else { + None + } + }) +} + +/// Traverse and collect the diagnostic items in the current +pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap { + // Initialize the collector. + let mut collector = DiagnosticItemCollector::new(tcx); + + // Collect diagnostic items in this crate. + tcx.hir().krate().visit_all_item_likes(&mut collector); + + tcx.arena.alloc(collector.items) +} + + +/// Traverse and collect all the diagnostic items in all crates. +pub fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap { + // Initialize the collector. + let mut collector = FxHashMap::default(); + + // Collect diagnostic items in other crates. + for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) { + for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() { + collect_item(tcx, &mut collector, name, def_id); + } + } + + tcx.arena.alloc(collector) +} diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 53c099c0b4..ba27d332e4 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -16,17 +16,17 @@ struct EntryContext<'a, 'tcx> { map: &'a hir_map::Map<'tcx>, - // The top-level function called 'main' + /// The top-level function called `main`. main_fn: Option<(HirId, Span)>, - // The function that has attribute named 'main' + /// The function that has attribute named `main`. attr_main_fn: Option<(HirId, Span)>, - // The function that has the attribute 'start' on it + /// The function that has the attribute 'start' on it. start_fn: Option<(HirId, Span)>, - // The functions that one might think are 'main' but aren't, e.g. - // main functions not defined at the top level. For diagnostics. + /// The functions that one might think are `main` but aren't, e.g. + /// main functions not defined at the top level. For diagnostics. non_main_fns: Vec<(HirId, Span)> , } @@ -39,11 +39,11 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) { - // entry fn is never a trait item + // Entry fn is never a trait item. } fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { - // entry fn is never an impl item + // Entry fn is never a trait item. } } @@ -54,7 +54,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { *ty == config::CrateType::Executable }); if !any_exe { - // No need to find a main function + // No need to find a main function. return None; } @@ -88,7 +88,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { - // This is a top-level function so can be 'main'. + // This is a top-level function so can be `main`. EntryPointType::MainNamed } else { EntryPointType::OtherMain @@ -109,7 +109,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { ctxt.main_fn = Some((item.hir_id, item.span)); } else { span_err!(ctxt.session, item.span, E0136, - "multiple 'main' functions"); + "multiple `main` functions"); } }, EntryPointType::OtherMain => { @@ -130,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { if ctxt.start_fn.is_none() { ctxt.start_fn = Some((item.hir_id, item.span)); } else { - struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions") + struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions") .span_label(ctxt.start_fn.unwrap().1, "previous `start` function here") .span_label(item.span, "multiple `start` functions") .emit(); @@ -148,34 +148,48 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } else if let Some((hir_id, _)) = visitor.main_fn { Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) } else { - // No main function - let mut err = struct_err!(tcx.sess, E0601, - "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); - if !visitor.non_main_fns.is_empty() { - // There were some functions named 'main' though. Try to give the user a hint. - err.note("the main function must be defined at the crate level \ - but you have one or more functions named 'main' that are not \ - defined at the crate level. Either move the definition or \ - attach the `#[main]` attribute to override this behavior."); - for &(_, span) in &visitor.non_main_fns { - err.span_note(span, "here is a function named 'main'"); - } - err.emit(); - } else { - if let Some(ref filename) = tcx.sess.local_crate_source_file { - err.note(&format!("consider adding a `main` function to `{}`", filename.display())); - } - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note("If you don't know the basics of Rust, you can go look to the Rust Book \ - to get started: https://doc.rust-lang.org/book/"); - } - err.emit(); - } - + no_main_err(tcx, visitor); None } } +fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { + // There is no main function. + let mut err = struct_err!(tcx.sess, E0601, + "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); + let filename = &tcx.sess.local_crate_source_file; + let note = if !visitor.non_main_fns.is_empty() { + for &(_, span) in &visitor.non_main_fns { + err.span_note(span, "here is a function named `main`"); + } + err.note("you have one or more functions named `main` not defined at the crate level"); + err.help("either move the `main` function definitions or attach the `#[main]` attribute \ + to one of them"); + // There were some functions named `main` though. Try to give the user a hint. + format!("the main function must be defined at the crate level{}", + filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()) + } else if let Some(filename) = filename { + format!("consider adding a `main` function to `{}`", filename.display()) + } else { + String::from("consider adding a `main` function at the crate level") + }; + let sp = tcx.hir().krate().span; + // The file may be empty, which leads to the diagnostic machinery not emitting this + // note. This is a relatively simple way to detect that case and emit a span-less + // note instead. + if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) { + err.set_span(sp); + err.span_label(sp, ¬e); + } else { + err.note(¬e); + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note("If you don't know the basics of Rust, you can go look to the Rust Book \ + to get started: https://doc.rust-lang.org/book/"); + } + err.emit(); +} + pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> { tcx.entry_fn(LOCAL_CRATE) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a274d7bbee..de6dadabcb 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -313,9 +313,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { pub fn consume_body(&mut self, body: &hir::Body) { debug!("consume_body(body={:?})", body); - for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.pat_ty_adjusted(&arg.pat)); - debug!("consume_body: arg_ty = {:?}", arg_ty); + for param in &body.params { + let param_ty = return_if_err!(self.mc.pat_ty_adjusted(¶m.pat)); + debug!("consume_body: param_ty = {:?}", param_ty); let fn_body_scope_r = self.tcx().mk_region(ty::ReScope( @@ -323,13 +323,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { id: body.value.hir_id.local_id, data: region::ScopeData::Node })); - let arg_cmt = Rc::new(self.mc.cat_rvalue( - arg.hir_id, - arg.pat.span, - fn_body_scope_r, // Args live only as long as the fn body. - arg_ty)); + let param_cmt = Rc::new(self.mc.cat_rvalue( + param.hir_id, + param.pat.span, + fn_body_scope_r, // Parameters live only as long as the fn body. + param_ty)); - self.walk_irrefutable_pat(arg_cmt, &arg.pat); + self.walk_irrefutable_pat(param_cmt, ¶m.pat); } self.consume_expr(&body.value); @@ -596,7 +596,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::StmtKind::Item(_) => { - // we don't visit nested items in this visitor, + // We don't visit nested items in this visitor, // only the fn body we were given. } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c5c8639324..c5d9a722ae 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -3,10 +3,8 @@ //! Language items are items that represent concepts intrinsic to the language //! itself. Examples are: //! -//! * Traits that specify "kinds"; e.g., "Sync", "Send". -//! -//! * Traits that represent operators; e.g., "Add", "Sub", "Index". -//! +//! * Traits that specify "kinds"; e.g., `Sync`, `Send`. +//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. //! * Functions called by the compiler itself. pub use self::LangItem::*; @@ -151,11 +149,11 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { } fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - // at present, lang items are always items, not trait items + // At present, lang items are always items, not trait items. } fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - // at present, lang items are always items, not impl items + // At present, lang items are always items, not impl items. } } @@ -204,7 +202,7 @@ impl LanguageItemCollector<'tcx> { } } -/// Extract the first `lang = "$name"` out of a list of attributes. +/// Extracts the first `lang = "$name"` out of a list of attributes. /// The attributes `#[panic_handler]` and `#[alloc_error_handler]` /// are also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { @@ -216,7 +214,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { })) } -/// Traverse and collect all the lang items in all crates. +/// Traverses and collects all the lang items in all crates. pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx); @@ -246,6 +244,7 @@ pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { language_item_table! { // Variant name, Name, Method name, Target; + BoolImplItem, "bool", bool_impl, Target::Impl; CharImplItem, "char", char_impl, Target::Impl; StrImplItem, "str", str_impl, Target::Impl; SliceImplItem, "slice", slice_impl, Target::Impl; @@ -367,9 +366,7 @@ language_item_table! { MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union; - DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait; - - // Align offset for stride != 1, must not panic. + // Align offset for stride != 1; must not panic. AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; TerminationTraitLangItem, "termination", termination, Target::Trait; @@ -380,10 +377,14 @@ language_item_table! { impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. - /// If not found, fatally abort compilation. - pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { + /// If not found, fatally aborts compilation. + pub fn require_lang_item(&self, lang_item: LangItem, span: Option) -> DefId { self.lang_items().require(lang_item).unwrap_or_else(|msg| { - self.sess.fatal(&msg) + if let Some(span) = span { + self.sess.span_fatal(span, &msg) + } else { + self.sess.fatal(&msg) + } }) } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index daf0d8103a..00013bfc57 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -242,7 +242,7 @@ struct LocalInfo { #[derive(Copy, Clone, Debug)] enum VarKind { - Arg(HirId, ast::Name), + Param(HirId, ast::Name), Local(LocalInfo), CleanExit } @@ -298,7 +298,7 @@ impl IrMaps<'tcx> { self.num_vars += 1; match vk { - Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => { + Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) => { self.variable_map.insert(node_id, v); }, CleanExit => {} @@ -320,7 +320,7 @@ impl IrMaps<'tcx> { fn variable_name(&self, var: Variable) -> String { match self.var_kinds[var.get()] { - Local(LocalInfo { name, .. }) | Arg(_, name) => { + Local(LocalInfo { name, .. }) | Param(_, name) => { name.to_string() }, CleanExit => "".to_owned() @@ -330,7 +330,7 @@ impl IrMaps<'tcx> { fn variable_is_shorthand(&self, var: Variable) -> bool { match self.var_kinds[var.get()] { Local(LocalInfo { is_shorthand, .. }) => is_shorthand, - Arg(..) | CleanExit => false + Param(..) | CleanExit => false } } @@ -371,13 +371,13 @@ fn visit_fn<'tcx>( let body = ir.tcx.hir().body(body_id); - for arg in &body.arguments { - let is_shorthand = match arg.pat.node { + for param in &body.params { + let is_shorthand = match param.pat.node { crate::hir::PatKind::Struct(..) => true, _ => false, }; - arg.pat.each_binding(|_bm, hir_id, _x, ident| { - debug!("adding argument {:?}", hir_id); + param.pat.each_binding(|_bm, hir_id, _x, ident| { + debug!("adding parameters {:?}", hir_id); let var = if is_shorthand { Local(LocalInfo { id: hir_id, @@ -385,7 +385,7 @@ fn visit_fn<'tcx>( is_shorthand: true, }) } else { - Arg(hir_id, ident.name) + Param(hir_id, ident.name) }; fn_maps.add_variable(var); }) @@ -418,8 +418,8 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { } Struct(_, ref fields, _) => { for field in fields { - if field.node.is_shorthand { - shorthand_field_ids.insert(field.node.pat.hir_id); + if field.is_shorthand { + shorthand_field_ids.insert(field.pat.hir_id); } } } @@ -1525,8 +1525,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { - for arg in &body.arguments { - arg.pat.each_binding(|_bm, hir_id, _, ident| { + for param in &body.params { + param.pat.each_binding(|_bm, hir_id, _, ident| { let sp = ident.span; let var = self.variable(hir_id, sp); // Ignore unused self. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 77d6f39324..73ca981bbe 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1282,11 +1282,17 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { }; for fp in field_pats { - let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2) - let f_index = self.tcx.field_index(fp.node.hir_id, self.tables); + let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2) + let f_index = self.tcx.field_index(fp.hir_id, self.tables); let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index, - fp.node.ident, field_ty)); - self.cat_pattern_(cmt_field, &fp.node.pat, op)?; + fp.ident, field_ty)); + self.cat_pattern_(cmt_field, &fp.pat, op)?; + } + } + + PatKind::Or(ref pats) => { + for pat in pats { + self.cat_pattern_(cmt.clone(), &pat, op)?; } } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 76d8a6738f..c2bcd46216 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -33,6 +33,9 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAt } match item.node { + hir::ItemKind::Fn(_, header, ..) if header.is_const() => { + return true; + } hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id)); @@ -52,6 +55,11 @@ fn method_might_be_inlined( if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true } + if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.node { + if method_sig.header.is_const() { + return true + } + } if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_src) { match tcx.hir().find(impl_hir_id) { Some(Node::Item(item)) => diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 88c1971581..87470140e3 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -6,29 +6,27 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +use crate::hir; +use crate::hir::Node; +use crate::hir::def_id::DefId; +use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; use crate::ich::{StableHashingContext, NodeIdHashingMode}; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use crate::ty; +use crate::ty::{self, DefIdTree, TyCtxt}; +use crate::ty::query::Providers; -use std::mem; -use std::fmt; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_macros::HashStable; use syntax::source_map; use syntax_pos::{Span, DUMMY_SP}; -use crate::ty::{DefIdTree, TyCtxt}; -use crate::ty::query::Providers; -use crate::hir; -use crate::hir::Node; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; -use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, - StableHasherResult}; +use std::fmt; +use std::mem; -/// Scope represents a statically-describable scope that can be -/// used to bound the lifetime/region for values. +/// Represents a statically-describable scope that can be used to +/// bound the lifetime/region for values. /// /// `Node(node_id)`: Any AST node that has any scope at all has the /// `Node(node_id)` scope. Other variants represent special cases not @@ -225,7 +223,7 @@ pub struct ScopeTree { /// have lifetime parameters free in this body. root_parent: Option, - /// `parent_map` maps from a scope ID to the enclosing scope id; + /// Maps from a scope ID to the enclosing scope id; /// this is usually corresponding to the lexical nesting, though /// in the case of closures the parent scope is the innermost /// conditional expression or repeating block. (Note that the @@ -233,17 +231,17 @@ pub struct ScopeTree { /// the closure itself.) parent_map: FxHashMap, - /// `var_map` maps from a variable or binding ID to the block in - /// which that variable is declared. + /// Maps from a variable or binding ID to the block in which that + /// variable is declared. var_map: FxHashMap, - /// maps from a `NodeId` to the associated destruction scope (if any) + /// Maps from a `NodeId` to the associated destruction scope (if any). destruction_scopes: FxHashMap, - /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is - /// larger than the default. The map goes from the expression id - /// to the cleanup scope id. For rvalues not present in this - /// table, the appropriate cleanup scope is the innermost + /// `rvalue_scopes` includes entries for those expressions whose + /// cleanup scope is larger than the default. The map goes from the + /// expression ID to the cleanup scope id. For rvalues not present in + /// this table, the appropriate cleanup scope is the innermost /// enclosing statement, conditional expression, or repeating /// block (see `terminating_scopes`). /// In constants, None is used to indicate that certain expressions @@ -318,7 +316,7 @@ pub struct ScopeTree { /// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`, /// QED. /// - /// I don't think this property relies on `3.` in an essential way - it + /// This property ought to not on (3) in an essential way -- it /// is probably still correct even if we have "unrestricted" terminating /// scopes. However, why use the complicated proof when a simple one /// works? @@ -341,20 +339,20 @@ pub struct ScopeTree { #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct YieldData { - /// `Span` of the yield. + /// The `Span` of the yield. pub span: Span, - /// The number of expressions and patterns appearing before the `yield` in the body + 1. + /// The number of expressions and patterns appearing before the `yield` in the body plus one. pub expr_and_pat_count: usize, pub source: hir::YieldSource, } #[derive(Debug, Copy, Clone)] pub struct Context { - /// the root of the current region tree. This is typically the id + /// The root of the current region tree. This is typically the id /// of the innermost fn body. Each fn forms its own disjoint tree /// in the region hierarchy. These fn bodies are themselves /// arranged into a tree. See the "Modeling closures" section of - /// the README in infer::region_constraints for more + /// the README in `infer::region_constraints` for more /// details. root_id: Option, @@ -369,15 +367,15 @@ pub struct Context { struct RegionResolutionVisitor<'tcx> { tcx: TyCtxt<'tcx>, - // The number of expressions and patterns visited in the current body + // The number of expressions and patterns visited in the current body. expr_and_pat_count: usize, // When this is `true`, we record the `Scopes` we encounter // when processing a Yield expression. This allows us to fix // up their indices. pessimistic_yield: bool, - // Stores scopes when pessimistic_yield is true. + // Stores scopes when `pessimistic_yield` is `true`. fixup_scopes: Vec, - // Generated scope tree: + // The generated scope tree. scope_tree: ScopeTree, cx: Context, @@ -411,7 +409,7 @@ struct ExprLocatorVisitor { expr_and_pat_count: usize, } -// This visitor has to have the same visit_expr calls as RegionResolutionVisitor +// This visitor has to have the same `visit_expr` calls as `RegionResolutionVisitor` // since `expr_count` is compared against the results there. impl<'tcx> Visitor<'tcx> for ExprLocatorVisitor { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { @@ -456,7 +454,7 @@ impl<'tcx> ScopeTree { assert!(prev.is_none()); } - // record the destruction scopes for later so we can query them + // Record the destruction scopes for later so we can query them. if let ScopeData::Destruction = child.data { self.destruction_scopes.insert(child.item_local_id(), child); } @@ -478,7 +476,7 @@ impl<'tcx> ScopeTree { self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_closure` is defined within `sup_closure`. These ids + /// Records that `sub_closure` is defined within `sup_closure`. These IDs /// should be the ID of the block that is the fn body, which is /// also the root of the region hierarchy for that fn. fn record_closure_parent(&mut self, @@ -505,14 +503,14 @@ impl<'tcx> ScopeTree { self.rvalue_scopes.insert(var, lifetime); } + /// Returns the narrowest scope that encloses `id`, if any. pub fn opt_encl_scope(&self, id: Scope) -> Option { - //! Returns the narrowest scope that encloses `id`, if any. self.parent_map.get(&id).cloned().map(|(p, _)| p) } + /// Returns the narrowest scope that encloses `id`, if any. #[allow(dead_code)] // used in cfg pub fn encl_scope(&self, id: Scope) -> Scope { - //! Returns the narrowest scope that encloses `id`, if any. self.opt_encl_scope(id).unwrap() } @@ -522,16 +520,15 @@ impl<'tcx> ScopeTree { bug!("no enclosing scope for id {:?}", var_id)) } + /// Returns the scope when the temp created by `expr_id` will be cleaned up. pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option { - //! Returns the scope when temp created by expr_id will be cleaned up - - // check for a designated rvalue scope + // Check for a designated rvalue scope. if let Some(&s) = self.rvalue_scopes.get(&expr_id) { debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s); return s; } - // else, locate the innermost terminating scope + // Otherwise, locate the innermost terminating scope // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. @@ -552,9 +549,8 @@ impl<'tcx> ScopeTree { return None; } + /// Returns the lifetime of the variable `id`. pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind { - //! Returns the lifetime of the variable `id`. - let scope = ty::ReScope(self.var_scope(id)); debug!("var_region({:?}) = {:?}", id, scope); scope @@ -589,7 +585,7 @@ impl<'tcx> ScopeTree { return true; } - /// Returns the ID of the innermost containing body + /// Returns the ID of the innermost containing body. pub fn containing_body(&self, mut scope: Scope) -> Option { loop { if let ScopeData::CallSite = scope.data { @@ -1140,7 +1136,7 @@ fn resolve_local<'tcx>( // Rule A. `let (ref x, ref y) = (foo().x, 44)`. The rvalue `(22, 44)` // would have an extended lifetime, but not `foo()`. // - // Rule B. `let x = &foo().x`. The rvalue ``foo()` would have extended + // Rule B. `let x = &foo().x`. The rvalue `foo()` would have extended // lifetime. // // In some cases, multiple rules may apply (though not to the same @@ -1207,7 +1203,7 @@ fn resolve_local<'tcx>( PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true, PatKind::Struct(_, ref field_pats, _) => { - field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat)) + field_pats.iter().any(|fp| is_binding_pat(&fp.pat)) } PatKind::Slice(ref pats1, ref pats2, ref pats3) => { @@ -1383,8 +1379,8 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); - for argument in &body.arguments { - self.visit_pat(&argument.pat); + for param in &body.params { + self.visit_pat(¶m.pat); } // The body of the every fn is a root scope. diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f8f01f79e1..d833a34385 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -5,6 +5,8 @@ //! used between functions, and they operate in a purely top-down //! way. Therefore, we break lifetime name resolution into a separate pass. +// ignore-tidy-filelength + use crate::hir::def::{Res, DefKind}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use crate::hir::map::Map; @@ -15,7 +17,7 @@ use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use crate::rustc::lint; use crate::session::Session; use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet}; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use rustc_macros::HashStable; use std::borrow::Cow; use std::cell::Cell; @@ -556,6 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty); + debug!("visit_ty: ty.node={:?}", ty.node); match ty.node { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); @@ -585,11 +588,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.is_in_fn_syntax = was_in_fn_syntax; } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { + debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime); for bound in bounds { self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); } match lifetime.name { LifetimeName::Implicit => { + // For types like `dyn Foo`, we should + // generate a special form of elided. + span_bug!( + ty.span, + "object-lifetime-default expected, not implict", + ); + } + LifetimeName::ImplicitObjectLifetimeDefault => { // If the user does not write *anything*, we // use the object lifetime defaulting // rules. So e.g., `Box` becomes @@ -897,6 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { + debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref); if lifetime_ref.is_elided() { self.resolve_elided_lifetimes(vec![lifetime_ref]); return; @@ -1911,6 +1924,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn visit_segment_args(&mut self, res: Res, depth: usize, generic_args: &'tcx hir::GenericArgs) { + debug!( + "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})", + res, + depth, + generic_args, + ); + if generic_args.parenthesized { let was_in_fn_syntax = self.is_in_fn_syntax; self.is_in_fn_syntax = true; @@ -1964,6 +1984,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, }; + debug!("visit_segment_args: type_def_id={:?}", type_def_id); + + // Compute a vector of defaults, one for each type parameter, + // per the rules given in RFCs 599 and 1156. Example: + // + // ```rust + // struct Foo<'a, T: 'a, U> { } + // ``` + // + // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default + // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound) + // and `dyn Baz` to `dyn Baz + 'static` (because there is no + // such bound). + // + // Therefore, we would compute `object_lifetime_defaults` to a + // vector like `['x, 'static]`. Note that the vector only + // includes type parameters. let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| { let in_body = { let mut scope = self.scope; @@ -2003,6 +2040,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect() }) }; + debug!("visit_segment_args: unsubst={:?}", unsubst); unsubst .iter() .map(|set| match *set { @@ -2023,6 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect() }); + debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); + let mut i = 0; for arg in &generic_args.args { match arg { @@ -2045,8 +2085,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } + // Hack: when resolving the type `XX` in binding like `dyn + // Foo<'b, Item = XX>`, the current object-lifetime default + // would be to examine the trait `Foo` to check whether it has + // a lifetime bound declared on `Item`. e.g., if `Foo` is + // declared like so, then the default object lifetime bound in + // `XX` should be `'b`: + // + // ```rust + // trait Foo<'a> { + // type Item: 'a; + // } + // ``` + // + // but if we just have `type Item;`, then it would be + // `'static`. However, we don't get all of this logic correct. + // + // Instead, we do something hacky: if there are no lifetime parameters + // to the trait, then we simply use a default object lifetime + // bound of `'static`, because there is no other possibility. On the other hand, + // if there ARE lifetime parameters, then we require the user to give an + // explicit bound for now. + // + // This is intended to leave room for us to implement the + // correct behavior in the future. + let has_lifetime_parameter = generic_args + .args + .iter() + .any(|arg| match arg { + GenericArg::Lifetime(_) => true, + _ => false, + }); + + // Resolve lifetimes found in the type `XX` from `Item = XX` bindings. for b in &generic_args.bindings { - self.visit_assoc_type_binding(b); + let scope = Scope::ObjectLifetimeDefault { + lifetime: if has_lifetime_parameter { + None + } else { + Some(Region::Static) + }, + s: self.scope, + }; + self.with(scope, |_, this| this.visit_assoc_type_binding(b)); } } @@ -2347,6 +2428,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); + if lifetime_refs.is_empty() { return; } @@ -2474,7 +2557,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } = info; let help_name = if let Some(ident) = parent.and_then(|body| { - self.tcx.hir().body(body).arguments[index].pat.simple_ident() + self.tcx.hir().body(body).params[index].pat.simple_ident() }) { format!("`{}`", ident) } else { @@ -2539,6 +2622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { + debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; let mut scope = self.scope; let lifetime = loop { @@ -2638,6 +2722,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => { self.resolve_lifetime_ref(lt); } + hir::LifetimeName::ImplicitObjectLifetimeDefault => { + self.tcx.sess.delay_span_bug( + lt.span, + "lowering generated `ImplicitObjectLifetimeDefault` \ + outside of an object type", + ) + } hir::LifetimeName::Error => { // No need to do anything, error already reported. } @@ -2956,7 +3047,7 @@ pub fn report_missing_lifetime_specifiers( span, E0106, "missing lifetime specifier{}", - if count > 1 { "s" } else { "" } + pluralise!(count) ) } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 0d22c37cd6..c06a0feb6a 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -290,10 +290,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required, + self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required, |v| { - if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() { - v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required, + if let Some(ctor_hir_id) = var.data.ctor_hir_id() { + v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required, |_| {}); } @@ -372,7 +372,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.check_missing_stability(var.node.id, var.span, "variant"); + self.check_missing_stability(var.id, var.span, "variant"); intravisit::walk_variant(self, var, g, item_id); } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 4fb88dadd1..fa5fa2257d 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -116,8 +116,8 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Context<'a, 'tcx> { - fn register(&mut self, name: &str, span: Span) { - $(if name == stringify!($name) { + fn register(&mut self, name: Symbol, span: Span) { + $(if name == sym::$name { if self.items.$name().is_none() { self.items.missing.push(lang_items::$item); } @@ -136,7 +136,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &hir::ForeignItem) { if let Some((lang_item, _)) = lang_items::extract(&i.attrs) { - self.register(&lang_item.as_str(), i.span); + self.register(lang_item, i.span); } intravisit::walk_foreign_item(self, i) } diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 3d33e24953..1f60487784 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -27,7 +27,7 @@ impl<'a> HashStable> for Cache { fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - // do nothing + // Do nothing. } } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ce04cca96e..15e6cb6bca 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -4,30 +4,46 @@ use super::{ Pointer, InterpResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar, }; +use crate::mir; use crate::ty::layout::{Size, Align}; + +use rustc_data_structures::sorted_map::SortedMap; +use rustc_target::abi::HasDataLayout; use syntax::ast::Mutability; use std::iter; -use crate::mir; use std::ops::{Range, Deref, DerefMut}; -use rustc_data_structures::sorted_map::SortedMap; -use rustc_target::abi::HasDataLayout; use std::borrow::Cow; -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub struct Allocation { +// NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in +// `src/librustc_mir/interpret/snapshot.rs`. +#[derive( + Clone, + Debug, + Eq, + PartialEq, + PartialOrd, + Ord, + Hash, + RustcEncodable, + RustcDecodable, + HashStable, +)] +pub struct Allocation { /// The actual bytes of the allocation. - /// Note that the bytes of a pointer represent the offset of the pointer - pub bytes: Vec, + /// Note that the bytes of a pointer represent the offset of the pointer. + bytes: Vec, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting /// at the given offset. - pub relocations: Relocations, - /// Denotes undefined memory. Reading from undefined memory is forbidden in miri - pub undef_mask: UndefMask, + relocations: Relocations, + /// Denotes which part of this allocation is initialized. + undef_mask: UndefMask, + /// The size of the allocation. Currently, must always equal `bytes.len()`. + pub size: Size, /// The alignment of the allocation to detect unaligned reads. pub align: Align, - /// Whether the allocation is mutable. + /// `true` if the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, /// which happens for `static mut` and `static` with interior mutability. pub mutability: Mutability, @@ -35,7 +51,6 @@ pub struct Allocation { pub extra: Extra, } - pub trait AllocationExtra: ::std::fmt::Debug + Clone { // There is no constructor in here because the constructor's type depends // on `MemoryKind`, and making things sufficiently generic leads to painful @@ -77,7 +92,7 @@ pub trait AllocationExtra: ::std::fmt::Debug + Clone { } } -// For Tag=() and no extra state, we have is a trivial implementation. +// For `Tag = ()` and no extra state, we have a trivial implementation. impl AllocationExtra<()> for () { } // The constructors are all without extra; the extra gets added by a machine hook later. @@ -85,11 +100,12 @@ impl Allocation { /// Creates a read-only allocation initialized by the given bytes pub fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { let bytes = slice.into().into_owned(); - let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true); + let size = Size::from_bytes(bytes.len() as u64); Self { bytes, relocations: Relocations::new(), - undef_mask, + undef_mask: UndefMask::new(size, true), + size, align, mutability: Mutability::Immutable, extra: (), @@ -106,6 +122,7 @@ impl Allocation { bytes: vec![0; size.bytes() as usize], relocations: Relocations::new(), undef_mask: UndefMask::new(size, false), + size, align, mutability: Mutability::Mutable, extra: (), @@ -113,9 +130,62 @@ impl Allocation { } } +impl Allocation<(), ()> { + /// Add Tag and Extra fields + pub fn with_tags_and_extra( + self, + mut tagger: impl FnMut(AllocId) -> T, + extra: E, + ) -> Allocation { + Allocation { + bytes: self.bytes, + size: self.size, + relocations: Relocations::from_presorted( + self.relocations.iter() + // The allocations in the relocations (pointers stored *inside* this allocation) + // all get the base pointer tag. + .map(|&(offset, ((), alloc))| { + let tag = tagger(alloc); + (offset, (tag, alloc)) + }) + .collect() + ), + undef_mask: self.undef_mask, + align: self.align, + mutability: self.mutability, + extra, + } + } +} + +/// Raw accessors. Provide access to otherwise private bytes. +impl Allocation { + pub fn len(&self) -> usize { + self.size.bytes() as usize + } + + /// Looks at a slice which may describe undefined bytes or describe a relocation. This differs + /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the + /// edges) at all. It further ignores `AllocationExtra` callbacks. + /// This must not be used for reads affecting the interpreter execution. + pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { + &self.bytes[range] + } + + /// Returns the undef mask. + pub fn undef_mask(&self) -> &UndefMask { + &self.undef_mask + } + + /// Returns the relocation list. + pub fn relocations(&self) -> &Relocations { + &self.relocations + } +} + impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} -/// Byte accessors +/// Byte accessors. impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Just a small local helper function to avoid a bit of code repetition. /// Returns the range of this allocation that was meant. @@ -125,16 +195,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { offset: Size, size: Size ) -> Range { - let end = offset + size; // this does overflow checking + let end = offset + size; // This does overflow checking. assert_eq!( end.bytes() as usize as u64, end.bytes(), "cannot handle this access on this host architecture" ); let end = end.bytes() as usize; assert!( - end <= self.bytes.len(), + end <= self.len(), "Out-of-bounds access at offset {}, size {} in allocation of size {}", - offset.bytes(), size.bytes(), self.bytes.len() + offset.bytes(), size.bytes(), self.len() ); (offset.bytes() as usize)..end } @@ -162,7 +232,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.check_defined(ptr, size)?; self.check_relocations(cx, ptr, size)?; } else { - // We still don't want relocations on the *edges* + // We still don't want relocations on the *edges*. self.check_relocation_edges(cx, ptr, size)?; } @@ -171,7 +241,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(&self.bytes[range]) } - /// Check that these bytes are initialized and not pointer bytes, and then return them + /// Checks that these bytes are initialized and not pointer bytes, and then return them /// as a slice. /// /// It is the caller's responsibility to check bounds and alignment beforehand. @@ -223,7 +293,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } } -/// Reading and writing +/// Reading and writing. impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// before a `0` is found. @@ -259,9 +329,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { allow_ptr_and_undef: bool, ) -> InterpResult<'tcx> { - // Check bounds and relocations on the edges + // Check bounds and relocations on the edges. self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; - // Check undef and ptr + // Check undef and ptr. if !allow_ptr_and_undef { self.check_defined(ptr, size)?; self.check_relocations(cx, ptr, size)?; @@ -302,12 +372,12 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - /// Read a *non-ZST* scalar + /// Reads a *non-ZST* scalar. /// - /// zsts can't be read out of two reasons: - /// * byteorder cannot work with zero element buffers - /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers - /// being valid for ZSTs + /// ZSTs can't be read for two reasons: + /// * byte-order cannot work with zero-element buffers; + /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer + /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn read_scalar( @@ -317,20 +387,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size ) -> InterpResult<'tcx, ScalarMaybeUndef> { - // get_bytes_unchecked tests relocation edges + // `get_bytes_unchecked` tests relocation edges. let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. - // We must not return Ok() for unaligned pointers! + // We must not return `Ok()` for unaligned pointers! if self.check_defined(ptr, size).is_err() { - // this inflates undefined bytes to the entire scalar, even if only a few - // bytes are undefined + // This inflates undefined bytes to the entire scalar, even if only a few + // bytes are undefined. return Ok(ScalarMaybeUndef::Undef); } - // Now we do the actual reading + // Now we do the actual reading. let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); - // See if we got a pointer + // See if we got a pointer. if size != cx.data_layout().pointer_size { - // *Now* better make sure that the inside also is free of relocations. + // *Now*, we better make sure that the inside is free of relocations too. self.check_relocations(cx, ptr, size)?; } else { match self.relocations.get(&ptr.offset) { @@ -345,7 +415,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) } - /// Read a pointer-sized scalar. + /// Reads a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn read_ptr_sized( @@ -357,12 +427,12 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.read_scalar(cx, ptr, cx.data_layout().pointer_size) } - /// Write a *non-ZST* scalar + /// Writes a *non-ZST* scalar. /// - /// zsts can't be read out of two reasons: - /// * byteorder cannot work with zero element buffers - /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers - /// being valid for ZSTs + /// ZSTs can't be read for two reasons: + /// * byte-order cannot work with zero-element buffers; + /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer + /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn write_scalar( @@ -390,7 +460,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let dst = self.get_bytes_mut(cx, ptr, type_size)?; write_target_uint(endian, dst, bytes).unwrap(); - // See if we have to also write a relocation + // See if we have to also write a relocation. match val { Scalar::Ptr(val) => { self.relocations.insert( @@ -404,7 +474,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - /// Write a pointer-sized scalar. + /// Writes a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn write_ptr_sized( @@ -419,10 +489,10 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } } -/// Relocations +/// Relocations. impl<'tcx, Tag: Copy, Extra> Allocation { - /// Returns all relocations overlapping with the given ptr-offset pair. - pub fn relocations( + /// Returns all relocations overlapping with the given pointer-offset pair. + pub fn get_relocations( &self, cx: &impl HasDataLayout, ptr: Pointer, @@ -431,7 +501,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); - let end = ptr.offset + size; // this does overflow checking + let end = ptr.offset + size; // This does overflow checking. self.relocations.range(Size::from_bytes(start)..end) } @@ -443,7 +513,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { ptr: Pointer, size: Size, ) -> InterpResult<'tcx> { - if self.relocations(cx, ptr, size).is_empty() { + if self.get_relocations(cx, ptr, size).is_empty() { Ok(()) } else { throw_unsup!(ReadPointerAsBytes) @@ -465,7 +535,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. - let relocations = self.relocations(cx, ptr, size); + let relocations = self.get_relocations(cx, ptr, size); if relocations.is_empty() { return Ok(()); } @@ -491,7 +561,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { Ok(()) } - /// Error if there are relocations overlapping with the edges of the + /// Errors if there are relocations overlapping with the edges of the /// given memory range. #[inline] fn check_relocation_edges( @@ -507,7 +577,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } -/// Undefined bytes +/// Undefined bytes. impl<'tcx, Tag, Extra> Allocation { /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` /// error which will report the first byte which is undefined. @@ -536,9 +606,97 @@ impl<'tcx, Tag, Extra> Allocation { } } -/// Relocations +/// Run-length encoding of the undef mask. +/// Used to copy parts of a mask multiple times to another allocation. +pub struct AllocationDefinedness { + /// The definedness of the first range. + initial: bool, + /// The lengths of ranges that are run-length encoded. + /// The definedness of the ranges alternate starting with `initial`. + ranges: smallvec::SmallVec::<[u64; 1]>, +} + +/// Transferring the definedness mask to other allocations. +impl Allocation { + /// Creates a run-length encoding of the undef mask. + pub fn compress_undef_range( + &self, + src: Pointer, + size: Size, + ) -> AllocationDefinedness { + // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), + // a naive undef mask copying algorithm would repeatedly have to read the undef mask from + // the source and write it to the destination. Even if we optimized the memory accesses, + // we'd be doing all of this `repeat` times. + // Therefor we precompute a compressed version of the undef mask of the source value and + // then write it back `repeat` times without computing any more information from the source. + + // A precomputed cache for ranges of defined/undefined bits + // 0000010010001110 will become + // `[5, 1, 2, 1, 3, 3, 1]`, + // where each element toggles the state. + + let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); + let initial = self.undef_mask.get(src.offset); + let mut cur_len = 1; + let mut cur = initial; + + for i in 1..size.bytes() { + // FIXME: optimize to bitshift the current undef block's bits and read the top bit. + if self.undef_mask.get(src.offset + Size::from_bytes(i)) == cur { + cur_len += 1; + } else { + ranges.push(cur_len); + cur_len = 1; + cur = !cur; + } + } + + ranges.push(cur_len); + + AllocationDefinedness { ranges, initial, } + } + + /// Applies multiple instances of the run-length encoding to the undef mask. + pub fn mark_compressed_undef_range( + &mut self, + defined: &AllocationDefinedness, + dest: Pointer, + size: Size, + repeat: u64, + ) { + // An optimization where we can just overwrite an entire range of definedness bits if + // they are going to be uniformly `1` or `0`. + if defined.ranges.len() <= 1 { + self.undef_mask.set_range_inbounds( + dest.offset, + dest.offset + size * repeat, + defined.initial, + ); + return; + } + + for mut j in 0..repeat { + j *= size.bytes(); + j += dest.offset.bytes(); + let mut cur = defined.initial; + for range in &defined.ranges { + let old_j = j; + j += range; + self.undef_mask.set_range_inbounds( + Size::from_bytes(old_j), + Size::from_bytes(j), + cur, + ); + cur = !cur; + } + } + } +} + +/// Relocations. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Relocations(SortedMap); +pub struct Relocations(SortedMap); impl Relocations { pub fn new() -> Self { @@ -566,6 +724,59 @@ impl DerefMut for Relocations { } } +/// A partial, owned list of relocations to transfer into another allocation. +pub struct AllocationRelocations { + relative_relocations: Vec<(Size, (Tag, AllocId))>, +} + +impl Allocation { + pub fn prepare_relocation_copy( + &self, + cx: &impl HasDataLayout, + src: Pointer, + size: Size, + dest: Pointer, + length: u64, + ) -> AllocationRelocations { + let relocations = self.get_relocations(cx, src, size); + if relocations.is_empty() { + return AllocationRelocations { relative_relocations: Vec::new() }; + } + + let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); + + for i in 0..length { + new_relocations.extend( + relocations + .iter() + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) + ); + } + + AllocationRelocations { + relative_relocations: new_relocations, + } + } + + /// Applies a relocation copy. + /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected + /// to be clear of relocations. + pub fn mark_relocation_range( + &mut self, + relocations: AllocationRelocations, + ) { + self.relocations.insert_presorted(relocations.relative_relocations); + } +} + //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking //////////////////////////////////////////////////////////////////////////////// @@ -627,8 +838,8 @@ impl UndefMask { let (blocka, bita) = bit_index(start); let (blockb, bitb) = bit_index(end); if blocka == blockb { - // first set all bits but the first `bita` - // then unset the last `64 - bitb` bits + // First set all bits except the first `bita`, + // then unset the last `64 - bitb` bits. let range = if bitb == 0 { u64::max_value() << bita } else { @@ -643,24 +854,24 @@ impl UndefMask { } // across block boundaries if new_state { - // set bita..64 to 1 + // Set `bita..64` to `1`. self.blocks[blocka] |= u64::max_value() << bita; - // set 0..bitb to 1 + // Set `0..bitb` to `1`. if bitb != 0 { self.blocks[blockb] |= u64::max_value() >> (64 - bitb); } - // fill in all the other blocks (much faster than one bit at a time) + // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1) .. blockb { self.blocks[block] = u64::max_value(); } } else { - // set bita..64 to 0 + // Set `bita..64` to `0`. self.blocks[blocka] &= !(u64::max_value() << bita); - // set 0..bitb to 0 + // Set `0..bitb` to `0`. if bitb != 0 { self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb)); } - // fill in all the other blocks (much faster than one bit at a time) + // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1) .. blockb { self.blocks[block] = 0; } @@ -697,7 +908,7 @@ impl UndefMask { let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1; assert_eq!(additional_blocks as usize as u64, additional_blocks); self.blocks.extend( - // FIXME(oli-obk): optimize this by repeating `new_state as Block` + // FIXME(oli-obk): optimize this by repeating `new_state as Block`. iter::repeat(0).take(additional_blocks as usize), ); } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index ef0e205184..ac99ccd45e 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,23 +1,21 @@ -use std::{fmt, env}; +use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef}; use crate::hir; use crate::hir::map::definitions::DefPathData; use crate::mir; use crate::ty::{self, Ty, layout}; use crate::ty::layout::{Size, Align, LayoutError}; -use rustc_target::spec::abi::Abi; -use rustc_macros::HashStable; - -use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef}; +use crate::ty::query::TyCtxtAt; use backtrace::Backtrace; - -use crate::ty::query::TyCtxtAt; use errors::DiagnosticBuilder; - +use rustc_macros::HashStable; +use rustc_target::spec::abi::Abi; use syntax_pos::{Pos, Span}; use syntax::symbol::Symbol; +use std::{fmt, env}; + #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { /// Already reported a lint or an error for this evaluation. @@ -215,6 +213,15 @@ fn print_backtrace(backtrace: &mut Backtrace) { eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace); } +impl From for InterpErrorInfo<'tcx> { + fn from(err: ErrorHandled) -> Self { + match err { + ErrorHandled::Reported => err_inval!(ReferencedConstant), + ErrorHandled::TooGeneric => err_inval!(TooGeneric), + }.into() + } +} + impl<'tcx> From> for InterpErrorInfo<'tcx> { fn from(kind: InterpError<'tcx>) -> Self { let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") { @@ -315,6 +322,9 @@ impl fmt::Debug for PanicInfo { } } +/// Error information for when the program we executed turned out not to actually be a valid +/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp +/// where we work on generic code or execution does not have all information available. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum InvalidProgramInfo<'tcx> { /// Resolution can fail if we are in a too generic context. @@ -344,6 +354,7 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> { } } +/// Error information for when the program caused Undefined Behavior. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum UndefinedBehaviorInfo { /// Free-form case. Only for errors that are never caught! @@ -366,12 +377,19 @@ impl fmt::Debug for UndefinedBehaviorInfo { } } +/// Error information for when the program did something that might (or might not) be correct +/// to do according to the Rust spec, but due to limitations in the interpreter, the +/// operation could not be carried out. These limitations can differ between CTFE and the +/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers. +/// +/// Currently, we also use this as fall-back error kind for errors that have not been +/// categorized yet. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsupportedOpInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Unsupported(String), - // -- Everything below is not classified yet -- + // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>), @@ -430,13 +448,13 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { match self { PointerOutOfBounds { ptr, msg, allocation_size } => { write!(f, "{} failed: pointer must be in-bounds at offset {}, \ - but is outside bounds of allocation {} which has size {}", + but is outside bounds of allocation {} which has size {}", msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, ValidationFailure(ref err) => { write!(f, "type validation failed: {}", err) } - NoMirFor(ref func) => write!(f, "no mir for `{}`", func), + NoMirFor(ref func) => write!(f, "no MIR for `{}`", func), FunctionAbiMismatch(caller_abi, callee_abi) => write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}", callee_abi, caller_abi), @@ -451,9 +469,9 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { FunctionArgCountMismatch => write!(f, "tried to call a function with incorrect number of arguments"), ReallocatedWrongMemoryKind(ref old, ref new) => - write!(f, "tried to reallocate memory from {} to {}", old, new), + write!(f, "tried to reallocate memory from `{}` to `{}`", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => - write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new), + write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new), InvalidChar(c) => write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c), AlignmentCheckFailed { required, has } => @@ -462,7 +480,7 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), PathNotFound(ref path) => - write!(f, "Cannot find path {:?}", path), + write!(f, "cannot find path {:?}", path), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, \ got size {} and align {}", @@ -525,7 +543,7 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { InvalidBoolOp(_) => write!(f, "invalid boolean operation"), UnterminatedCString(_) => - write!(f, "attempted to get length of a null terminated string, but no null \ + write!(f, "attempted to get length of a null-terminated string, but no null \ found before end of allocation"), ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"), @@ -538,6 +556,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { } } +/// Error information for when the program exhausted the resources granted to it +/// by the interpreter. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum ResourceExhaustionInfo { /// The stack grew too big. @@ -582,7 +602,7 @@ pub type InterpResult<'tcx, T = ()> = Result>; impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Forward `Display` to `Debug` + // Forward `Display` to `Debug`. write!(f, "{:?}", self) } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 1ec95c29a4..23433c2e88 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -1,4 +1,4 @@ -//! An interpreter for MIR used in CTFE and by miri +//! An interpreter for MIR used in CTFE and by miri. #[macro_export] macro_rules! err_unsup { @@ -107,21 +107,21 @@ pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask}; pub use self::pointer::{Pointer, PointerArithmetic, CheckInAllocMsg}; -use std::fmt; use crate::mir; use crate::hir::def_id::DefId; use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind}; +use crate::ty::codec::TyDecoder; use crate::ty::layout::{self, Size}; use std::io; +use std::fmt; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicU32, Ordering}; use rustc_serialize::{Encoder, Decodable, Encodable}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::{Lock as Mutex, HashMapExt}; +use rustc_data_structures::sync::{Lock, HashMapExt}; use rustc_data_structures::tiny_list::TinyList; use rustc_macros::HashStable; use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian}; -use crate::ty::codec::TyDecoder; -use std::sync::atomic::{AtomicU32, Ordering}; -use std::num::NonZeroU32; /// Uniquely identifies a specific constant or static. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable)] @@ -152,8 +152,8 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>( tcx: TyCtxt<'tcx>, alloc_id: AllocId, ) -> Result<(), E::Error> { - let alloc: GlobalAlloc<'tcx> = - tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId"); + let alloc: GlobalAlloc<'tcx> = tcx.alloc_map.lock().get(alloc_id) + .expect("no value for given alloc ID"); match alloc { GlobalAlloc::Memory(alloc) => { trace!("encoding {:?} with {:#?}", alloc_id, alloc); @@ -166,8 +166,8 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>( fn_instance.encode(encoder)?; } GlobalAlloc::Static(did) => { - // referring to statics doesn't need to know about their allocations, - // just about its DefId + // References to statics doesn't need to know about their allocations, + // just about its `DefId`. AllocDiscriminant::Static.encode(encoder)?; did.encode(encoder)?; } @@ -187,19 +187,18 @@ enum State { } pub struct AllocDecodingState { - // For each AllocId we keep track of which decoding state it's currently in. - decoding_state: Vec>, + // For each `AllocId`, we keep track of which decoding state it's currently in. + decoding_state: Vec>, // The offsets of each allocation in the data stream. data_offsets: Vec, } impl AllocDecodingState { - pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> { static DECODER_SESSION_ID: AtomicU32 = AtomicU32::new(0); let counter = DECODER_SESSION_ID.fetch_add(1, Ordering::SeqCst); - // Make sure this is never zero + // Make sure this is never zero. let session_id = DecodingSessionId::new((counter & 0x7FFFFFFF) + 1).unwrap(); AllocDecodingSession { @@ -208,10 +207,10 @@ impl AllocDecodingState { } } - pub fn new(data_offsets: Vec) -> AllocDecodingState { - let decoding_state = vec![Mutex::new(State::Empty); data_offsets.len()]; + pub fn new(data_offsets: Vec) -> Self { + let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()]; - AllocDecodingState { + Self { decoding_state, data_offsets, } @@ -225,23 +224,23 @@ pub struct AllocDecodingSession<'s> { } impl<'s> AllocDecodingSession<'s> { - // Decodes an AllocId in a thread-safe way. + /// Decodes an `AllocId` in a thread-safe way. pub fn decode_alloc_id(&self, decoder: &mut D) -> Result where D: TyDecoder<'tcx>, { - // Read the index of the allocation + // Read the index of the allocation. let idx = decoder.read_u32()? as usize; let pos = self.state.data_offsets[idx] as usize; - // Decode the AllocDiscriminant now so that we know if we have to reserve an - // AllocId. + // Decode the `AllocDiscriminant` now so that we know if we have to reserve an + // `AllocId`. let (alloc_kind, pos) = decoder.with_position(pos, |decoder| { let alloc_kind = AllocDiscriminant::decode(decoder)?; Ok((alloc_kind, decoder.position())) })?; - // Check the decoding state, see if it's already decoded or if we should + // Check the decoding state to see if it's already decoded or if we should // decode it here. let alloc_id = { let mut entry = self.state.decoding_state[idx].lock(); @@ -251,11 +250,11 @@ impl<'s> AllocDecodingSession<'s> { return Ok(alloc_id); } ref mut entry @ State::Empty => { - // We are allowed to decode + // We are allowed to decode. match alloc_kind { AllocDiscriminant::Alloc => { // If this is an allocation, we need to reserve an - // AllocId so we can decode cyclic graphs. + // `AllocId` so we can decode cyclic graphs. let alloc_id = decoder.tcx().alloc_map.lock().reserve(); *entry = State::InProgress( TinyList::new_single(self.session_id), @@ -263,8 +262,8 @@ impl<'s> AllocDecodingSession<'s> { Some(alloc_id) }, AllocDiscriminant::Fn | AllocDiscriminant::Static => { - // Fns and statics cannot be cyclic and their AllocId - // is determined later by interning + // Fns and statics cannot be cyclic, and their `AllocId` + // is determined later by interning. *entry = State::InProgressNonAlloc( TinyList::new_single(self.session_id)); None @@ -273,9 +272,9 @@ impl<'s> AllocDecodingSession<'s> { } State::InProgressNonAlloc(ref mut sessions) => { if sessions.contains(&self.session_id) { - bug!("This should be unreachable") + bug!("this should be unreachable"); } else { - // Start decoding concurrently + // Start decoding concurrently. sessions.insert(self.session_id); None } @@ -285,7 +284,7 @@ impl<'s> AllocDecodingSession<'s> { // Don't recurse. return Ok(alloc_id) } else { - // Start decoding concurrently + // Start decoding concurrently. sessions.insert(self.session_id); Some(alloc_id) } @@ -293,20 +292,20 @@ impl<'s> AllocDecodingSession<'s> { } }; - // Now decode the actual data + // Now decode the actual data. let alloc_id = decoder.with_position(pos, |decoder| { match alloc_kind { AllocDiscriminant::Alloc => { - let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?; - // We already have a reserved AllocId. + let alloc = <&'tcx Allocation as Decodable>::decode(decoder)?; + // We already have a reserved `AllocId`. let alloc_id = alloc_id.unwrap(); - trace!("decoded alloc {:?} {:#?}", alloc_id, allocation); - decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, allocation); + trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc); + decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, alloc); Ok(alloc_id) }, AllocDiscriminant::Fn => { assert!(alloc_id.is_none()); - trace!("creating fn alloc id"); + trace!("creating fn alloc ID"); let instance = ty::Instance::decode(decoder)?; trace!("decoded fn alloc instance: {:?}", instance); let alloc_id = decoder.tcx().alloc_map.lock().create_fn_alloc(instance); @@ -314,8 +313,9 @@ impl<'s> AllocDecodingSession<'s> { }, AllocDiscriminant::Static => { assert!(alloc_id.is_none()); - trace!("creating extern static alloc id at"); + trace!("creating extern static alloc ID"); let did = DefId::decode(decoder)?; + trace!("decoded static def-ID: {:?}", did); let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did); Ok(alloc_id) } @@ -340,7 +340,7 @@ impl fmt::Display for AllocId { /// a static, or a "real" allocation with some data in it. #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)] pub enum GlobalAlloc<'tcx> { - /// The alloc ID is used as a function pointer + /// The alloc ID is used as a function pointer. Function(Instance<'tcx>), /// The alloc ID points to a "lazy" static variable that did not get computed (yet). /// This is also used to break the cycle in recursive statics. @@ -350,16 +350,17 @@ pub enum GlobalAlloc<'tcx> { } pub struct AllocMap<'tcx> { - /// Lets you know what an `AllocId` refers to. + /// Maps `AllocId`s to their corresponding allocations. alloc_map: FxHashMap>, /// Used to ensure that statics and functions only get one associated `AllocId`. /// Should never contain a `GlobalAlloc::Memory`! - /// FIXME: Should we just have two separate dedup maps for statics and functions each? + // + // FIXME: Should we just have two separate dedup maps for statics and functions each? dedup: FxHashMap, AllocId>, /// The `AllocId` to assign to the next requested ID. - /// Always incremented, never gets smaller. + /// Always incremented; never gets smaller. next_id: AllocId, } @@ -389,7 +390,7 @@ impl<'tcx> AllocMap<'tcx> { next } - /// Reserve a new ID *if* this allocation has not been dedup-reserved before. + /// Reserves a new ID *if* this allocation has not been dedup-reserved before. /// Should only be used for function pointers and statics, we don't want /// to dedup IDs for "real" memory! fn reserve_and_set_dedup(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId { @@ -430,17 +431,17 @@ impl<'tcx> AllocMap<'tcx> { } }); if is_generic { - // Get a fresh ID + // Get a fresh ID. let id = self.reserve(); self.alloc_map.insert(id, GlobalAlloc::Function(instance)); id } else { - // Deduplicate + // Deduplicate. self.reserve_and_set_dedup(GlobalAlloc::Function(instance)) } } - /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical + /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical /// `Allocation` with a different `AllocId`. /// Statics with identical content will still point to the same `Allocation`, i.e., /// their data will be deduplicated through `Allocation` interning -- but they @@ -465,19 +466,19 @@ impl<'tcx> AllocMap<'tcx> { pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation { match self.get(id) { Some(GlobalAlloc::Memory(mem)) => mem, - _ => bug!("expected allocation id {} to point to memory", id), + _ => bug!("expected allocation ID {} to point to memory", id), } } - /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old); + bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old); } } - /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called /// twice for the same `(AllocId, Allocation)` pair. fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem)); @@ -513,7 +514,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result // Methods to facilitate working with signed integers stored in a u128 //////////////////////////////////////////////////////////////////////////////// -/// Truncate `value` to `size` bits and then sign-extend it to 128 bits +/// Truncates `value` to `size` bits and then sign-extend it to 128 bits /// (i.e., if it is negative, fill with 1's on the left). #[inline] pub fn sign_extend(value: u128, size: Size) -> u128 { @@ -522,14 +523,14 @@ pub fn sign_extend(value: u128, size: Size) -> u128 { // Truncated until nothing is left. return 0; } - // sign extend + // Sign-extend it. let shift = 128 - size; - // shift the unsigned value to the left - // and back to the right as signed (essentially fills with FF on the left) + // Shift the unsigned value to the left, then shift back to the right as signed + // (essentially fills with FF on the left). (((value << shift) as i128) >> shift) as u128 } -/// Truncate `value` to `size` bits. +/// Truncates `value` to `size` bits. #[inline] pub fn truncate(value: u128, size: Size) -> u128 { let size = size.bits(); @@ -538,6 +539,6 @@ pub fn truncate(value: u128, size: Size) -> u128 { return 0; } let shift = 128 - size; - // truncate (shift left to drop out leftover values, shift right to fill with zeroes) + // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). (value << shift) >> shift } diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 0a99851337..1bb4d9ea4d 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -86,18 +86,17 @@ pub trait PointerArithmetic: layout::HasDataLayout { impl PointerArithmetic for T {} - -/// Pointer is generic over the type that represents a reference to Allocations, +/// `Pointer` is generic over the type that represents a reference to `Allocation`s, /// thus making it possible for the most convenient representation to be used in /// each context. /// -/// Defaults to the index based and loosely coupled AllocId. +/// Defaults to the index based and loosely coupled `AllocId`. /// /// Pointer is also generic over the `Tag` associated with each pointer, /// which is used to do provenance tracking during execution. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash, HashStable)] -pub struct Pointer { +pub struct Pointer { pub alloc_id: Id, pub offset: Size, pub tag: Tag, @@ -117,7 +116,7 @@ impl fmt::Debug for Pointer<(), Id> { } } -/// Produces a `Pointer` which points to the beginning of the Allocation +/// Produces a `Pointer` which points to the beginning of the `Allocation`. impl From for Pointer { #[inline(always)] fn from(alloc_id: AllocId) -> Self { @@ -189,8 +188,11 @@ impl<'tcx, Tag> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } + /// Test if the pointer is "inbounds" of an allocation of the given size. + /// A pointer is "inbounds" even if its offset is equal to the size; this is + /// a "one-past-the-end" pointer. #[inline(always)] - pub fn check_in_alloc( + pub fn check_inbounds_alloc( self, allocation_size: Size, msg: CheckInAllocMsg, diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 5381d46972..b8bc741419 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -17,8 +17,8 @@ pub struct RawConst<'tcx> { pub ty: Ty<'tcx>, } -/// Represents a constant value in Rust. `Scalar` and `ScalarPair` are optimizations that -/// match the `LocalState` optimizations for easy conversions between `Value` and `ConstValue`. +/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for +/// array length computations, enum discriminants and the pattern matching logic. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, HashStable)] pub enum ConstValue<'tcx> { @@ -91,7 +91,7 @@ impl<'tcx> ConstValue<'tcx> { /// of a simple value or a pointer into another `Allocation` #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash, HashStable)] -pub enum Scalar { +pub enum Scalar { /// The raw bytes of a simple value. Raw { /// The first `size` bytes of `data` are the value. @@ -359,7 +359,7 @@ impl<'tcx, Tag> Scalar { #[inline(always)] pub fn assert_bits(self, target_size: Size) -> u128 { - self.to_bits(target_size).expect("Expected Raw bits but got a Pointer") + self.to_bits(target_size).expect("expected Raw bits but got a Pointer") } /// Do not call this method! Use either `assert_ptr` or `force_ptr`. @@ -374,7 +374,7 @@ impl<'tcx, Tag> Scalar { #[inline(always)] pub fn assert_ptr(self) -> Pointer { - self.to_ptr().expect("Expected a Pointer but got Raw bits") + self.to_ptr().expect("expected a Pointer but got Raw bits") } /// Do not call this method! Dispatch based on the type instead. @@ -482,8 +482,8 @@ impl From> for Scalar { } } -#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] -pub enum ScalarMaybeUndef { +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)] +pub enum ScalarMaybeUndef { Scalar(Scalar), Undef, } @@ -530,7 +530,7 @@ impl<'tcx, Tag> ScalarMaybeUndef { pub fn not_undef(self) -> InterpResult<'static, Scalar> { match self { ScalarMaybeUndef::Scalar(scalar) => Ok(scalar), - ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::from_bytes(0))), + ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)), } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1e2ec08301..92efcf44de 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -18,6 +18,7 @@ use crate::ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; + use polonius_engine::Atom; use rustc_data_structures::bit_set::BitMatrix; use rustc_data_structures::fx::FxHashSet; @@ -31,7 +32,6 @@ use rustc_serialize::{Encodable, Decodable}; use smallvec::SmallVec; use std::borrow::Cow; use std::fmt::{self, Debug, Display, Formatter, Write}; -use std::iter::FusedIterator; use std::ops::{Index, IndexMut}; use std::slice; use std::vec::IntoIter; @@ -70,7 +70,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { /// The various "big phases" that MIR goes through. /// -/// Warning: ordering of variants is significant +/// Warning: ordering of variants is significant. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum MirPhase { Build = 0, @@ -80,16 +80,16 @@ pub enum MirPhase { } impl MirPhase { - /// Gets the index of the current MirPhase within the set of all MirPhases. + /// Gets the index of the current MirPhase within the set of all `MirPhase`s. pub fn phase_index(&self) -> usize { *self as usize } } -/// Lowered representation of a single function. +/// The lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Body<'tcx> { - /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock` + /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock` /// that indexes into this vector. basic_blocks: IndexVec>, @@ -100,7 +100,7 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, - /// List of source scopes; these are referenced by statements + /// A list of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -108,15 +108,10 @@ pub struct Body<'tcx> { /// needn't) be tracked across crates. pub source_scope_local_data: ClearCrossCrate>, - /// Rvalues promoted from this function, such as borrows of constants. - /// Each of them is the Body of a constant with the fn's type parameters - /// in scope, but a separate set of locals. - pub promoted: IndexVec>, - - /// Yields type of the function, if it is a generator. + /// The yield type of the function, if it is a generator. pub yield_ty: Option>, - /// Generator drop glue + /// Generator drop glue. pub generator_drop: Option>>, /// The layout of a generator. Produced by the state transformation. @@ -129,10 +124,10 @@ pub struct Body<'tcx> { /// variables and temporaries. pub local_decls: LocalDecls<'tcx>, - /// User type annotations + /// User type annotations. pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, - /// Number of arguments this function takes. + /// The number of arguments this function takes. /// /// Starting at local 1, `arg_count` locals will be provided by the caller /// and can be assumed to be initialized. @@ -148,10 +143,11 @@ pub struct Body<'tcx> { /// Names and capture modes of all the closure upvars, assuming /// the first argument is either the closure or a reference to it. + // // NOTE(eddyb) This is *strictly* a temporary hack for codegen // debuginfo generation, and will be removed at some point. - // Do **NOT** use it for anything else, upvar information should not be - // in the MIR, please rely on local crate HIR or other side-channels. + // Do **NOT** use it for anything else; upvar information should not be + // in the MIR, so please rely on local crate HIR or other side-channels. pub __upvar_debuginfo_codegen_only_do_not_use: Vec, /// Mark this MIR of a const context other than const functions as having converted a `&&` or @@ -162,10 +158,10 @@ pub struct Body<'tcx> { /// List of places where control flow was destroyed. Used for error reporting. pub control_flow_destroyed: Vec<(Span, String)>, - /// A span representing this MIR, for error reporting + /// A span representing this MIR, for error reporting. pub span: Span, - /// A cache for various calculations + /// A cache for various calculations. cache: cache::Cache, } @@ -174,7 +170,6 @@ impl<'tcx> Body<'tcx> { basic_blocks: IndexVec>, source_scopes: IndexVec, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, yield_ty: Option>, local_decls: LocalDecls<'tcx>, user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, @@ -183,7 +178,7 @@ impl<'tcx> Body<'tcx> { span: Span, control_flow_destroyed: Vec<(Span, String)>, ) -> Self { - // We need `arg_count` locals, and one for the return place + // We need `arg_count` locals, and one for the return place. assert!( local_decls.len() >= arg_count + 1, "expected at least {} locals, got {}", @@ -196,7 +191,6 @@ impl<'tcx> Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop: None, generator_layout: None, @@ -391,12 +385,12 @@ impl<'tcx> Body<'tcx> { true } - /// Returns the return type, it always return first element from `local_decls` array + /// Returns the return type; it always return first element from `local_decls` array. pub fn return_ty(&self) -> Ty<'tcx> { self.local_decls[RETURN_PLACE].ty } - /// Gets the location of the terminator for the given block + /// Gets the location of the terminator for the given block. pub fn terminator_loc(&self, bb: BasicBlock) -> Location { Location { block: bb, statement_index: self[bb].statements.len() } } @@ -418,7 +412,6 @@ impl_stable_hash_for!(struct Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, @@ -471,7 +464,7 @@ impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate< /// Most passes can work with it as a whole, within a single function. #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)] pub struct SourceInfo { - /// Source span for the AST pertaining to this MIR entity. + /// The source span for the AST pertaining to this MIR entity. pub span: Span, /// The source scope, keeping track of which bindings can be @@ -599,13 +592,13 @@ impl Atom for Local { /// Classifies locals into categories. See `Body::local_kind`. #[derive(PartialEq, Eq, Debug, HashStable)] pub enum LocalKind { - /// User-declared variable binding + /// User-declared variable binding. Var, - /// Compiler-introduced temporary + /// Compiler-introduced temporary. Temp, - /// Function argument + /// Function argument. Arg, - /// Location of function's return value + /// Location of function's return value. ReturnPointer, } @@ -627,7 +620,7 @@ pub struct VarBindingForm<'tcx> { /// (b) it gives a way to separate this case from the remaining cases /// for diagnostics. pub opt_match_place: Option<(Option>, Span)>, - /// Span of the pattern in which this variable was bound. + /// The span of the pattern in which this variable was bound. pub pat_span: Span, } @@ -729,12 +722,12 @@ impl_stable_hash_for!(struct BlockTailInfo { tail_result_is_ignored }); /// argument, or the return place. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct LocalDecl<'tcx> { - /// `let mut x` vs `let x`. + /// Whether this is a mutable minding (i.e., `let x` or `let mut x`). /// /// Temporaries and the return place are always mutable. pub mutability: Mutability, - /// Some(binding_mode) if this corresponds to a user-declared local variable. + /// `Some(binding_mode)` if this corresponds to a user-declared local variable. /// /// This is solely used for local diagnostics when generating /// warnings/errors when compiling the current crate, and @@ -768,7 +761,7 @@ pub struct LocalDecl<'tcx> { /// intervening statement context). pub is_block_tail: Option, - /// Type of this local. + /// The type of this local. pub ty: Ty<'tcx>, /// If the user manually ascribed a type to this variable, @@ -777,7 +770,7 @@ pub struct LocalDecl<'tcx> { /// region inference. pub user_ty: UserTypeProjections, - /// Name of the local, used in debuginfo and pretty-printing. + /// The name of the local, used in debuginfo and pretty-printing. /// /// Note that function arguments can also have this set to `Some(_)` /// to generate better debuginfo. @@ -845,8 +838,8 @@ pub struct LocalDecl<'tcx> { /// ROOT SCOPE /// │{ argument x: &str } /// │ - /// │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes - /// │ │ // in practice because I'm lazy. + /// │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes + /// │ │ // in practice because I'm lazy. /// │ │ /// │ │← x.source_info.scope /// │ │← `x.parse().unwrap()` @@ -860,7 +853,7 @@ pub struct LocalDecl<'tcx> { /// │ /// │ │{ let x: u32 } /// │ │← x.visibility_scope - /// │ │← `drop(x)` // this accesses `x: u32` + /// │ │← `drop(x)` // This accesses `x: u32`. /// ``` pub source_info: SourceInfo, @@ -1046,16 +1039,16 @@ pub struct Terminator<'tcx> { #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum TerminatorKind<'tcx> { - /// block should have one successor in the graph; we jump there + /// Block should have one successor in the graph; we jump there. Goto { target: BasicBlock }, - /// operand evaluates to an integer; jump depending on its value - /// to one of the targets, and otherwise fallback to `otherwise` + /// Operand evaluates to an integer; jump depending on its value + /// to one of the targets, and otherwise fallback to `otherwise`. SwitchInt { - /// discriminant value being tested + /// The discriminant value being tested. discr: Operand<'tcx>, - /// type of value being tested + /// The type of value being tested. switch_ty: Ty<'tcx>, /// Possible values. The locations to branch to in each case @@ -1065,6 +1058,7 @@ pub enum TerminatorKind<'tcx> { /// Possible branch sites. The last element of this vector is used /// for the otherwise branch, so targets.len() == values.len() + 1 /// should hold. + // // This invariant is quite non-obvious and also could be improved. // One way to make this invariant is to have something like this instead: // @@ -1077,7 +1071,7 @@ pub enum TerminatorKind<'tcx> { }, /// Indicates that the landing pad is finished and unwinding should - /// continue. Emitted by build::scope::diverge_cleanup. + /// continue. Emitted by `build::scope::diverge_cleanup`. Resume, /// Indicates that the landing pad is finished and that the process @@ -1091,10 +1085,10 @@ pub enum TerminatorKind<'tcx> { /// Indicates a terminator that can never be reached. Unreachable, - /// Drop the Place + /// Drop the `Place`. Drop { location: Place<'tcx>, target: BasicBlock, unwind: Option }, - /// Drop the Place and assign the new value over it. This ensures + /// Drop the `Place` and assign the new value over it. This ensures /// that the assignment to `P` occurs *even if* the destructor for /// place unwinds. Its semantics are best explained by the /// elaboration: @@ -1127,9 +1121,9 @@ pub enum TerminatorKind<'tcx> { unwind: Option, }, - /// Block ends with a call of a converging function + /// Block ends with a call of a converging function. Call { - /// The function that’s being called + /// The function that’s being called. func: Operand<'tcx>, /// Arguments the function is called with. /// These are owned by the callee, which is free to modify them. @@ -1140,7 +1134,7 @@ pub enum TerminatorKind<'tcx> { destination: Option<(Place<'tcx>, BasicBlock)>, /// Cleanups to be done if the call unwinds. cleanup: Option, - /// Whether this is from a call in HIR, rather than from an overloaded + /// `true` if this is from a call in HIR rather than from an overloaded /// operator. True for overloaded function call. from_hir_call: bool, }, @@ -1155,40 +1149,40 @@ pub enum TerminatorKind<'tcx> { cleanup: Option, }, - /// A suspend point + /// A suspend point. Yield { - /// The value to return + /// The value to return. value: Operand<'tcx>, - /// Where to resume to + /// Where to resume to. resume: BasicBlock, - /// Cleanup to be done if the generator is dropped at this suspend point + /// Cleanup to be done if the generator is dropped at this suspend point. drop: Option, }, - /// Indicates the end of the dropping of a generator + /// Indicates the end of the dropping of a generator. GeneratorDrop, /// A block where control flow only ever takes one real path, but borrowck /// needs to be more conservative. FalseEdges { - /// The target normal control flow will take + /// The target normal control flow will take. real_target: BasicBlock, /// A block control flow could conceptually jump to, but won't in - /// practice + /// practice. imaginary_target: BasicBlock, }, /// A terminator for blocks that only take one path in reality, but where we /// reserve the right to unwind in borrowck, even if it won't happen in practice. /// This can arise in infinite loops with no function calls for example. FalseUnwind { - /// The target normal control flow will take + /// The target normal control flow will take. real_target: BasicBlock, /// The imaginary cleanup block link. This particular path will never be taken /// in practice, but in order to avoid fragility we want to always /// consider it in borrowck. We don't want to accept programs which - /// pass borrowck only when panic=abort or some assertions are disabled - /// due to release vs. debug mode builds. This needs to be an Option because - /// of the remove_noop_landing_pads and no_landing_pads passes + /// pass borrowck only when `panic=abort` or some assertions are disabled + /// due to release vs. debug mode builds. This needs to be an `Option` because + /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. unwind: Option, }, } @@ -1453,7 +1447,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } impl<'tcx> TerminatorKind<'tcx> { - /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the + /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the /// successor basic block, if any. The only information not included is the list of possible /// successors, which may be rendered differently between the text and the graphviz format. pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { @@ -1553,9 +1547,9 @@ pub struct Statement<'tcx> { // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(Statement<'_>, 56); +static_assert_size!(Statement<'_>, 32); -impl<'tcx> Statement<'tcx> { +impl Statement<'_> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. pub fn make_nop(&mut self) { @@ -1574,7 +1568,7 @@ impl<'tcx> Statement<'tcx> { #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub enum StatementKind<'tcx> { /// Write the RHS Rvalue to the LHS Place. - Assign(Place<'tcx>, Box>), + Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), /// This represents all the reading that a pattern match may do /// (e.g., inspecting constants and discriminant values), and the @@ -1583,10 +1577,10 @@ pub enum StatementKind<'tcx> { /// /// Note that this also is emitted for regular `let` bindings to ensure that locals that are /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` - FakeRead(FakeReadCause, Place<'tcx>), + FakeRead(FakeReadCause, Box>), /// Write the discriminant for a variant to the enum Place. - SetDiscriminant { place: Place<'tcx>, variant_index: VariantIdx }, + SetDiscriminant { place: Box>, variant_index: VariantIdx }, /// Start a live range for the storage of the local. StorageLive(Local), @@ -1603,7 +1597,7 @@ pub enum StatementKind<'tcx> { /// by miri and only generated when "-Z mir-emit-retag" is passed. /// See /// for more details. - Retag(RetagKind, Place<'tcx>), + Retag(RetagKind, Box>), /// Encodes a user's type ascription. These need to be preserved /// intact so that NLL can respect them. For example: @@ -1617,26 +1611,26 @@ pub enum StatementKind<'tcx> { /// - `Contravariant` -- requires that `T_y :> T` /// - `Invariant` -- requires that `T_y == T` /// - `Bivariant` -- no effect - AscribeUserType(Place<'tcx>, ty::Variance, Box), + AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } -/// `RetagKind` describes what kind of retag is to be performed. +/// Describes what kind of retag is to be performed. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)] pub enum RetagKind { - /// The initial retag when entering a function + /// The initial retag when entering a function. FnEntry, - /// Retag preparing for a two-phase borrow + /// Retag preparing for a two-phase borrow. TwoPhase, - /// Retagging raw pointers + /// Retagging raw pointers. Raw, - /// A "normal" retag + /// A "normal" retag. Default, } -/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists. +/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum FakeReadCause { /// Inject a fake read of the borrowed input at the end of each guards @@ -1677,11 +1671,11 @@ pub struct InlineAsm<'tcx> { pub inputs: Box<[(Span, Operand<'tcx>)]>, } -impl<'tcx> Debug for Statement<'tcx> { +impl Debug for Statement<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use self::StatementKind::*; match self.kind { - Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv), + Assign(box(ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv), FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place), Retag(ref kind, ref place) => write!( fmt, @@ -1702,7 +1696,7 @@ impl<'tcx> Debug for Statement<'tcx> { InlineAsm(ref asm) => { write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs) } - AscribeUserType(ref place, ref variance, ref c_ty) => { + AscribeUserType(box(ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) } Nop => write!(fmt, "nop"), @@ -1722,7 +1716,7 @@ pub struct Place<'tcx> { pub base: PlaceBase<'tcx>, /// projection out of a place (access a field, deref a pointer, etc) - pub projection: Option>>, + pub projection: Box<[PlaceElem<'tcx>]>, } #[derive( @@ -1737,34 +1731,34 @@ pub enum PlaceBase<'tcx> { } /// We store the normalized type to avoid requiring normalization when reading MIR -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub ty: Ty<'tcx>, - pub kind: StaticKind, + pub kind: StaticKind<'tcx>, + /// The `DefId` of the item this static was declared in. For promoted values, usually, this is + /// the same as the `DefId` of the `mir::Body` containing the `Place` this promoted appears in. + /// However, after inlining, that might no longer be the case as inlined `Place`s are copied + /// into the calling frame. + pub def_id: DefId, } #[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] -pub enum StaticKind { - Promoted(Promoted), - Static(DefId), +pub enum StaticKind<'tcx> { + /// Promoted references consist of an id (`Promoted`) and the substs necessary to monomorphize + /// it. Usually, these substs are just the identity substs for the item. However, the inliner + /// will adjust these substs when it inlines a function based on the substs at the callsite. + Promoted(Promoted, SubstsRef<'tcx>), + Static, } impl_stable_hash_for!(struct Static<'tcx> { ty, - kind + kind, + def_id }); -/// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`. -#[derive( - Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, -)] -pub struct Projection<'tcx> { - pub base: Option>>, - pub elem: PlaceElem<'tcx>, -} - #[derive( Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, )] @@ -1807,6 +1801,23 @@ pub enum ProjectionElem { Downcast(Option, VariantIdx), } +impl ProjectionElem { + /// Returns `true` if the target of this projection may refer to a different region of memory + /// than the base. + fn is_indirect(&self) -> bool { + match self { + Self::Deref => true, + + | Self::Field(_, _) + | Self::Index(_) + | Self::ConstantIndex { .. } + | Self::Subslice { .. } + | Self::Downcast(_, _) + => false + } + } +} + /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; @@ -1829,14 +1840,22 @@ newtype_index! { #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PlaceRef<'a, 'tcx> { pub base: &'a PlaceBase<'tcx>, - pub projection: &'a Option>>, + pub projection: &'a [PlaceElem<'tcx>], } impl<'tcx> Place<'tcx> { - pub const RETURN_PLACE: Place<'tcx> = Place { - base: PlaceBase::Local(RETURN_PLACE), - projection: None, - }; + // FIXME change this back to a const when projection is a shared slice. + // + // pub const RETURN_PLACE: Place<'tcx> = Place { + // base: PlaceBase::Local(RETURN_PLACE), + // projection: &[], + // }; + pub fn return_place() -> Place<'tcx> { + Place { + base: PlaceBase::Local(RETURN_PLACE), + projection: Box::new([]), + } + } pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { self.elem(ProjectionElem::Field(f, ty)) @@ -1862,12 +1881,24 @@ impl<'tcx> Place<'tcx> { } pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> { + // FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore + let mut projection = self.projection.into_vec(); + projection.push(elem); + Place { base: self.base, - projection: Some(Box::new(Projection { base: self.projection, elem })), + projection: projection.into_boxed_slice(), } } + /// Returns `true` if this `Place` contains a `Deref` projection. + /// + /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the + /// same region of memory as its base. + pub fn is_indirect(&self) -> bool { + self.projection.iter().any(|elem| elem.is_indirect()) + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // @@ -1876,59 +1907,23 @@ impl<'tcx> Place<'tcx> { match self { Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } | Place { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: box [ProjectionElem::Deref], } => Some(*local), _ => None, } } - /// Recursively "iterates" over place components, generating a `PlaceBase` and - /// `Projections` list and invoking `op` with a `ProjectionsIter`. - pub fn iterate( - &self, - op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R, - ) -> R { - Place::iterate_over(&self.base, &self.projection, op) - } - - pub fn iterate_over( - place_base: &PlaceBase<'tcx>, - place_projection: &Option>>, - op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R, - ) -> R { - fn iterate_over2<'tcx, R>( - place_base: &PlaceBase<'tcx>, - place_projection: &Option>>, - next: &Projections<'_, 'tcx>, - op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R, - ) -> R { - match place_projection { - None => { - op(place_base, next.iter()) - } - - Some(interior) => { - iterate_over2( - place_base, - &interior.base, - &Projections::List { - projection: interior, - next, - }, - op, - ) - } - } + /// If this place represents a local variable like `_X` with no + /// projections, return `Some(_X)`. + pub fn as_local(&self) -> Option { + match self { + Place { projection: box [], base: PlaceBase::Local(l) } => Some(*l), + _ => None, } - - iterate_over2(place_base, place_projection, &Projections::Empty, op) } pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> { @@ -1943,7 +1938,7 @@ impl From for Place<'_> { fn from(local: Local) -> Self { Place { base: local.into(), - projection: None, + projection: Box::new([]), } } } @@ -1955,13 +1950,6 @@ impl From for PlaceBase<'_> { } impl<'a, 'tcx> PlaceRef<'a, 'tcx> { - pub fn iterate( - &self, - op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R, - ) -> R { - Place::iterate_over(self.base, self.projection, op) - } - /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // @@ -1970,143 +1958,71 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> { match self { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } | PlaceRef { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: [ProjectionElem::Deref], } => Some(*local), _ => None, } } } -/// A linked list of projections running up the stack; begins with the -/// innermost projection and extends to the outermost (e.g., `a.b.c` -/// would have the place `b` with a "next" pointer to `b.c`). -/// Created by `Place::iterate`. -/// -/// N.B., this particular impl strategy is not the most obvious. It was -/// chosen because it makes a measurable difference to NLL -/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot. -pub enum Projections<'p, 'tcx> { - Empty, - - List { projection: &'p Projection<'tcx>, next: &'p Projections<'p, 'tcx> }, -} - -impl<'p, 'tcx> Projections<'p, 'tcx> { - fn iter(&self) -> ProjectionsIter<'_, 'tcx> { - ProjectionsIter { value: self } - } -} - -impl<'p, 'tcx> IntoIterator for &'p Projections<'p, 'tcx> { - type Item = &'p Projection<'tcx>; - type IntoIter = ProjectionsIter<'p, 'tcx>; - - /// Converts a list of `Projection` components into an iterator; - /// this iterator yields up a never-ending stream of `Option<&Place>`. - /// These begin with the "innermost" projection and then with each - /// projection therefrom. So given a place like `a.b.c` it would - /// yield up: - /// - /// ```notrust - /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ... - /// ``` - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -/// Iterator over components; see `Projections::iter` for more -/// information. -/// -/// N.B., this is not a *true* Rust iterator -- the code above just -/// manually invokes `next`. This is because we (sometimes) want to -/// keep executing even after `None` has been returned. -pub struct ProjectionsIter<'p, 'tcx> { - pub value: &'p Projections<'p, 'tcx>, -} - -impl<'p, 'tcx> Iterator for ProjectionsIter<'p, 'tcx> { - type Item = &'p Projection<'tcx>; - - fn next(&mut self) -> Option { - if let &Projections::List { projection, next } = self.value { - self.value = next; - Some(projection) - } else { - None - } - } -} - -impl<'p, 'tcx> FusedIterator for ProjectionsIter<'p, 'tcx> {} - -impl<'tcx> Debug for Place<'tcx> { +impl Debug for Place<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - self.iterate(|_place_base, place_projections| { - // FIXME: remove this collect once we have migrated to slices - let projs_vec: Vec<_> = place_projections.collect(); - for projection in projs_vec.iter().rev() { - match projection.elem { - ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { - write!(fmt, "(").unwrap(); - } - ProjectionElem::Deref => { - write!(fmt, "(*").unwrap(); - } - ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } => {} + for elem in self.projection.iter().rev() { + match elem { + ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { + write!(fmt, "(").unwrap(); + } + ProjectionElem::Deref => { + write!(fmt, "(*").unwrap(); } + ProjectionElem::Index(_) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } => {} } - }); + } - self.iterate(|place_base, place_projections| { - write!(fmt, "{:?}", place_base)?; + write!(fmt, "{:?}", self.base)?; - for projection in place_projections { - match projection.elem { - ProjectionElem::Downcast(Some(name), _index) => { - write!(fmt, " as {})", name)?; - } - ProjectionElem::Downcast(None, index) => { - write!(fmt, " as variant#{:?})", index)?; - } - ProjectionElem::Deref => { - write!(fmt, ")")?; - } - ProjectionElem::Field(field, ty) => { - write!(fmt, ".{:?}: {:?})", field.index(), ty)?; - } - ProjectionElem::Index(ref index) => { - write!(fmt, "[{:?}]", index)?; - } - ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => { - write!(fmt, "[{:?} of {:?}]", offset, min_length)?; - } - ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => { - write!(fmt, "[-{:?} of {:?}]", offset, min_length)?; - } - ProjectionElem::Subslice { from, to } if to == 0 => { - write!(fmt, "[{:?}:]", from)?; - } - ProjectionElem::Subslice { from, to } if from == 0 => { - write!(fmt, "[:-{:?}]", to)?; - } - ProjectionElem::Subslice { from, to } => { - write!(fmt, "[{:?}:-{:?}]", from, to)?; - } + for elem in self.projection.iter() { + match elem { + ProjectionElem::Downcast(Some(name), _index) => { + write!(fmt, " as {})", name)?; + } + ProjectionElem::Downcast(None, index) => { + write!(fmt, " as variant#{:?})", index)?; + } + ProjectionElem::Deref => { + write!(fmt, ")")?; + } + ProjectionElem::Field(field, ty) => { + write!(fmt, ".{:?}: {:?})", field.index(), ty)?; + } + ProjectionElem::Index(ref index) => { + write!(fmt, "[{:?}]", index)?; + } + ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => { + write!(fmt, "[{:?} of {:?}]", offset, min_length)?; + } + ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => { + write!(fmt, "[-{:?} of {:?}]", offset, min_length)?; + } + ProjectionElem::Subslice { from, to } if *to == 0 => { + write!(fmt, "[{:?}:]", from)?; + } + ProjectionElem::Subslice { from, to } if *from == 0 => { + write!(fmt, "[:-{:?}]", to)?; + } + ProjectionElem::Subslice { from, to } => { + write!(fmt, "[{:?}:-{:?}]", from, to)?; } } + } - Ok(()) - }) + Ok(()) } } @@ -2114,10 +2030,12 @@ impl Debug for PlaceBase<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { PlaceBase::Local(id) => write!(fmt, "{:?}", id), - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => { + PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static, def_id }) => { write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty) } - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Promoted(promoted) }) => { + PlaceBase::Static(box self::Static { + ty, kind: StaticKind::Promoted(promoted, _), def_id: _ + }) => { write!(fmt, "({:?}: {:?})", promoted, ty) } } @@ -2143,7 +2061,7 @@ pub struct SourceScopeData { #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct SourceScopeLocalData { - /// A HirId with lint levels equivalent to this scope's lint levels. + /// An `HirId` with lint levels equivalent to this scope's lint levels. pub lint_root: hir::HirId, /// The unsafe block that contains this node. pub safety: Safety, @@ -2197,7 +2115,6 @@ impl<'tcx> Operand<'tcx> { let ty = tcx.type_of(def_id).subst(tcx, substs); Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }) @@ -2476,7 +2393,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, - pub ty: Ty<'tcx>, /// Optional user-given type: for something like /// `collect::>`, this would be present and would @@ -2734,11 +2650,12 @@ impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] pub struct Location { - /// the location is within this block + /// The block that the location is within. pub block: BasicBlock, - /// the location is the start of the statement; or, if `statement_index` - /// == num-statements, then the start of the terminator. + /// The location is the position of the start of the statement; or, if + /// `statement_index` equals the number of statements, then the start of the + /// terminator. pub statement_index: usize, } @@ -2801,7 +2718,7 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { General, - /// Permitted in const fn and regular fns. + /// Permitted both in `const fn`s and regular `fn`s. GeneralAndConstFn, ExternStatic(hir::HirId), BorrowPacked(hir::HirId), @@ -2817,9 +2734,9 @@ pub struct UnsafetyViolation { #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyCheckResult { - /// Violations that are propagated *upwards* from this function + /// Violations that are propagated *upwards* from this function. pub violations: Lrc<[UnsafetyViolation]>, - /// unsafe blocks in this function, along with whether they are used. This is + /// `unsafe` blocks in this function, along with whether they are used. This is /// used for the "unused_unsafe" lint. pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, } @@ -2831,7 +2748,7 @@ newtype_index! { } } -/// The layout of generator state +/// The layout of generator state. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. @@ -2846,11 +2763,14 @@ pub struct GeneratorLayout<'tcx> { /// layout. pub storage_conflicts: BitMatrix, - /// Names and scopes of all the stored generator locals. - /// NOTE(tmandry) This is *strictly* a temporary hack for codegen + /// The names and scopes of all the stored generator locals. + /// + /// N.B., this is *strictly* a temporary hack for codegen /// debuginfo generation, and will be removed at some point. /// Do **NOT** use it for anything else, local information should not be /// in the MIR, please rely on local crate HIR or other side-channels. + // + // FIXME(tmandry): see above. pub __local_debuginfo_codegen_only_do_not_use: IndexVec>, } @@ -2908,7 +2828,7 @@ pub struct BorrowCheckResult<'tcx> { /// instances assigned one of these same indices. Those regions will /// be substituted away by the creator. We use `ReClosureBound` in /// that case because the regions must be allocated in the global -/// TyCtxt, and hence we cannot use `ReVar` (which is what we use +/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use /// internally within the rest of the NLL code). #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureRegionRequirements<'tcx> { @@ -2924,8 +2844,8 @@ pub struct ClosureRegionRequirements<'tcx> { pub outlives_requirements: Vec>, } -/// Indicates an outlives constraint between a type or between two -/// free-regions declared on the closure. +/// Indicates an outlives-constraint between a type or between two +/// free regions declared on the closure. #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureOutlivesRequirement<'tcx> { // This region or type ... @@ -2941,11 +2861,11 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub category: ConstraintCategory, } -/// Outlives constraints can be categorized to determine whether and why they +/// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. /// -/// See also [rustc_mir::borrow_check::nll::constraints] +/// See also [rustc_mir::borrow_check::nll::constraints]. #[derive( Copy, Clone, @@ -2993,7 +2913,7 @@ pub enum ConstraintCategory { Internal, } -/// The subject of a ClosureOutlivesRequirement -- that is, the thing +/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing /// that must outlive some region. #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub enum ClosureOutlivesSubject<'tcx> { @@ -3011,7 +2931,7 @@ pub enum ClosureOutlivesSubject<'tcx> { } /* - * TypeFoldable implementations for MIR types + * `TypeFoldable` implementations for MIR types */ CloneTypeFoldableAndLiftImpls! { @@ -3034,7 +2954,6 @@ BraceStructTypeFoldableImpl! { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, @@ -3088,14 +3007,14 @@ BraceStructTypeFoldableImpl! { EnumTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> { - (StatementKind::Assign)(a, b), + (StatementKind::Assign)(a), (StatementKind::FakeRead)(cause, place), (StatementKind::SetDiscriminant) { place, variant_index }, (StatementKind::StorageLive)(a), (StatementKind::StorageDead)(a), (StatementKind::InlineAsm)(a), (StatementKind::Retag)(kind, place), - (StatementKind::AscribeUserType)(a, v, b), + (StatementKind::AscribeUserType)(a, v), (StatementKind::Nop), } } @@ -3228,13 +3147,63 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Place { - base: self.base.clone(), + base: self.base.fold_with(folder), projection: self.projection.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.projection.visit_with(visitor) + self.base.visit_with(visitor) || self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)), + PlaceBase::Static(static_) => PlaceBase::Static(static_.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + PlaceBase::Local(local) => local.visit_with(visitor), + PlaceBase::Static(static_) => (**static_).visit_with(visitor), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Static { + ty: self.ty.fold_with(folder), + kind: self.kind.fold_with(folder), + def_id: self.def_id, + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + let Static { ty, kind, def_id: _ } = self; + + ty.visit_with(visitor) || kind.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for StaticKind<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + StaticKind::Promoted(promoted, substs) => + StaticKind::Promoted(promoted.fold_with(folder), substs.fold_with(folder)), + StaticKind::Static => StaticKind::Static + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + StaticKind::Promoted(promoted, substs) => + promoted.visit_with(visitor) || substs.visit_with(visitor), + StaticKind::Static => { false } + } } } @@ -3327,30 +3296,26 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for Projection<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { use crate::mir::ProjectionElem::*; - let base = self.base.fold_with(folder); - let elem = match self.elem { + match self { Deref => Deref, - Field(f, ref ty) => Field(f, ty.fold_with(folder)), - Index(ref v) => Index(v.fold_with(folder)), - ref elem => elem.clone(), - }; - - Projection { base, elem } + Field(f, ty) => Field(*f, ty.fold_with(folder)), + Index(v) => Index(v.fold_with(folder)), + elem => elem.clone(), + } } fn super_visit_with>(&self, visitor: &mut Vs) -> bool { use crate::mir::ProjectionElem::*; - self.base.visit_with(visitor) - || match self.elem { - Field(_, ref ty) => ty.visit_with(visitor), - Index(ref v) => v.visit_with(visitor), - _ => false, - } + match self { + Field(_, ty) => ty.visit_with(visitor), + Index(v) => v.visit_with(visitor), + _ => false, + } } } @@ -3385,12 +3350,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Constant { span: self.span.clone(), - ty: self.ty.fold_with(folder), user_ty: self.user_ty.fold_with(folder), literal: self.literal.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.literal.visit_with(visitor) + self.literal.visit_with(visitor) } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index f8889380b2..d776809839 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -121,21 +121,16 @@ BraceStructTypeFoldableImpl! { impl<'tcx> Place<'tcx> { pub fn ty_from( base: &PlaceBase<'tcx>, - projection: &Option>>, + projection: &[PlaceElem<'tcx>], local_decls: &D, tcx: TyCtxt<'tcx> ) -> PlaceTy<'tcx> where D: HasLocalDecls<'tcx> { - Place::iterate_over(base, projection, |place_base, place_projections| { - let mut place_ty = place_base.ty(local_decls); - - for proj in place_projections { - place_ty = place_ty.projection_ty(tcx, &proj.elem); - } - - place_ty - }) + projection.iter().fold( + base.ty(local_decls), + |place_ty, elem| place_ty.projection_ty(tcx, elem) + ) } pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx> @@ -252,7 +247,7 @@ impl<'tcx> Operand<'tcx> { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - &Operand::Constant(ref c) => c.ty, + &Operand::Constant(ref c) => c.literal.ty, } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ee4ecb6762..1e3b9eb29c 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -152,18 +152,18 @@ macro_rules! make_mir_visitor { } fn visit_place_base(&mut self, - place_base: & $($mutability)? PlaceBase<'tcx>, + base: & $($mutability)? PlaceBase<'tcx>, context: PlaceContext, location: Location) { - self.super_place_base(place_base, context, location); + self.super_place_base(base, context, location); } fn visit_projection(&mut self, - place_base: & $($mutability)? PlaceBase<'tcx>, - place: & $($mutability)? Projection<'tcx>, + base: & $($mutability)? PlaceBase<'tcx>, + projection: & $($mutability)? [PlaceElem<'tcx>], context: PlaceContext, location: Location) { - self.super_projection(place_base, place, context, location); + self.super_projection(base, projection, context, location); } fn visit_constant(&mut self, @@ -344,7 +344,9 @@ macro_rules! make_mir_visitor { self.visit_source_info(source_info); match kind { - StatementKind::Assign(place, rvalue) => { + StatementKind::Assign( + box(ref $($mutability)? place, ref $($mutability)? rvalue) + ) => { self.visit_assign(place, rvalue, location); } StatementKind::FakeRead(_, place) => { @@ -391,7 +393,10 @@ macro_rules! make_mir_visitor { StatementKind::Retag(kind, place) => { self.visit_retag(kind, place, location); } - StatementKind::AscribeUserType(place, variance, user_ty) => { + StatementKind::AscribeUserType( + box(ref $($mutability)? place, ref $($mutability)? user_ty), + variance + ) => { self.visit_ascribe_user_ty(place, variance, user_ty, location); } StatementKind::Nop => {} @@ -685,7 +690,7 @@ macro_rules! make_mir_visitor { location: Location) { let mut context = context; - if place.projection.is_some() { + if !place.projection.is_empty() { context = if context.is_mutating_use() { PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { @@ -695,9 +700,10 @@ macro_rules! make_mir_visitor { self.visit_place_base(& $($mutability)? place.base, context, location); - if let Some(box proj) = & $($mutability)? place.projection { - self.visit_projection(& $($mutability)? place.base, proj, context, location); - } + self.visit_projection(& $($mutability)? place.base, + & $($mutability)? place.projection, + context, + location); } fn super_place_base(&mut self, @@ -708,41 +714,38 @@ macro_rules! make_mir_visitor { PlaceBase::Local(local) => { self.visit_local(local, context, location); } - PlaceBase::Static(box Static { kind: _, ty }) => { + PlaceBase::Static(box Static { kind: _, ty, def_id: _ }) => { self.visit_ty(& $($mutability)? *ty, TyContext::Location(location)); } } } fn super_projection(&mut self, - place_base: & $($mutability)? PlaceBase<'tcx>, - proj: & $($mutability)? Projection<'tcx>, + base: & $($mutability)? PlaceBase<'tcx>, + projection: & $($mutability)? [PlaceElem<'tcx>], context: PlaceContext, location: Location) { - if let Some(box proj_base) = & $($mutability)? proj.base { - self.visit_projection(place_base, proj_base, context, location); - } + if let [proj_base @ .., elem] = projection { + self.visit_projection(base, proj_base, context, location); - match & $($mutability)? proj.elem { - ProjectionElem::Deref => { - } - ProjectionElem::Subslice { from: _, to: _ } => { - } - ProjectionElem::Field(_field, ty) => { - self.visit_ty(ty, TyContext::Location(location)); - } - ProjectionElem::Index(local) => { - self.visit_local( - local, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), - location - ); - } - ProjectionElem::ConstantIndex { offset: _, - min_length: _, - from_end: _ } => { - } - ProjectionElem::Downcast(_name, _variant_index) => { + match elem { + ProjectionElem::Field(_field, ty) => { + self.visit_ty(ty, TyContext::Location(location)); + } + ProjectionElem::Index(local) => { + self.visit_local( + local, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); + } + ProjectionElem::Deref | + ProjectionElem::Subslice { from: _, to: _ } | + ProjectionElem::ConstantIndex { offset: _, + min_length: _, + from_end: _ } | + ProjectionElem::Downcast(_, _) => { + } } } } @@ -782,13 +785,11 @@ macro_rules! make_mir_visitor { location: Location) { let Constant { span, - ty, user_ty, literal, } = constant; self.visit_span(span); - self.visit_ty(ty, TyContext::Location(location)); drop(user_ty); // no visit method for this self.visit_const(literal, location); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5ab1b90642..252e49d5d1 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -17,7 +17,6 @@ use crate::traits::query::{ use std::borrow::Cow; use syntax_pos::symbol::InternedString; - // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way @@ -110,7 +109,11 @@ rustc_queries! { no_hash } - query mir_validated(_: DefId) -> &'tcx Steal> { + query mir_validated(_: DefId) -> + ( + &'tcx Steal>, + &'tcx Steal>> + ) { no_hash } @@ -125,7 +128,17 @@ rustc_queries! { } } - query promoted_mir(key: DefId) -> &'tcx IndexVec> { } + query promoted_mir(key: DefId) -> &'tcx IndexVec> { + cache_on_disk_if { key.is_local() } + load_cached(tcx, id) { + let promoted: Option< + rustc_data_structures::indexed_vec::IndexVec< + crate::mir::Promoted, + crate::mir::Body<'tcx> + >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); + promoted.map(|p| &*tcx.arena.alloc(p)) + } + } } TypeChecking { @@ -231,6 +244,10 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } + query asyncness(key: DefId) -> hir::IsAsync { + desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + } + /// Returns `true` if calls to the function may be promoted. /// /// This is either because the function is e.g., a tuple-struct or tuple-variant @@ -449,15 +466,6 @@ rustc_queries! { no_force desc { "extract field of const" } } - - /// Produces an absolute path representation of the given type. See also the documentation - /// on `std::any::type_name`. - query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - eval_always - no_force - desc { "get absolute path of type" } - } - } TypeChecking { @@ -790,7 +798,7 @@ rustc_queries! { } BorrowChecking { - // Lifetime resolution. See `middle::resolve_lifetimes`. + /// Lifetime resolution. See `middle::resolve_lifetimes`. query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes { desc { "resolving lifetimes" } } @@ -832,13 +840,30 @@ rustc_queries! { -> &'tcx [(Symbol, Option)] { desc { "calculating the lib features defined in a crate" } } + /// Returns the lang items defined in another crate by loading it from metadata. + // FIXME: It is illegal to pass a `CrateNum` other than `LOCAL_CRATE` here, just get rid + // of that argument? query get_lang_items(_: CrateNum) -> &'tcx LanguageItems { eval_always desc { "calculating the lang items map" } } + + /// Returns all diagnostic items defined in all crates. + query all_diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { + eval_always + desc { "calculating the diagnostic items map" } + } + + /// Returns the lang items defined in another crate by loading it from metadata. query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] { desc { "calculating the lang items defined in a crate" } } + + /// Returns the diagnostic items defined in a crate. + query diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { + desc { "calculating the diagnostic items map in a crate" } + } + query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { desc { "calculating the missing lang items in a crate" } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3536b2aa8f..5eda3df378 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1,36 +1,38 @@ //! Contains infrastructure for configuring the compiler, including parsing -//! command line options. - -use std::str::FromStr; +//! command-line options. +use crate::lint; +use crate::middle::cstore; use crate::session::{early_error, early_warn, Session}; use crate::session::search_paths::SearchPath; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; + use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; use rustc_target::spec::{Target, TargetTriple}; -use crate::lint; -use crate::middle::cstore; use syntax; use syntax::ast::{self, IntTy, UintTy, MetaItemKind}; use syntax::source_map::{FileName, FilePathMapping}; use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION}; +use syntax::parse::{ParseSess, new_parser_from_source_str}; use syntax::parse::token; -use syntax::parse; use syntax::symbol::{sym, Symbol}; use syntax::feature_gate::UnstableFeatures; -use errors::emitter::HumanReadableErrorType; +use syntax::source_map::SourceMap; +use errors::emitter::HumanReadableErrorType; use errors::{ColorConfig, FatalError, Handler}; use getopts; -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::btree_map::Iter as BTreeMapIter; -use std::collections::btree_map::Keys as BTreeMapKeysIter; -use std::collections::btree_map::Values as BTreeMapValuesIter; -use rustc_data_structures::fx::FxHashSet; -use std::{fmt, str}; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::btree_map::{ + Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, +}; +use std::fmt; +use std::str::{self, FromStr}; use std::hash::Hasher; use std::collections::hash_map::DefaultHasher; use std::iter::FromIterator; @@ -241,14 +243,14 @@ pub enum ErrorOutputType { } impl Default for ErrorOutputType { - fn default() -> ErrorOutputType { - ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) + fn default() -> Self { + Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) } } -// Use tree-based collections to cheaply get a deterministic Hash implementation. -// DO NOT switch BTreeMap out for an unsorted container type! That would break -// dependency tracking for command-line arguments. +/// Use tree-based collections to cheaply get a deterministic `Hash` implementation. +/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break +/// dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct OutputTypes(BTreeMap>); @@ -281,7 +283,7 @@ impl OutputTypes { self.0.len() } - // True if any of the output types require codegen or linking. + // Returns `true` if any of the output types require codegen or linking. pub fn should_codegen(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -295,9 +297,9 @@ impl OutputTypes { } } -// Use tree-based collections to cheaply get a deterministic Hash implementation. -// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That -// would break dependency tracking for command-line arguments. +/// Use tree-based collections to cheaply get a deterministic `Hash` implementation. +/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That +/// would break dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct Externs(BTreeMap); @@ -327,7 +329,7 @@ macro_rules! hash_option { ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({ if $sub_hashes.insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() { - bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) + bug!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) } }); } @@ -362,7 +364,7 @@ macro_rules! top_level_options { ); } -// The top-level command-line options struct +// The top-level command-line options struct. // // For each option, one has to specify how it behaves with regard to the // dependency tracking system of incremental compilation. This is done via the @@ -376,16 +378,16 @@ macro_rules! top_level_options { // Incremental compilation is not influenced by this option. // // If you add a new option to this struct or one of the sub-structs like -// CodegenOptions, think about how it influences incremental compilation. If in +// `CodegenOptions`, think about how it influences incremental compilation. If in // doubt, specify [TRACKED], which is always "correct" but might lead to // unnecessary re-compilation. top_level_options!( pub struct Options { // The crate config requested for the session, which may be combined - // with additional crate configurations during the compile process + // with additional crate configurations during the compile process. crate_types: Vec [TRACKED], optimize: OptLevel [TRACKED], - // Include the debug_assertions flag into dependency tracking, since it + // Include the `debug_assertions` flag in dependency tracking, since it // can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], @@ -395,15 +397,15 @@ top_level_options!( output_types: OutputTypes [TRACKED], search_paths: Vec [UNTRACKED], libs: Vec<(String, Option, Option)> [TRACKED], - maybe_sysroot: Option [TRACKED], + maybe_sysroot: Option [UNTRACKED], target_triple: TargetTriple [TRACKED], test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - // if Some, enable incremental compilation, using the given - // directory to store intermediate results + // If `Some`, enable incremental compilation, using the given + // directory to store intermediate results. incremental: Option [UNTRACKED], debugging_opts: DebuggingOptions [TRACKED], @@ -418,7 +420,7 @@ top_level_options!( // written `extern crate name as std`. Defaults to `std`. Used by // out-of-tree drivers. alt_std_name: Option [TRACKED], - // Indicates how the compiler should treat unstable features + // Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], // Indicates whether this run of the compiler is actually rustdoc. This @@ -434,12 +436,12 @@ top_level_options!( cli_forced_codegen_units: Option [UNTRACKED], cli_forced_thinlto_off: bool [UNTRACKED], - // Remap source path prefixes in all output (messages, object files, debug, etc) + // Remap source path prefixes in all output (messages, object files, debug, etc.). remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], edition: Edition [TRACKED], - // Whether or not we're emitting JSON blobs about each artifact produced + // `true` if we're emitting JSON blobs about each artifact produced // by the compiler. json_artifact_notifications: bool [TRACKED], } @@ -468,7 +470,7 @@ pub enum BorrowckMode { } impl BorrowckMode { - /// Should we run the MIR-based borrow check, but also fall back + /// Returns whether we should run the MIR-based borrow check, but also fall back /// on the AST borrow check if the MIR-based one errors. pub fn migrate(self) -> bool { match self { @@ -477,7 +479,7 @@ impl BorrowckMode { } } - /// Should we emit the AST-based borrow checker errors? + /// Returns whether we should emit the AST-based borrow checker errors. pub fn use_ast(self) -> bool { match self { BorrowckMode::Mir => false, @@ -487,12 +489,13 @@ impl BorrowckMode { } pub enum Input { - /// Loads source from file + /// Load source code from a file. File(PathBuf), + /// Load source code from a string. Str { - /// String that is shown in place of a filename + /// A string that is shown in place of a filename. name: FileName, - /// Anonymous source string + /// An anonymous string containing the source code. input: String, }, } @@ -651,7 +654,7 @@ impl Options { FilePathMapping::new(self.remap_path_prefix.clone()) } - /// Returns `true` if there will be an output file generated + /// Returns `true` if there will be an output file generated. pub fn will_create_output_file(&self) -> bool { !self.debugging_opts.parse_only && // The file is just being parsed !self.debugging_opts.ls // The file is just being queried @@ -709,16 +712,14 @@ impl Passes { } } -/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all -/// at once. The goal of this macro is to define an interface that can be -/// programmatically used by the option parser in order to initialize the struct -/// without hardcoding field names all over the place. +/// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this +/// macro is to define an interface that can be programmatically used by the option parser +/// to initialize the struct without hardcoding field names all over the place. /// -/// The goal is to invoke this macro once with the correct fields, and then this -/// macro generates all necessary code. The main gotcha of this macro is the -/// cgsetters module which is a bunch of generated code to parse an option into -/// its respective field in the struct. There are a few hand-written parsers for -/// parsing specific types of values in this module. +/// The goal is to invoke this macro once with the correct fields, and then this macro generates all +/// necessary code. The main gotcha of this macro is the `cgsetters` module which is a bunch of +/// generated code to parse an option into its respective field in the struct. There are a few +/// hand-written parsers for parsing specific types of values in this module. macro_rules! options { ($struct_name:ident, $setter_name:ident, $defaultfn:ident, $buildfn:ident, $prefix:expr, $outputname:expr, @@ -1292,6 +1293,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show macro backtraces even for non-local macros"), teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help"), + terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], + "set the current terminal width"), continue_parse_after_error: bool = (false, parse_bool, [TRACKED], "attempt to recover from parse errors (experimental)"), dep_tasks: bool = (false, parse_bool, [UNTRACKED], @@ -1537,7 +1540,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { ret } -/// Converts the crate cfg! configuration from String to Symbol. +/// Converts the crate `cfg!` configuration from `String` to `Symbol`. /// `rustc_interface::interface::Config` accepts this in the compiler configuration, /// but the symbol interner is not yet set up then, so we must convert it later. pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> ast::CrateConfig { @@ -1548,9 +1551,9 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> ast::CrateCo pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig { // Combine the configuration requested by the session (command line) with - // some default and generated configuration items + // some default and generated configuration items. let default_cfg = default_configuration(sess); - // If the user wants a test runner, then add the test cfg + // If the user wants a test runner, then add the test cfg. if sess.opts.test { user_cfg.insert((sym::test, None)); } @@ -1719,13 +1722,7 @@ pub fn rustc_short_optgroups() -> Vec { static, framework, or dylib (the default).", "[KIND=]NAME", ), - opt::multi_s( - "", - "crate-type", - "Comma separated list of types of crates - for the compiler to emit", - "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", - ), + make_crate_type_option(), opt::opt_s( "", "crate-name", @@ -1855,13 +1852,22 @@ pub fn rustc_optgroups() -> Vec { opts } -// Convert strings provided as --cfg [cfgspec] into a crate_cfg +struct NullEmitter; + +impl errors::emitter::Emitter for NullEmitter { + fn emit_diagnostic(&mut self, _: &errors::Diagnostic) {} +} + +// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { syntax::with_default_globals(move || { let cfg = cfgspecs.into_iter().map(|s| { - let sess = parse::ParseSess::new(FilePathMapping::empty()); + + let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let handler = Handler::with_emitter(false, None, Box::new(NullEmitter)); + let sess = ParseSess::with_span_handler(handler, cm); let filename = FileName::cfg_spec_source_code(&s); - let mut parser = parse::new_parser_from_source_str(&sess, filename, s.to_string()); + let mut parser = new_parser_from_source_str(&sess, filename, s.to_string()); macro_rules! error {($reason: expr) => { early_error(ErrorOutputType::default(), @@ -1921,7 +1927,7 @@ pub fn get_cmd_lint_options(matches: &getopts::Matches, (lint_opts, describe_lints, lint_cap) } -/// Parse the `--color` flag +/// Parses the `--color` flag. pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { match matches.opt_str("color").as_ref().map(|s| &s[..]) { Some("auto") => ColorConfig::Auto, @@ -1933,7 +1939,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { Some(arg) => early_error( ErrorOutputType::default(), &format!( - "argument for --color must be auto, \ + "argument for `--color` must be auto, \ always or never (instead was `{}`)", arg ), @@ -1978,16 +1984,16 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) (json_rendered(json_color), json_artifact_notifications) } -/// Parse the `--error-format` flag +/// Parses the `--error-format` flag. pub fn parse_error_format( matches: &getopts::Matches, color: ColorConfig, json_rendered: HumanReadableErrorType, ) -> ErrorOutputType { - // We need the opts_present check because the driver will send us Matches + // We need the `opts_present` check because the driver will send us Matches // with only stable options if no unstable options are used. Since error-format - // is unstable, it will not be present. We have to use opts_present not - // opt_present because the latter will panic. + // is unstable, it will not be present. We have to use `opts_present` not + // `opt_present` because the latter will panic. let error_format = if matches.opts_present(&["error-format".to_owned()]) { match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { None | @@ -2002,7 +2008,7 @@ pub fn parse_error_format( Some(arg) => early_error( ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), &format!( - "argument for --error-format must be `human`, `json` or \ + "argument for `--error-format` must be `human`, `json` or \ `short` (instead was `{}`)", arg ), @@ -2041,7 +2047,7 @@ pub fn build_session_options_and_crate_config( early_error( ErrorOutputType::default(), &format!( - "argument for --edition must be one of: \ + "argument for `--edition` must be one of: \ {}. (instead was `{}`)", EDITION_NAME_LIST, arg @@ -2055,7 +2061,7 @@ pub fn build_session_options_and_crate_config( early_error( ErrorOutputType::default(), &format!( - "Edition {} is unstable and only \ + "edition {} is unstable and only \ available for nightly builds of rustc.", edition, ) @@ -2079,14 +2085,14 @@ pub fn build_session_options_and_crate_config( if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { early_error( ErrorOutputType::Json { pretty: false, json_rendered }, - "--error-format=pretty-json is unstable", + "`--error-format=pretty-json` is unstable", ); } if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = error_format { early_error( ErrorOutputType::Json { pretty: false, json_rendered }, - "--error-format=human-annotate-rs is unstable", + "`--error-format=human-annotate-rs` is unstable", ); } } @@ -2120,7 +2126,7 @@ pub fn build_session_options_and_crate_config( let mut codegen_units = cg.codegen_units; let mut disable_thinlto = false; - // Issue #30063: if user requests llvm-related output to one + // Issue #30063: if user requests LLVM-related output to one // particular path, disable codegen-units. let incompatible: Vec<_> = output_types .iter() @@ -2136,8 +2142,8 @@ pub fn build_session_options_and_crate_config( early_warn( error_format, &format!( - "--emit={} with -o incompatible with \ - -C codegen-units=N for N > 1", + "`--emit={}` with `-o` incompatible with \ + `-C codegen-units=N` for N > 1", ot ), ); @@ -2157,21 +2163,21 @@ pub fn build_session_options_and_crate_config( if debugging_opts.threads == Some(0) { early_error( error_format, - "Value for threads must be a positive nonzero integer", + "value for threads must be a positive non-zero integer", ); } if debugging_opts.threads.unwrap_or(1) > 1 && debugging_opts.fuel.is_some() { early_error( error_format, - "Optimization fuel is incompatible with multiple threads", + "optimization fuel is incompatible with multiple threads", ); } if codegen_units == Some(0) { early_error( error_format, - "Value for codegen units must be a positive nonzero integer", + "value for codegen units must be a positive non-zero integer", ); } @@ -2418,10 +2424,10 @@ pub fn build_session_options_and_crate_config( ) } - // We start out with a Vec<(Option, bool)>>, - // and later convert it into a BTreeSet<(Option, bool)> + // We start out with a `Vec<(Option, bool)>>`, + // and later convert it into a `BTreeSet<(Option, bool)>` // This allows to modify entries in-place to set their correct - // 'public' value + // 'public' value. let mut externs: BTreeMap = BTreeMap::new(); for (arg, private) in matches.opt_strs("extern").into_iter().map(|v| (v, false)) .chain(matches.opt_strs("extern-private").into_iter().map(|v| (v, true))) { @@ -2506,6 +2512,16 @@ pub fn build_session_options_and_crate_config( ) } +pub fn make_crate_type_option() -> RustcOptGroup { + opt::multi_s( + "", + "crate-type", + "Comma separated list of types of crates + for the compiler to emit", + "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", + ) +} + pub fn parse_crate_types_from_list(list_list: Vec) -> Result, String> { let mut crate_types: Vec = Vec::new(); for unparsed_crate_type in &list_list { @@ -2610,15 +2626,15 @@ impl fmt::Display for CrateType { /// The values of all command-line arguments that are relevant for dependency /// tracking are hashed into a single value that determines whether the /// incremental compilation cache can be re-used or not. This hashing is done -/// via the DepTrackingHash trait defined below, since the standard Hash -/// implementation might not be suitable (e.g., arguments are stored in a Vec, +/// via the `DepTrackingHash` trait defined below, since the standard `Hash` +/// implementation might not be suitable (e.g., arguments are stored in a `Vec`, /// the hash of which is order dependent, but we might not want the order of /// arguments to make a difference for the hash). /// -/// However, since the value provided by Hash::hash often *is* suitable, +/// However, since the value provided by `Hash::hash` often *is* suitable, /// especially for primitive types, there is the -/// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the -/// Hash implementation for DepTrackingHash. It's important though that +/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the +/// `Hash` implementation for `DepTrackingHash`. It's important though that /// we have an opt-in scheme here, so one is hopefully forced to think about /// how the hash should be calculated when adding a new command-line argument. mod dep_tracking { @@ -2631,9 +2647,9 @@ mod dep_tracking { use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath, SymbolManglingVersion}; - use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; + use syntax::feature_gate::UnstableFeatures; pub trait DepTrackingHash { fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType); diff --git a/src/librustc/session/config/tests.rs b/src/librustc/session/config/tests.rs index 3d6312548a..9eb68056bf 100644 --- a/src/librustc/session/config/tests.rs +++ b/src/librustc/session/config/tests.rs @@ -87,7 +87,7 @@ fn test_can_print_warnings() { let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, None, registry); - assert!(!sess.diagnostic().flags.can_emit_warnings); + assert!(!sess.diagnostic().can_emit_warnings()); }); syntax::with_default_globals(|| { @@ -97,7 +97,7 @@ fn test_can_print_warnings() { let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, None, registry); - assert!(sess.diagnostic().flags.can_emit_warnings); + assert!(sess.diagnostic().can_emit_warnings()); }); syntax::with_default_globals(|| { @@ -105,7 +105,7 @@ fn test_can_print_warnings() { let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); let sess = build_session(sessopts, None, registry); - assert!(sess.diagnostic().flags.can_emit_warnings); + assert!(sess.diagnostic().can_emit_warnings()); }); } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 61dac67891..a24fed8f21 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -79,12 +79,12 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - // FIXME: lint_store and buffered_lints are not thread-safe, - // but are only used in a single thread + // FIXME: `lint_store` and `buffered_lints` are not thread-safe, + // but are only used in a single thread. pub lint_store: RwLock, pub buffered_lints: Lock>, - /// Set of (DiagnosticId, Option, message) tuples tracking + /// Set of `(DiagnosticId, Option, message)` tuples tracking /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, @@ -92,11 +92,11 @@ pub struct Session { pub plugin_attributes: Lock>, pub crate_types: Once>, pub dependency_formats: Once, - /// The crate_disambiguator is constructed out of all the `-C metadata` + /// The `crate_disambiguator` is constructed out of all the `-C metadata` /// arguments passed to the compiler. Its value together with the crate-name /// forms a unique global identifier for the crate. It is used to allow /// multiple crates with the same name to coexist. See the - /// rustc_codegen_llvm::back::symbol_names module for more information. + /// `rustc_codegen_llvm::back::symbol_names` module for more information. pub crate_disambiguator: Once, features: Once, @@ -111,7 +111,7 @@ pub struct Session { /// The maximum number of stackframes allowed in const eval. pub const_eval_stack_frame_limit: usize, - /// The metadata::creader module may inject an allocator/panic_runtime + /// The `metadata::creader` module may inject an allocator/`panic_runtime` /// dependency if it didn't already find one, and this tracks what was /// injected. pub allocator_kind: Once>, @@ -130,7 +130,7 @@ pub struct Session { /// Used by `-Z profile-queries` in `util::common`. pub profile_channel: Lock>>, - /// Used by -Z self-profile + /// Used by `-Z self-profile`. pub self_profiling: Option>, /// Some measurements that are being gathered during compilation. @@ -187,16 +187,16 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } -/// Enum to support dispatch of one-time diagnostics (in Session.diag_once) +/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`). enum DiagnosticBuilderMethod { Note, SpanNote, SpanSuggestion(String), // suggestion - // add more variants as needed to support one-time diagnostics + // Add more variants as needed to support one-time diagnostics. } -/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid -/// emitting the same message more than once +/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid +/// emitting the same message more than once. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum DiagnosticMessageId { ErrorId(u16), // EXXXX error code as integer @@ -365,12 +365,6 @@ impl Session { pub fn span_note_without_error>(&self, sp: S, msg: &str) { self.diagnostic().span_note_without_error(sp, msg) } - pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { - self.diagnostic().span_unimpl(sp, msg) - } - pub fn unimpl(&self, msg: &str) -> ! { - self.diagnostic().unimpl(msg) - } pub fn buffer_lint>( &self, @@ -408,7 +402,7 @@ impl Session { Some(next) => { self.next_node_id.set(ast::NodeId::from_usize(next)); } - None => bug!("Input too large, ran out of node ids!"), + None => bug!("input too large; ran out of node-IDs!"), } id @@ -440,11 +434,11 @@ impl Session { diag_builder.note(message); } DiagnosticBuilderMethod::SpanNote => { - let span = span_maybe.expect("span_note needs a span"); + let span = span_maybe.expect("`span_note` needs a span"); diag_builder.span_note(span, message); } DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { - let span = span_maybe.expect("span_suggestion_* needs a span"); + let span = span_maybe.expect("`span_suggestion_*` needs a span"); diag_builder.span_suggestion( span, message, @@ -688,7 +682,7 @@ impl Session { pub fn must_not_eliminate_frame_pointers(&self) -> bool { // "mcount" function relies on stack pointer. - // See https://sourceware.org/binutils/docs/gprof/Implementation.html + // See . if self.instrument_mcount() { true } else if let Some(x) = self.opts.cg.force_frame_pointers { @@ -699,7 +693,7 @@ impl Session { } /// Returns the symbol name for the registrar function, - /// given the crate Svh and the function DefIndex. + /// given the crate `Svh` and the function `DefIndex`. pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String { format!( "__rustc_plugin_registrar_{}__", @@ -719,7 +713,7 @@ impl Session { &self.sysroot, self.opts.target_triple.triple(), &self.opts.search_paths, - // target_tlib_path==None means it's the same as host_tlib_path. + // `target_tlib_path == None` means it's the same as `host_tlib_path`. self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path), kind, ) @@ -779,12 +773,12 @@ impl Session { if let IncrCompSession::Active { .. } = *incr_comp_session { } else { bug!( - "Trying to finalize IncrCompSession `{:?}`", + "trying to finalize `IncrCompSession` `{:?}`", *incr_comp_session - ) + ); } - // Note: This will also drop the lock file, thus unlocking the directory + // Note: this will also drop the lock file, thus unlocking the directory. *incr_comp_session = IncrCompSession::Finalized { session_directory: new_directory_path, }; @@ -800,13 +794,15 @@ impl Session { } => session_directory.clone(), IncrCompSession::InvalidBecauseOfErrors { .. } => return, _ => bug!( - "Trying to invalidate IncrCompSession `{:?}`", + "trying to invalidate `IncrCompSession` `{:?}`", *incr_comp_session ), }; - // Note: This will also drop the lock file, thus unlocking the directory - *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory }; + // Note: this will also drop the lock file, thus unlocking the directory. + *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { + session_directory, + }; } pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> { @@ -815,8 +811,8 @@ impl Session { incr_comp_session, |incr_comp_session| match *incr_comp_session { IncrCompSession::NotInitialized => bug!( - "Trying to get session directory from IncrCompSession `{:?}`", - *incr_comp_session + "trying to get session directory from `IncrCompSession`: {:?}", + *incr_comp_session, ), IncrCompSession::Active { ref session_directory, @@ -1038,6 +1034,7 @@ fn default_emitter( source_map: &Lrc, emitter_dest: Option>, ) -> Box { + let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace; match (sopts.error_format, emitter_dest) { (config::ErrorOutputType::HumanReadable(kind), dst) => { let (short, color_config) = kind.unzip(); @@ -1046,6 +1043,7 @@ fn default_emitter( let emitter = AnnotateSnippetEmitterWriter::new( Some(source_map.clone()), short, + external_macro_backtrace, ); Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) } else { @@ -1055,6 +1053,8 @@ fn default_emitter( Some(source_map.clone()), short, sopts.debugging_opts.teach, + sopts.debugging_opts.terminal_width, + external_macro_backtrace, ), Some(dst) => EmitterWriter::new( dst, @@ -1062,6 +1062,8 @@ fn default_emitter( short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer + None, // no terminal width + external_macro_backtrace, ), }; Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) @@ -1073,6 +1075,7 @@ fn default_emitter( source_map.clone(), pretty, json_rendered, + external_macro_backtrace, ).ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new( @@ -1082,6 +1085,7 @@ fn default_emitter( source_map.clone(), pretty, json_rendered, + external_macro_backtrace, ).ui_testing(sopts.debugging_opts.ui_testing), ), } @@ -1183,7 +1187,10 @@ fn build_session_( ); let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map); + let parse_sess = parse::ParseSess::with_span_handler( + span_diagnostic, + source_map, + ); let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), None => filesearch::get_or_default_sysroot(), @@ -1212,7 +1219,7 @@ fn build_session_( let print_fuel = AtomicU64::new(0); let working_dir = env::current_dir().unwrap_or_else(|e| - p_s.span_diagnostic + parse_sess.span_diagnostic .fatal(&format!("Current directory is invalid: {}", e)) .raise() ); @@ -1230,7 +1237,7 @@ fn build_session_( opts: sopts, host_tlib_path, target_tlib_path, - parse_sess: p_s, + parse_sess, sysroot, local_crate_source_file, working_dir, @@ -1375,13 +1382,13 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false)) + Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false)) } config::ErrorOutputType::Json { pretty, json_rendered } => - Box::new(JsonEmitter::basic(pretty, json_rendered)), + Box::new(JsonEmitter::basic(pretty, json_rendered, false)), }; let handler = errors::Handler::with_emitter(true, None, emitter); - handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal); + handler.struct_fatal(msg).emit(); errors::FatalError.raise(); } @@ -1389,13 +1396,13 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false)) + Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false)) } config::ErrorOutputType::Json { pretty, json_rendered } => - Box::new(JsonEmitter::basic(pretty, json_rendered)), + Box::new(JsonEmitter::basic(pretty, json_rendered, false)), }; let handler = errors::Handler::with_emitter(true, None, emitter); - handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); + handler.struct_warn(msg).emit(); } pub type CompileResult = Result<(), ErrorReported>; diff --git a/src/librustc/traits/chalk_fulfill.rs b/src/librustc/traits/chalk_fulfill.rs index 0c7c94b684..a7e1f2a6a7 100644 --- a/src/librustc/traits/chalk_fulfill.rs +++ b/src/librustc/traits/chalk_fulfill.rs @@ -81,6 +81,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { .map(|obligation| FulfillmentError { obligation: obligation.goal.clone(), code: FulfillmentErrorCode::CodeAmbiguity, + points_at_arg_span: false, }) .collect(); Err(errors) @@ -129,6 +130,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented ), + points_at_arg_span: false, }), } } else { @@ -142,6 +144,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented ), + points_at_arg_span: false, }) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 83bd5c5604..7935c01f84 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1,20 +1,21 @@ use super::{ + ConstEvalFailure, + EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + ObjectSafetyViolation, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, - TraitNotObjectSafe, - ConstEvalFailure, + Overflow, PredicateObligation, SelectionContext, SelectionError, - ObjectSafetyViolation, - Overflow, + TraitNotObjectSafe, }; use crate::hir; @@ -23,7 +24,7 @@ use crate::hir::def_id::DefId; use crate::infer::{self, InferCtxt}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::session::DiagnosticMessageId; -use crate::ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use crate::ty::GenericParamDefKind; use crate::ty::error::ExpectedFound; use crate::ty::fast_reject; @@ -32,17 +33,19 @@ use crate::ty::subst::Subst; use crate::ty::SubtypePredicate; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use std::fmt; use syntax::ast; -use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind}; +use syntax::symbol::{sym, kw}; +use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - pub fn report_fulfillment_errors(&self, - errors: &[FulfillmentError<'tcx>], - body_id: Option, - fallback_has_occurred: bool) { + pub fn report_fulfillment_errors( + &self, + errors: &[FulfillmentError<'tcx>], + body_id: Option, + fallback_has_occurred: bool, + ) { #[derive(Debug)] struct ErrorDescriptor<'tcx> { predicate: ty::Predicate<'tcx>, @@ -61,9 +64,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We want to ignore desugarings here: spans are equivalent even // if one is the result of a desugaring and the other is not. let mut span = error.obligation.cause.span; - if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. }) - = span.ctxt().outer_expn_info() { - span = def_site; + let expn_data = span.ctxt().outer_expn_data(); + if let ExpnKind::Desugaring(_) = expn_data.kind { + span = expn_data.call_site; } error_map.entry(span).or_default().push( @@ -118,11 +121,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. - fn error_implies(&self, - cond: &ty::Predicate<'tcx>, - error: &ty::Predicate<'tcx>) - -> bool - { + fn error_implies( + &self, + cond: &ty::Predicate<'tcx>, + error: &ty::Predicate<'tcx>, + ) -> bool { if cond == error { return true } @@ -154,13 +157,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { false } - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, - body_id: Option, - fallback_has_occurred: bool) { + fn report_fulfillment_error( + &self, + error: &FulfillmentError<'tcx>, + body_id: Option, + fallback_has_occurred: bool, + ) { debug!("report_fulfillment_errors({:?})", error); match error.code { - FulfillmentErrorCode::CodeSelectionError(ref e) => { - self.report_selection_error(&error.obligation, e, fallback_has_occurred); + FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { + self.report_selection_error( + &error.obligation, + selection_error, + fallback_has_occurred, + error.points_at_arg_span, + ); } FulfillmentErrorCode::CodeProjectionError(ref e) => { self.report_projection_error(&error.obligation, e); @@ -169,19 +180,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.maybe_report_ambiguity(&error.obligation, body_id); } FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types(&error.obligation.cause, - expected_found.expected, - expected_found.found, - err.clone()) - .emit(); + self.report_mismatched_types( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + err.clone(), + ).emit(); } } } - fn report_projection_error(&self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>) - { + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ) { let predicate = self.resolve_vars_if_possible(&obligation.predicate); @@ -537,7 +550,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.suggest_new_overflow_limit(&mut err); } - self.note_obligation_cause(&mut err, obligation); + self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code, + &mut vec![]); err.emit(); self.tcx.sess.abort_if_errors(); @@ -602,6 +616,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, fallback_has_occurred: bool, + points_at_arg: bool, ) { let span = obligation.cause.span; @@ -657,19 +672,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span, E0277, "{}", - message.unwrap_or_else(|| - format!("the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), post_message) - )); + message.unwrap_or_else(|| format!( + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message, + ))); let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { "consider using `()`, or a `Result`".to_owned() } else { - format!("{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty()) + format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty(), + ) }; if let Some(ref s) = label { @@ -686,6 +704,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); self.suggest_remove_reference(&obligation, &mut err, &trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); @@ -923,7 +942,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bug!("overflow should be handled before the `report_selection_error` path"); } }; + self.note_obligation_cause(&mut err, obligation); + err.emit(); } @@ -953,6 +974,74 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn suggest_fn_call( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ) { + let self_ty = trait_ref.self_ty(); + match self_ty.sty { + ty::FnDef(def_id, _) => { + // We tried to apply the bound to an `fn`. Check whether calling it would evaluate + // to a type that *would* satisfy the trait binding. If it would, suggest calling + // it: `bar(foo)` -> `bar(foo)`. This case is *very* likely to be hit if `foo` is + // `async`. + let output_ty = self_ty.fn_sig(self.tcx).output(); + let new_trait_ref = ty::TraitRef { + def_id: trait_ref.def_id(), + substs: self.tcx.mk_substs_trait(output_ty.skip_binder(), &[]), + }; + let obligation = Obligation::new( + obligation.cause.clone(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); + match self.evaluate_obligation(&obligation) { + Ok(EvaluationResult::EvaluatedToOk) | + Ok(EvaluationResult::EvaluatedToOkModuloRegions) | + Ok(EvaluationResult::EvaluatedToAmbig) => { + if let Some(hir::Node::Item(hir::Item { + ident, + node: hir::ItemKind::Fn(.., body_id), + .. + })) = self.tcx.hir().get_if_local(def_id) { + let body = self.tcx.hir().body(*body_id); + let msg = "use parentheses to call the function"; + let snippet = format!( + "{}({})", + ident, + body.params.iter() + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) + if ident.name != kw::SelfLower => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "), + ); + // When the obligation error has been ensured to have been caused by + // an argument, the `obligation.cause.span` points at the expression + // of the argument, so we can provide a suggestion. This is signaled + // by `points_at_arg`. Otherwise, we give a more general note. + if points_at_arg { + err.span_suggestion( + obligation.cause.span, + msg, + snippet, + Applicability::HasPlaceholders, + ); + } else { + err.help(&format!("{}: `{}`", msg, snippet)); + } + } + } + _ => {} + } + } + _ => {} + } + } + /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. fn suggest_remove_reference( @@ -969,6 +1058,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .filter(|c| !c.is_whitespace()) .take_while(|c| *c == '&') .count(); + if let Some('\'') = snippet.chars() + .filter(|c| !c.is_whitespace()) + .skip(refs_number) + .next() + { // Do not suggest removal of borrow from type arguments. + return; + } let mut trait_type = trait_ref.self_ty(); @@ -1044,7 +1140,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { node: hir::ExprKind::Closure(_, ref _decl, id, span, _), .. }) => { - (self.tcx.sess.source_map().def_span(span), self.tcx.hir().body(id).arguments.iter() + (self.tcx.sess.source_map().def_span(span), + self.tcx.hir().body(id).params.iter() .map(|arg| { if let hir::Pat { node: hir::PatKind::Tuple(ref args, _), @@ -1129,7 +1226,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => format!("{} {}argument{}", arg_length, if distinct && arg_length > 1 { "distinct " } else { "" }, - if arg_length == 1 { "" } else { "s" }), + pluralise!(arg_length)) } }; @@ -1327,7 +1424,10 @@ impl<'tcx> TyCtxt<'tcx> { let mut reported_violations = FxHashSet::default(); for violation in violations { if reported_violations.insert(violation.clone()) { - err.note(&violation.error_msg()); + match violation.span() { + Some(span) => err.span_label(span, violation.error_msg()), + None => err.note(&violation.error_msg()), + }; } } Some(err) @@ -1496,15 +1596,165 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } - fn note_obligation_cause(&self, - err: &mut DiagnosticBuilder<'_>, - obligation: &Obligation<'tcx, T>) - where T: fmt::Display - { - self.note_obligation_cause_code(err, - &obligation.predicate, - &obligation.cause.code, - &mut vec![]); + fn note_obligation_cause( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) { + // First, attempt to add note to this error with an async-await-specific + // message, and fall back to regular note otherwise. + if !self.note_obligation_cause_for_async_await(err, obligation) { + self.note_obligation_cause_code(err, &obligation.predicate, &obligation.cause.code, + &mut vec![]); + } + } + + /// Adds an async-await specific note to the diagnostic: + /// + /// ```ignore (diagnostic) + /// note: future does not implement `std::marker::Send` because this value is used across an + /// await + /// --> $DIR/issue-64130-non-send-future-diags.rs:15:5 + /// | + /// LL | let g = x.lock().unwrap(); + /// | - has type `std::sync::MutexGuard<'_, u32>` + /// LL | baz().await; + /// | ^^^^^^^^^^^ await occurs here, with `g` maybe used later + /// LL | } + /// | - `g` is later dropped here + /// ``` + /// + /// Returns `true` if an async-await specific note was added to the diagnostic. + fn note_obligation_cause_for_async_await( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) -> bool { + debug!("note_obligation_cause_for_async_await: obligation.predicate={:?} \ + obligation.cause.span={:?}", obligation.predicate, obligation.cause.span); + let source_map = self.tcx.sess.source_map(); + + // Look into the obligation predicate to determine the type in the generator which meant + // that the predicate was not satisifed. + let (trait_ref, target_ty) = match obligation.predicate { + ty::Predicate::Trait(trait_predicate) => + (trait_predicate.skip_binder().trait_ref, trait_predicate.skip_binder().self_ty()), + _ => return false, + }; + debug!("note_obligation_cause_for_async_await: target_ty={:?}", target_ty); + + // Attempt to detect an async-await error by looking at the obligation causes, looking + // for only generators, generator witnesses, opaque types or `std::future::GenFuture` to + // be present. + // + // When a future does not implement a trait because of a captured type in one of the + // generators somewhere in the call stack, then the result is a chain of obligations. + // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that + // future is passed as an argument to a function C which requires a `Send` type, then the + // chain looks something like this: + // + // - `BuiltinDerivedObligation` with a generator witness (B) + // - `BuiltinDerivedObligation` with a generator (B) + // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B) + // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) + // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) + // - `BuiltinDerivedObligation` with a generator witness (A) + // - `BuiltinDerivedObligation` with a generator (A) + // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A) + // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) + // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) + // - `BindingObligation` with `impl_send (Send requirement) + // + // The first obligations in the chain can be used to get the details of the type that is + // captured but the entire chain must be inspected to detect this case. + let mut generator = None; + let mut next_code = Some(&obligation.cause.code); + while let Some(code) = next_code { + debug!("note_obligation_cause_for_async_await: code={:?}", code); + match code { + ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | + ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", + derived_obligation.parent_trait_ref.self_ty().sty); + match derived_obligation.parent_trait_ref.self_ty().sty { + ty::Adt(ty::AdtDef { did, .. }, ..) if + self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, + ty::Generator(did, ..) => generator = generator.or(Some(did)), + ty::GeneratorWitness(_) | ty::Opaque(..) => {}, + _ => return false, + } + + next_code = Some(derived_obligation.parent_code.as_ref()); + }, + ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(..) + if generator.is_some() => break, + _ => return false, + } + } + + let generator_did = generator.expect("can only reach this if there was a generator"); + + // Only continue to add a note if the generator is from an `async` function. + let parent_node = self.tcx.parent(generator_did) + .and_then(|parent_did| self.tcx.hir().get_if_local(parent_did)); + debug!("note_obligation_cause_for_async_await: parent_node={:?}", parent_node); + if let Some(hir::Node::Item(hir::Item { + node: hir::ItemKind::Fn(_, header, _, _), + .. + })) = parent_node { + debug!("note_obligation_cause_for_async_await: header={:?}", header); + if header.asyncness != hir::IsAsync::Async { + return false; + } + } + + let span = self.tcx.def_span(generator_did); + let tables = self.tcx.typeck_tables_of(generator_did); + debug!("note_obligation_cause_for_async_await: generator_did={:?} span={:?} ", + generator_did, span); + + // Look for a type inside the generator interior that matches the target type to get + // a span. + let target_span = tables.generator_interior_types.iter() + .find(|ty::GeneratorInteriorTypeCause { ty, .. }| ty::TyS::same_type(*ty, target_ty)) + .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }| + (span, source_map.span_to_snippet(*span), scope_span)); + if let Some((target_span, Ok(snippet), scope_span)) = target_span { + // Look at the last interior type to get a span for the `.await`. + let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap(); + let mut span = MultiSpan::from_span(await_span); + span.push_span_label( + await_span, format!("await occurs here, with `{}` maybe used later", snippet)); + + span.push_span_label(*target_span, format!("has type `{}`", target_ty)); + + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + span.push_span_label( + source_map.end_point(*scope_span), + format!("`{}` is later dropped here", snippet), + ); + } + + err.span_note(span, &format!( + "future does not implement `{}` as this value is used across an await", + trait_ref, + )); + + // Add a note for the item obligation that remains - normally a note pointing to the + // bound that introduced the obligation (e.g. `T: Send`). + debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code); + self.note_obligation_cause_code( + err, + &obligation.predicate, + next_code.unwrap(), + &mut Vec::new(), + ); + + true + } else { + false + } } fn note_obligation_cause_code(&self, @@ -1534,17 +1784,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { - err.note(&format!("required so that the projection `{}` is well-formed", - data)); + err.note(&format!( + "required so that the projection `{}` is well-formed", + data, + )); } ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { - err.note(&format!("required so that reference `{}` does not outlive its referent", - ref_ty)); + err.note(&format!( + "required so that reference `{}` does not outlive its referent", + ref_ty, + )); } ObligationCauseCode::ObjectTypeBound(object_ty, region) => { - err.note(&format!("required so that the lifetime bound of `{}` for `{}` \ - is satisfied", - region, object_ty)); + err.note(&format!( + "required so that the lifetime bound of `{}` for `{}` is satisfied", + region, + object_ty, + )); } ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = tcx.def_path_str(item_def_id); @@ -1552,7 +1808,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(sp) = tcx.hir().span_if_local(item_def_id) { let sp = tcx.sess.source_map().def_span(sp); - err.span_note(sp, &msg); + err.span_label(sp, &msg); + } else { + err.note(&msg); + } + } + ObligationCauseCode::BindingObligation(item_def_id, span) => { + let item_name = tcx.def_path_str(item_def_id); + let msg = format!("required by this bound in `{}`", item_name); + if let Some(ident) = tcx.opt_item_name(item_def_id) { + err.span_label(ident.span, ""); + } + if span != DUMMY_SP { + err.span_label(span, &msg); } else { err.note(&msg); } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 99b5ef3894..805727b6ce 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -68,6 +68,10 @@ pub struct PendingPredicateObligation<'tcx> { pub stalled_on: Vec>, } +// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PendingPredicateObligation<'_>, 136); + impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. pub fn new() -> FulfillmentContext<'tcx> { @@ -248,19 +252,24 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { /// This is always inlined, despite its size, because it has a single /// callsite and it is called *very* frequently. #[inline(always)] - fn process_obligation(&mut self, - pending_obligation: &mut Self::Obligation) - -> ProcessResult - { - // if we were stalled on some unresolved variables, first check + fn process_obligation( + &mut self, + pending_obligation: &mut Self::Obligation, + ) -> ProcessResult { + // If we were stalled on some unresolved variables, first check // whether any of them have been resolved; if not, don't bother // doing more work yet if !pending_obligation.stalled_on.is_empty() { - if pending_obligation.stalled_on.iter().all(|&ty| { - // Use the force-inlined variant of shallow_resolve() because this code is hot. - let resolved = ShallowResolver::new(self.selcx.infcx()).inlined_shallow_resolve(ty); - resolved == ty // nothing changed here - }) { + let mut changed = false; + // This `for` loop was once a call to `all()`, but this lower-level + // form was a perf win. See #64545 for details. + for &ty in &pending_obligation.stalled_on { + if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) { + changed = true; + break; + } + } + if !changed { debug!("process_predicate: pending obligation {:?} still stalled on {:?}", self.selcx.infcx() .resolve_vars_if_possible(&pending_obligation.obligation), @@ -277,7 +286,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate); } - debug!("process_obligation: obligation = {:?}", obligation); + debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause); match obligation.predicate { ty::Predicate::Trait(ref data) => { @@ -425,10 +434,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::Predicate::WellFormed(ty) => { - match ty::wf::obligations(self.selcx.infcx(), - obligation.param_env, - obligation.cause.body_id, - ty, obligation.cause.span) { + match ty::wf::obligations( + self.selcx.infcx(), + obligation.param_env, + obligation.cause.body_id, + ty, + obligation.cause.span, + ) { None => { pending_obligation.stalled_on = vec![ty]; ProcessResult::Unchanged diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1ca92d79fa..1123422ad6 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -123,6 +123,10 @@ pub struct Obligation<'tcx, T> { pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PredicateObligation<'_>, 112); + /// The reason why we incurred this obligation; used for error reporting. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ObligationCause<'tcx> { @@ -147,7 +151,8 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::StartFunctionType => { tcx.sess.source_map().def_span(self.span) } - ObligationCauseCode::MatchExpressionArm { arm_span, .. } => arm_span, + ObligationCauseCode::MatchExpressionArm( + box MatchExpressionArmCause { arm_span, .. }) => arm_span, _ => self.span, } } @@ -171,6 +176,9 @@ pub enum ObligationCauseCode<'tcx> { /// also implement all supertraits of `X`. ItemObligation(DefId), + /// Like `ItemObligation`, but with extra detail on the source of the obligation. + BindingObligation(DefId, Span), + /// A type like `&'a T` is WF only if `T: 'a`. ReferenceOutlivesReferent(Ty<'tcx>), @@ -223,23 +231,13 @@ pub enum ObligationCauseCode<'tcx> { ExprAssignable, /// Computing common supertype in the arms of a match expression - MatchExpressionArm { - arm_span: Span, - source: hir::MatchSource, - prior_arms: Vec, - last_ty: Ty<'tcx>, - discrim_hir_id: hir::HirId, - }, + MatchExpressionArm(Box>), /// Computing common supertype in the pattern guard for the arms of a match expression MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> }, /// Computing common supertype in an if expression - IfExpression { - then: Span, - outer: Option, - semicolon: Option, - }, + IfExpression(Box), /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, @@ -269,6 +267,26 @@ pub enum ObligationCauseCode<'tcx> { TrivialBound, } +// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(ObligationCauseCode<'_>, 32); + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct MatchExpressionArmCause<'tcx> { + pub arm_span: Span, + pub source: hir::MatchSource, + pub prior_arms: Vec, + pub last_ty: Ty<'tcx>, + pub discrim_hir_id: hir::HirId, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct IfExpressionCause { + pub then: Span, + pub outer: Option, + pub semicolon: Option, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DerivedObligationCause<'tcx> { /// The trait reference of the parent obligation that led to the @@ -469,7 +487,11 @@ EnumTypeFoldableImpl! { pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, - pub code: FulfillmentErrorCode<'tcx> + pub code: FulfillmentErrorCode<'tcx>, + /// Diagnostics only: we opportunistically change the `code.span` when we encounter an + /// obligation error caused by a call argument. When this is the case, we also signal that in + /// this field to ensure accuracy of suggestions. + pub points_at_arg_span: bool, } #[derive(Clone)] @@ -640,11 +662,11 @@ pub struct VtableTraitAliasData<'tcx, N> { } /// Creates predicate obligations from the generic bounds. -pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>) - -> PredicateObligations<'tcx> -{ +pub fn predicates_for_generics<'tcx>( + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + generic_bounds: &ty::InstantiatedPredicates<'tcx>, +) -> PredicateObligations<'tcx> { util::predicates_for_generics(cause, 0, param_env, generic_bounds) } @@ -1168,7 +1190,7 @@ impl<'tcx> FulfillmentError<'tcx> { code: FulfillmentErrorCode<'tcx>) -> FulfillmentError<'tcx> { - FulfillmentError { obligation: obligation, code: code } + FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false } } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 37eff852ab..a7990c4af6 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,7 @@ use std::borrow::Cow; use std::iter::{self}; use syntax::ast::{self}; use syntax::symbol::InternedString; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation { @@ -32,10 +32,10 @@ pub enum ObjectSafetyViolation { SupertraitSelf, /// Method has something illegal. - Method(ast::Name, MethodViolationCode), + Method(ast::Name, MethodViolationCode, Span), /// Associated const. - AssocConst(ast::Name), + AssocConst(ast::Name, Span), } impl ObjectSafetyViolation { @@ -46,22 +46,35 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SupertraitSelf => "the trait cannot use `Self` as a type parameter \ in the supertraits or where-clauses".into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => - format!("method `{}` has no receiver", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => - format!("method `{}` references the `Self` type \ - in its arguments or return type", name).into(), - ObjectSafetyViolation::Method(name, - MethodViolationCode::WhereClauseReferencesSelf(_)) => - format!("method `{}` references the `Self` type in where clauses", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => + format!("associated function `{}` has no `self` parameter", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( + "method `{}` references the `Self` type in its parameters or return type", + name, + ).into(), + ObjectSafetyViolation::Method( + name, + MethodViolationCode::WhereClauseReferencesSelf, + _, + ) => format!("method `{}` references the `Self` type in where clauses", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => format!("method `{}` has generic type parameters", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) => - format!("method `{}`'s receiver cannot be dispatched on", name).into(), - ObjectSafetyViolation::AssocConst(name) => + ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => + format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(), + ObjectSafetyViolation::AssocConst(name, _) => format!("the trait cannot contain associated consts like `{}`", name).into(), } } + + pub fn span(&self) -> Option { + // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so + // diagnostics use a `note` instead of a `span_label`. + match *self { + ObjectSafetyViolation::AssocConst(_, span) | + ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span), + _ => None, + } + } } /// Reasons a method might not be object-safe. @@ -74,7 +87,7 @@ pub enum MethodViolationCode { ReferencesSelf, /// e.g., `fn foo(&self) where Self: Clone` - WhereClauseReferencesSelf(Span), + WhereClauseReferencesSelf, /// e.g., `fn foo()` Generic, @@ -88,9 +101,11 @@ impl<'tcx> TyCtxt<'tcx> { /// astconv -- currently, `Self` in supertraits. This is needed /// because `object_safety_violations` can't be used during /// type collection. - pub fn astconv_object_safety_violations(self, trait_def_id: DefId) - -> Vec - { + pub fn astconv_object_safety_violations( + self, + trait_def_id: DefId, + ) -> Vec { + debug_assert!(self.generics_of(trait_def_id).has_self); let violations = traits::supertrait_def_ids(self, trait_def_id) .filter(|&def_id| self.predicates_reference_self(def_id, true)) .map(|_| ObjectSafetyViolation::SupertraitSelf) @@ -106,6 +121,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn object_safety_violations(self, trait_def_id: DefId) -> Vec { + debug_assert!(self.generics_of(trait_def_id).has_self); debug!("object_safety_violations: {:?}", trait_def_id); traits::supertrait_def_ids(self, trait_def_id) @@ -113,19 +129,38 @@ impl<'tcx> TyCtxt<'tcx> { .collect() } - fn object_safety_violations_for_trait(self, trait_def_id: DefId) - -> Vec - { + /// We say a method is *vtable safe* if it can be invoked on a trait + /// object. Note that object-safe traits can have some + /// non-vtable-safe methods, so long as they require `Self: Sized` or + /// otherwise ensure that they cannot be used when `Self = Trait`. + pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool { + debug_assert!(self.generics_of(trait_def_id).has_self); + debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); + // Any method that has a `Self: Sized` bound cannot be called. + if self.generics_require_sized_self(method.def_id) { + return false; + } + + match self.virtual_call_violation_for_method(trait_def_id, method) { + None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true, + Some(_) => false, + } + } + + fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec { // Check methods for violations. let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| - self.object_safety_violation_for_method(trait_def_id, &item) - .map(|code| ObjectSafetyViolation::Method(item.ident.name, code)) + self.object_safety_violation_for_method(trait_def_id, &item).map(|code| { + ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span) + }) ).filter(|violation| { - if let ObjectSafetyViolation::Method(_, - MethodViolationCode::WhereClauseReferencesSelf(span)) = violation - { + if let ObjectSafetyViolation::Method( + _, + MethodViolationCode::WhereClauseReferencesSelf, + span, + ) = violation { // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. self.lint_node_note( @@ -151,7 +186,7 @@ impl<'tcx> TyCtxt<'tcx> { violations.extend(self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Const) - .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name))); + .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span))); debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, @@ -163,14 +198,16 @@ impl<'tcx> TyCtxt<'tcx> { fn predicates_reference_self( self, trait_def_id: DefId, - supertraits_only: bool) -> bool - { + supertraits_only: bool, + ) -> bool { let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id)); let predicates = if supertraits_only { self.super_predicates_of(trait_def_id) } else { self.predicates_of(trait_def_id) }; + let self_ty = self.types.self_param; + let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty); predicates .predicates .iter() @@ -179,7 +216,7 @@ impl<'tcx> TyCtxt<'tcx> { match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty()) + data.skip_binder().input_types().skip(1).any(has_self_ty) } ty::Predicate::Projection(ref data) => { // And similarly for projections. This should be redundant with @@ -199,7 +236,7 @@ impl<'tcx> TyCtxt<'tcx> { .trait_ref(self) .input_types() .skip(1) - .any(|t| t.has_self_ty()) + .any(has_self_ty) } ty::Predicate::WellFormed(..) | ty::Predicate::ObjectSafe(..) | @@ -229,11 +266,11 @@ impl<'tcx> TyCtxt<'tcx> { let predicates = predicates.instantiate_identity(self).predicates; elaborate_predicates(self, predicates) .any(|predicate| match predicate { - ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.skip_binder().self_ty().is_self() + ty::Predicate::Trait(ref trait_pred) => { + trait_pred.def_id() == sized_def_id + && trait_pred.skip_binder().self_ty().is_param(0) } ty::Predicate::Projection(..) | - ty::Predicate::Trait(..) | ty::Predicate::Subtype(..) | ty::Predicate::RegionOutlives(..) | ty::Predicate::WellFormed(..) | @@ -248,11 +285,11 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns `Some(_)` if this method makes the containing trait not object safe. - fn object_safety_violation_for_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> Option - { + fn object_safety_violation_for_method( + self, + trait_def_id: DefId, + method: &ty::AssocItem, + ) -> Option { debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method); // Any method that has a `Self : Sized` requisite is otherwise // exempt from the regulations. @@ -263,36 +300,15 @@ impl<'tcx> TyCtxt<'tcx> { self.virtual_call_violation_for_method(trait_def_id, method) } - /// We say a method is *vtable safe* if it can be invoked on a trait - /// object. Note that object-safe traits can have some - /// non-vtable-safe methods, so long as they require `Self:Sized` or - /// otherwise ensure that they cannot be used when `Self=Trait`. - pub fn is_vtable_safe_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> bool - { - debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); - // Any method that has a `Self : Sized` requisite can't be called. - if self.generics_require_sized_self(method.def_id) { - return false; - } - - match self.virtual_call_violation_for_method(trait_def_id, method) { - None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true, - Some(_) => false, - } - } - /// Returns `Some(_)` if this method cannot be called on a trait /// object; this does not necessarily imply that the enclosing trait /// is not object safe, because the method might have a where clause /// `Self:Sized`. - fn virtual_call_violation_for_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> Option - { + fn virtual_call_violation_for_method( + self, + trait_def_id: DefId, + method: &ty::AssocItem, + ) -> Option { // The method's first parameter must be named `self` if !method.method_has_self_argument { return Some(MethodViolationCode::StaticMethod); @@ -323,9 +339,10 @@ impl<'tcx> TyCtxt<'tcx> { .collect::>() // Do a shallow visit so that `contains_illegal_self_type_reference` // may apply it's custom visiting. - .visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) { - let span = self.def_span(method.def_id); - return Some(MethodViolationCode::WhereClauseReferencesSelf(span)); + .visit_tys_shallow(|t| { + self.contains_illegal_self_type_reference(trait_def_id, t) + }) { + return Some(MethodViolationCode::WhereClauseReferencesSelf); } let receiver_ty = self.liberate_late_bound_regions( @@ -333,15 +350,15 @@ impl<'tcx> TyCtxt<'tcx> { &sig.map_bound(|sig| sig.inputs()[0]), ); - // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. + // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows - // `Receiver: Unsize dyn Trait]>` - if receiver_ty != self.mk_self_type() { + // `Receiver: Unsize dyn Trait]>`. + if receiver_ty != self.types.self_param { if !self.receiver_is_dispatchable(method, receiver_ty) { return Some(MethodViolationCode::UndispatchableReceiver); } else { - // sanity check to make sure the receiver actually has the layout of a pointer + // Do sanity check to make sure the receiver actually has the layout of a pointer. use crate::ty::layout::Abi; @@ -351,12 +368,12 @@ impl<'tcx> TyCtxt<'tcx> { match self.layout_of(param_env.and(ty)) { Ok(layout) => &layout.abi, Err(err) => bug!( - "Error: {}\n while computing layout for type {:?}", err, ty + "error: {}\n while computing layout for type {:?}", err, ty ) } }; - // e.g., Rc<()> + // e.g., `Rc<()>` let unit_receiver_ty = self.receiver_for_self_ty( receiver_ty, self.mk_unit(), method.def_id ); @@ -367,7 +384,7 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.delay_span_bug( self.def_span(method.def_id), &format!( - "Receiver when Self = () should have a Scalar ABI, found {:?}", + "receiver when `Self = ()` should have a Scalar ABI; found {:?}", abi ), ); @@ -378,7 +395,7 @@ impl<'tcx> TyCtxt<'tcx> { trait_def_id, self.mk_region(ty::ReStatic) ); - // e.g., Rc + // e.g., `Rc` let trait_object_receiver = self.receiver_for_self_ty( receiver_ty, trait_object_ty, method.def_id ); @@ -389,7 +406,8 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.delay_span_bug( self.def_span(method.def_id), &format!( - "Receiver when Self = {} should have a ScalarPair ABI, found {:?}", + "receiver when `Self = {}` should have a ScalarPair ABI; \ + found {:?}", trait_object_ty, abi ), ); @@ -401,10 +419,13 @@ impl<'tcx> TyCtxt<'tcx> { None } - /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty` - /// e.g., for receiver_ty = `Rc` and self_ty = `Foo`, returns `Rc`. + /// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`. + /// For example, for `receiver_ty = Rc` and `self_ty = Foo`, returns `Rc`. fn receiver_for_self_ty( - self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId + self, + receiver_ty: Ty<'tcx>, + self_ty: Ty<'tcx>, + method_def_id: DefId, ) -> Ty<'tcx> { debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id); let substs = InternalSubsts::for_item(self, method_def_id, |param, _| { @@ -555,7 +576,7 @@ impl<'tcx> TyCtxt<'tcx> { // Self: Unsize let unsize_predicate = ty::TraitRef { def_id: unsize_did, - substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]), + substs: self.mk_substs_trait(self.types.self_param, &[unsized_self_ty.into()]), }.to_predicate(); // U: Trait @@ -608,11 +629,11 @@ impl<'tcx> TyCtxt<'tcx> { }) } - fn contains_illegal_self_type_reference(self, - trait_def_id: DefId, - ty: Ty<'tcx>) - -> bool - { + fn contains_illegal_self_type_reference( + self, + trait_def_id: DefId, + ty: Ty<'tcx>, + ) -> bool { // This is somewhat subtle. In general, we want to forbid // references to `Self` in the argument and return types, // since the value of `Self` is erased. However, there is one @@ -654,10 +675,11 @@ impl<'tcx> TyCtxt<'tcx> { let mut supertraits: Option>> = None; let mut error = false; + let self_ty = self.types.self_param; ty.maybe_walk(|ty| { match ty.sty { - ty::Param(ref param_ty) => { - if param_ty.is_self() { + ty::Param(_) => { + if ty == self_ty { error = true; } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 0a42b6b46f..5a988d9509 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -9,10 +9,9 @@ use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::Span; -use syntax_pos::symbol::LocalInternedString; #[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(LocalInternedString); +pub struct OnUnimplementedFormatString(Symbol); #[derive(Debug)] pub struct OnUnimplementedDirective { @@ -89,19 +88,19 @@ impl<'tcx> OnUnimplementedDirective { if item.check_name(sym::message) && message.is_none() { if let Some(message_) = item.value_str() { message = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, message_.as_str(), span)?); + tcx, trait_def_id, message_, span)?); continue; } } else if item.check_name(sym::label) && label.is_none() { if let Some(label_) = item.value_str() { label = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, label_.as_str(), span)?); + tcx, trait_def_id, label_, span)?); continue; } } else if item.check_name(sym::note) && note.is_none() { if let Some(note_) = item.value_str() { note = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, note_.as_str(), span)?); + tcx, trait_def_id, note_, span)?); continue; } } else if item.check_name(sym::on) && is_root && @@ -154,7 +153,7 @@ impl<'tcx> OnUnimplementedDirective { message: None, subcommands: vec![], label: Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, value.as_str(), attr.span)?), + tcx, trait_def_id, value, attr.span)?), note: None, })) } else { @@ -218,7 +217,7 @@ impl<'tcx> OnUnimplementedFormatString { fn try_parse( tcx: TyCtxt<'tcx>, trait_def_id: DefId, - from: LocalInternedString, + from: Symbol, err_sp: Span, ) -> Result { let result = OnUnimplementedFormatString(from); @@ -234,7 +233,8 @@ impl<'tcx> OnUnimplementedFormatString { ) -> Result<(), ErrorReported> { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); - let parser = Parser::new(&self.0, None, vec![], false); + let s = self.0.as_str(); + let parser = Parser::new(&s, None, vec![], false); let mut result = Ok(()); for token in parser { match token { @@ -294,7 +294,8 @@ impl<'tcx> OnUnimplementedFormatString { }).collect::>(); let empty_string = String::new(); - let parser = Parser::new(&self.0, None, vec![], false); + let s = self.0.as_str(); + let parser = Parser::new(&s, None, vec![], false); parser.map(|p| match p { Piece::String(s) => s, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 38263f26a5..87a23f655a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -15,7 +15,6 @@ use super::util; use crate::hir::def_id::DefId; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::mir::interpret::{GlobalId, ConstValue}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_macros::HashStable; use syntax::ast::Ident; @@ -397,40 +396,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { - let tcx = self.selcx.tcx().global_tcx(); - let param_env = self.param_env; - if !param_env.has_local_value() { - if substs.needs_infer() || substs.has_placeholders() { - let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); - let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(tcx, substs); - return evaluated; - } - } - } else { - if !substs.has_local_value() { - let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return evaluated; - } - } - } - } - } - } - constant + constant.eval(self.selcx.tcx(), self.param_env) } } @@ -1417,7 +1383,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( projection_ty: ty::ProjectionTy::from_ref_and_name( tcx, trait_ref, - Ident::with_empty_ctxt(FN_OUTPUT_NAME), + Ident::with_dummy_span(FN_OUTPUT_NAME), ), ty: ret_type } diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 2ee63647aa..b9557ceaa6 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -1,7 +1,8 @@ use crate::infer::InferCtxt; use crate::infer::canonical::OriginalQueryValues; -use crate::traits::{EvaluationResult, PredicateObligation, SelectionContext, - TraitQueryMode, OverflowError}; +use crate::traits::{ + EvaluationResult, PredicateObligation, SelectionContext, TraitQueryMode, OverflowError, +}; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs index 6b9bdfd63f..039dea1ffc 100644 --- a/src/librustc/traits/query/method_autoderef.rs +++ b/src/librustc/traits/query/method_autoderef.rs @@ -6,11 +6,11 @@ use crate::ty::Ty; pub struct CandidateStep<'tcx> { pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, pub autoderefs: usize, - // true if the type results from a dereference of a raw pointer. - // when assembling candidates, we include these steps, but not when - // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods - // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then - // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. + /// `true` if the type results from a dereference of a raw pointer. + /// when assembling candidates, we include these steps, but not when + /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods + /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then + /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. pub from_unsafe_deref: bool, pub unsize: bool, } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 2ffcd0fd4d..c31ff3ab1b 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -5,11 +5,10 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; -use crate::mir::interpret::{GlobalId, ConstValue}; use crate::traits::project::Normalized; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::subst::{Subst, InternalSubsts}; +use crate::ty::subst::Subst; use crate::ty::{self, Ty, TyCtxt}; use super::NoSolution; @@ -191,40 +190,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { - let tcx = self.infcx.tcx.global_tcx(); - let param_env = self.param_env; - if !param_env.has_local_value() { - if substs.needs_infer() || substs.has_placeholders() { - let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); - let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(tcx, substs); - return evaluated; - } - } - } else { - if !substs.has_local_value() { - let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return evaluated; - } - } - } - } - } - } - constant + constant.eval(self.infcx.tcx, self.param_env) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d4ae366262..a54bc05f16 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -134,7 +134,7 @@ impl IntercrateAmbiguityCause { String::new() }; format!( - "upstream crates may add new impl of trait `{}`{} \ + "upstream crates may add a new impl of trait `{}`{} \ in future versions", trait_desc, self_desc ) @@ -3513,7 +3513,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We can only make objects from sized types. let tr = ty::TraitRef { - def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: tcx.mk_substs_trait(source, &[]), }; nested.push(predicate_to_obligation(tr.to_predicate())); diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 05b698eb4c..68c97226f8 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -472,6 +472,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::TupleElem => Some(super::TupleElem), super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf), super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)), + super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)), super::ReferenceOutlivesReferent(ty) => { tcx.lift(&ty).map(super::ReferenceOutlivesReferent) } @@ -508,31 +509,33 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { trait_item_def_id, }), super::ExprAssignable => Some(super::ExprAssignable), - super::MatchExpressionArm { + super::MatchExpressionArm(box super::MatchExpressionArmCause { arm_span, source, ref prior_arms, last_ty, discrim_hir_id, - } => { + }) => { tcx.lift(&last_ty).map(|last_ty| { - super::MatchExpressionArm { + super::MatchExpressionArm(box super::MatchExpressionArmCause { arm_span, source, prior_arms: prior_arms.clone(), last_ty, discrim_hir_id, - } + }) }) } super::MatchExpressionArmPattern { span, ty } => { tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty }) } - super::IfExpression { then, outer, semicolon } => Some(super::IfExpression { - then, - outer, - semicolon, - }), + super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => { + Some(super::IfExpression(box super::IfExpressionCause { + then, + outer, + semicolon, + })) + } super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), super::MainFunctionType => Some(super::MainFunctionType), super::StartFunctionType => Some(super::StartFunctionType), diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 07d6f63314..3e5520dd46 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -512,21 +512,20 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( (impl_trait_ref, impl_obligations) } -/// See `super::obligations_for_generics` -pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, - recursion_depth: usize, - param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>) - -> Vec> -{ - debug!("predicates_for_generics(generic_bounds={:?})", - generic_bounds); - - generic_bounds.predicates.iter().map(|predicate| { - Obligation { cause: cause.clone(), - recursion_depth, - param_env, - predicate: predicate.clone() } +/// See [`super::obligations_for_generics`]. +pub fn predicates_for_generics<'tcx>( + cause: ObligationCause<'tcx>, + recursion_depth: usize, + param_env: ty::ParamEnv<'tcx>, + generic_bounds: &ty::InstantiatedPredicates<'tcx>, +) -> Vec> { + debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); + + generic_bounds.predicates.iter().map(|predicate| Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate: predicate.clone(), }).collect() } @@ -562,7 +561,7 @@ impl<'tcx> TyCtxt<'tcx> { predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth) } - /// Cast a trait reference into a reference to one of its super + /// Casts a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. pub fn upcast_choices(self, @@ -571,7 +570,7 @@ impl<'tcx> TyCtxt<'tcx> { -> Vec> { if source_trait_ref.def_id() == target_trait_def_id { - return vec![source_trait_ref]; // shorcut the most common case + return vec![source_trait_ref]; // Shortcut the most common case. } supertraits(self, source_trait_ref) diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index e3c6eca02d..1aa2150112 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -27,7 +27,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash { fn variant(&self) -> &Self::Variant; } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> EncodableWithShorthand for Ty<'tcx> { type Variant = ty::TyKind<'tcx>; fn variant(&self) -> &Self::Variant { @@ -160,7 +160,7 @@ where Ok(decoder.map_encoded_cnum_to_current(cnum)) } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn decode_ty(decoder: &mut D) -> Result, D::Error> where @@ -284,9 +284,11 @@ where #[macro_export] macro_rules! __impl_decoder_methods { ($($name:ident -> $ty:ty;)*) => { - $(fn $name(&mut self) -> Result<$ty, Self::Error> { - self.opaque.$name() - })* + $( + fn $name(&mut self) -> Result<$ty, Self::Error> { + self.opaque.$name() + } + )* } } @@ -327,14 +329,17 @@ macro_rules! impl_arena_allocatable_decoders { macro_rules! implement_ty_decoder { ($DecoderName:ident <$($typaram:tt),*>) => { mod __ty_decoder_impl { - use super::$DecoderName; + use std::borrow::Cow; + + use rustc_serialize::{Decoder, SpecializedDecoder}; + use $crate::infer::canonical::CanonicalVarInfos; use $crate::ty; use $crate::ty::codec::*; use $crate::ty::subst::SubstsRef; use $crate::hir::def_id::{CrateNum}; - use rustc_serialize::{Decoder, SpecializedDecoder}; - use std::borrow::Cow; + + use super::$DecoderName; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { type Error = String; @@ -368,8 +373,8 @@ macro_rules! implement_ty_decoder { } } - // FIXME(#36588) These impls are horribly unsound as they allow - // the caller to pick any lifetime for 'tcx, including 'static, + // FIXME(#36588): These impls are horribly unsound as they allow + // the caller to pick any lifetime for `'tcx`, including `'static`, // by using the unspecialized proxies to them. arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ef74d9e5b2..785f45e46b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1,5 +1,7 @@ //! Type context book-keeping. +// ignore-tidy-filelength + use crate::arena::Arena; use crate::dep_graph::DepGraph; use crate::dep_graph::{self, DepNode, DepConstructor}; @@ -7,7 +9,7 @@ use crate::session::Session; use crate::session::config::{BorrowckMode, OutputFilenames}; use crate::session::config::CrateType; use crate::middle; -use crate::hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node}; +use crate::hir::{self, TraitCandidate, HirId, ItemKind, ItemLocalId, Node}; use crate::hir::def::{Res, DefKind, Export}; use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use crate::hir::map as hir_map; @@ -21,7 +23,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{Body, interpret, ProjectionKind}; +use crate::mir::{Body, interpret, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -45,15 +47,16 @@ use crate::ty::CanonicalPolyFnSig; use crate::util::common::ErrorReported; use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet}; use crate::util::nodemap::{FxHashMap, FxHashSet}; + use errors::DiagnosticBuilder; -use smallvec::SmallVec; -use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, - StableHasher, StableHasherResult, - StableVec}; use arena::SyncDroplessArena; +use smallvec::SmallVec; +use rustc_data_structures::stable_hasher::{ + HashStable, StableHasher, StableHasherResult, StableVec, hash_stable_hashmap, +}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; use rustc_data_structures::sharded::ShardedHashMap; +use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; @@ -74,8 +77,6 @@ use syntax::feature_gate; use syntax::symbol::{Symbol, InternedString, kw, sym}; use syntax_pos::Span; -use crate::hir; - pub struct AllArenas { pub interner: SyncDroplessArena, } @@ -91,10 +92,10 @@ impl AllArenas { type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { - /// The arena that types, regions, etc are allocated from + /// The arena that types, regions, etc. are allocated from. arena: &'tcx SyncDroplessArena, - /// Specifically use a speedy hash algorithm for these hash sets, + /// Specifically use a speedy hash algorithm for these hash sets, since /// they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, type_list: InternedSet<'tcx, List>>, @@ -129,8 +130,8 @@ impl<'tcx> CtxtInterners<'tcx> { } } - /// Intern a type - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + /// Interns a type. + #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, st: TyKind<'tcx> @@ -144,7 +145,6 @@ impl<'tcx> CtxtInterners<'tcx> { outer_exclusive_binder: flags.outer_exclusive_binder, }; - Interned(self.arena.alloc(ty_struct)) }).0 } @@ -173,6 +173,7 @@ pub struct CommonTypes<'tcx> { pub f32: Ty<'tcx>, pub f64: Ty<'tcx>, pub never: Ty<'tcx>, + pub self_param: Ty<'tcx>, pub err: Ty<'tcx>, /// Dummy type used for the `Self` of a `TraitRef` created for converting @@ -206,26 +207,24 @@ pub struct LocalTableInContext<'a, V> { fn validate_hir_id_for_typeck_tables(local_id_root: Option, hir_id: hir::HirId, mut_access: bool) { - if cfg!(debug_assertions) { - if let Some(local_id_root) = local_id_root { - if hir_id.owner != local_id_root.index { - ty::tls::with(|tcx| { - bug!("node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", - tcx.hir().node_to_string(hir_id), - DefId::local(hir_id.owner), - local_id_root) - }); - } - } else { - // We use "Null Object" TypeckTables in some of the analysis passes. - // These are just expected to be empty and their `local_id_root` is - // `None`. Therefore we cannot verify whether a given `HirId` would - // be a valid key for the given table. Instead we make sure that - // nobody tries to write to such a Null Object table. - if mut_access { - bug!("access to invalid TypeckTables") - } + if let Some(local_id_root) = local_id_root { + if hir_id.owner != local_id_root.index { + ty::tls::with(|tcx| { + bug!("node {} with HirId::owner {:?} cannot be placed in \ + TypeckTables with local_id_root {:?}", + tcx.hir().node_to_string(hir_id), + DefId::local(hir_id.owner), + local_id_root) + }); + } + } else { + // We use "Null Object" TypeckTables in some of the analysis passes. + // These are just expected to be empty and their `local_id_root` is + // `None`. Therefore we cannot verify whether a given `HirId` would + // be a valid key for the given table. Instead we make sure that + // nobody tries to write to such a Null Object table. + if mut_access { + bug!("access to invalid TypeckTables") } } } @@ -292,6 +291,40 @@ pub struct ResolvedOpaqueTy<'tcx> { pub substs: SubstsRef<'tcx>, } +/// Whenever a value may be live across a generator yield, the type of that value winds up in the +/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such +/// captured types that can be useful for diagnostics. In particular, it stores the span that +/// caused a given type to be recorded, along with the scope that enclosed the value (which can +/// be used to find the await that the value is live across). +/// +/// For example: +/// +/// ```ignore (pseudo-Rust) +/// async move { +/// let x: T = ...; +/// foo.await +/// ... +/// } +/// ``` +/// +/// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for +/// the scope that contains `x`. +#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, HashStable, PartialEq)] +pub struct GeneratorInteriorTypeCause<'tcx> { + /// Type of the captured binding. + pub ty: Ty<'tcx>, + /// Span of the binding that was captured. + pub span: Span, + /// Span of the scope of the captured binding. + pub scope_span: Option, +} + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for GeneratorInteriorTypeCause<'tcx> { + ty, span, scope_span + } +} + #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct TypeckTables<'tcx> { /// The HirId::owner all ItemLocalIds in this table are relative to. @@ -401,6 +434,10 @@ pub struct TypeckTables<'tcx> { /// leading to the member of the struct or tuple that is used instead of the /// entire variable. pub upvar_list: ty::UpvarListMap, + + /// Stores the type, span and optional scope span of all types + /// that are live across the yield of this generator (if a generator). + pub generator_interior_types: Vec>, } impl<'tcx> TypeckTables<'tcx> { @@ -426,6 +463,7 @@ impl<'tcx> TypeckTables<'tcx> { free_region_map: Default::default(), concrete_opaque_types: Default::default(), upvar_list: Default::default(), + generator_interior_types: Default::default(), } } @@ -735,6 +773,7 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { ref free_region_map, ref concrete_opaque_types, ref upvar_list, + ref generator_interior_types, } = *self; @@ -779,6 +818,7 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { free_region_map.hash_stable(hcx, hasher); concrete_opaque_types.hash_stable(hcx, hasher); upvar_list.hash_stable(hcx, hasher); + generator_interior_types.hash_stable(hcx, hasher); }) } } @@ -915,6 +955,10 @@ impl<'tcx> CommonTypes<'tcx> { u128: mk(Uint(ast::UintTy::U128)), f32: mk(Float(ast::FloatTy::F32)), f64: mk(Float(ast::FloatTy::F64)), + self_param: mk(ty::Param(ty::ParamTy { + index: 0, + name: kw::SelfUpper.as_interned_str(), + })), trait_object_dummy_self: mk(Infer(ty::FreshTy(0))), } @@ -973,6 +1017,7 @@ pub struct FreeRegionInfo { /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")] pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } @@ -1019,7 +1064,7 @@ pub struct GlobalCtxt<'tcx> { hir_map: hir_map::Map<'tcx>, - /// A map from DefPathHash -> DefId. Includes DefIds from the local crate + /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate /// as well as all upstream crates. Only populated in incremental mode. pub def_path_hash_to_def_id: Option>, @@ -1091,6 +1136,16 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(Steal::new(mir)) } + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { + self.arena.alloc(Steal::new(promoted)) + } + + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { + self.arena.alloc(promoted) + } + pub fn alloc_adt_def( self, did: DefId, @@ -1108,9 +1163,9 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Allocates a byte or string literal for `mir::interpret`, read-only + /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { - // create an allocation that just contains these bytes + // Create an allocation that just contains these bytes. let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); let alloc = self.intern_const_alloc(alloc); self.alloc_map.lock().create_memory_alloc(alloc) @@ -1293,10 +1348,22 @@ impl<'tcx> TyCtxt<'tcx> { self.get_lib_features(LOCAL_CRATE) } + /// Obtain all lang items of this crate and all dependencies (recursively) pub fn lang_items(self) -> &'tcx middle::lang_items::LanguageItems { self.get_lang_items(LOCAL_CRATE) } + /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to + /// compare against another `DefId`, since `is_diagnostic_item` is cheaper. + pub fn get_diagnostic_item(self, name: Symbol) -> Option { + self.all_diagnostic_items(LOCAL_CRATE).get(&name).copied() + } + + /// Check whether the diagnostic item with the given `name` has the given `DefId`. + pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool { + self.diagnostic_items(did.krate).get(&name) == Some(&did) + } + pub fn stability(self) -> &'tcx stability::Index<'tcx> { self.stability_index(LOCAL_CRATE) } @@ -1318,7 +1385,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Converts a `DefId` into its fully expanded `DefPath` (every - /// `DefId` is really just an interned def-path). + /// `DefId` is really just an interned `DefPath`). /// /// Note that if `id` is not local to this crate, the result will /// be a non-local `DefPath`. @@ -1374,6 +1441,10 @@ impl<'tcx> TyCtxt<'tcx> { self.cstore.metadata_encoding_version().to_vec() } + pub fn encode_metadata(self)-> EncodedMetadata { + self.cstore.encode_metadata(self) + } + // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { @@ -1418,25 +1489,25 @@ impl<'tcx> TyCtxt<'tcx> { self.queries.on_disk_cache.serialize(self.global_tcx(), encoder) } - /// If true, we should use the AST-based borrowck (we may *also* use + /// If `true`, we should use the AST-based borrowck (we may *also* use /// the MIR-based borrowck). pub fn use_ast_borrowck(self) -> bool { self.borrowck_mode().use_ast() } - /// If true, we should use the MIR-based borrow check, but also - /// fall back on the AST borrow check if the MIR-based one errors. + /// If `true`, we should use the MIR-based borrowck, but also + /// fall back on the AST borrowck if the MIR-based one errors. pub fn migrate_borrowck(self) -> bool { self.borrowck_mode().migrate() } - /// If true, make MIR codegen for `match` emit a temp that holds a + /// If `true`, make MIR codegen for `match` emit a temp that holds a /// borrow of the input to the match expression. pub fn generate_borrow_of_any_match_input(&self) -> bool { self.emit_read_for_match() } - /// If true, make MIR codegen for `match` emit FakeRead + /// If `true`, make MIR codegen for `match` emit FakeRead /// statements (which simulate the maximal effect of executing the /// patterns in a match arm). pub fn emit_read_for_match(&self) -> bool { @@ -1489,7 +1560,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - // This method returns the DefId and the BoundRegion corresponding to the given region. + // Returns the `DefId` and the `BoundRegion` corresponding to the given region. pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option { let (suitable_region_binding_scope, bound_region) = match *region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), @@ -1522,18 +1593,18 @@ impl<'tcx> TyCtxt<'tcx> { &self, scope_def_id: DefId, ) -> Option> { - // HACK: `type_of_def_id()` will fail on these (#55796), so return None + // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap(); match self.hir().get(hir_id) { Node::Item(item) => { match item.node { - ItemKind::Fn(..) => { /* type_of_def_id() will work */ } + ItemKind::Fn(..) => { /* `type_of_def_id()` will work */ } _ => { return None; } } } - _ => { /* type_of_def_id() will work or panic */ } + _ => { /* `type_of_def_id()` will work or panic */ } } let ret_ty = self.type_of(scope_def_id); @@ -1551,7 +1622,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - // Here we check if the bound region is in Impl Item. + // Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item( &self, suitable_region_binding_scope: DefId, @@ -1571,23 +1642,15 @@ impl<'tcx> TyCtxt<'tcx> { false } - /// Determine whether identifiers in the assembly have strict naming rules. + /// Determines whether identifiers in the assembly have strict naming rules. /// Currently, only NVPTX* targets need it. pub fn has_strict_asm_symbol_naming(&self) -> bool { - self.gcx.sess.target.target.arch.contains("nvptx") - } -} - -impl<'tcx> TyCtxt<'tcx> { - pub fn encode_metadata(self) - -> EncodedMetadata - { - self.cstore.encode_metadata(self) + self.sess.target.target.arch.contains("nvptx") } } impl<'tcx> GlobalCtxt<'tcx> { - /// Call the closure with a local `TyCtxt` using the given arena. + /// Calls the closure with a local `TyCtxt` using the given arena. /// `interners` is a slot passed so we can create a CtxtInterners /// with the same lifetime as `arena`. pub fn enter_local(&'tcx self, f: F) -> R @@ -1623,7 +1686,7 @@ impl<'tcx> GlobalCtxt<'tcx> { /// It would be more efficient if `TypedArena` provided a way to /// determine whether the address is in the allocated range. /// -/// None is returned if the value or one of the components is not part +/// `None` is returned if the value or one of the components is not part /// of the provided context. /// For `Ty`, `None` can be returned if either the type interner doesn't /// contain the `TyKind` key or if the address of the interned @@ -1634,7 +1697,6 @@ pub trait Lift<'tcx>: fmt::Debug { fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option; } - macro_rules! nop_lift { ($ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for $ty { @@ -1681,7 +1743,7 @@ nop_list_lift!{Predicate<'a> => Predicate<'tcx>} nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo} nop_list_lift!{ProjectionKind => ProjectionKind} -// this is the impl for `&'a InternalSubsts<'a>` +// This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift!{Kind<'a> => Kind<'tcx>} pub mod tls { @@ -1704,43 +1766,43 @@ pub mod tls { use rustc_rayon_core as rayon_core; /// This is the implicit state of rustc. It contains the current - /// TyCtxt and query. It is updated when creating a local interner or - /// executing a new query. Whenever there's a TyCtxt value available - /// you should also have access to an ImplicitCtxt through the functions + /// `TyCtxt` and query. It is updated when creating a local interner or + /// executing a new query. Whenever there's a `TyCtxt` value available + /// you should also have access to an `ImplicitCtxt` through the functions /// in this module. #[derive(Clone)] pub struct ImplicitCtxt<'a, 'tcx> { - /// The current TyCtxt. Initially created by `enter_global` and updated - /// by `enter_local` with a new local interner + /// The current `TyCtxt`. Initially created by `enter_global` and updated + /// by `enter_local` with a new local interner. pub tcx: TyCtxt<'tcx>, - /// The current query job, if any. This is updated by JobOwner::start in - /// ty::query::plumbing when executing a query + /// The current query job, if any. This is updated by `JobOwner::start` in + /// `ty::query::plumbing` when executing a query. pub query: Option>>, /// Where to store diagnostics for the current query job, if any. - /// This is updated by JobOwner::start in ty::query::plumbing when executing a query + /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. pub diagnostics: Option<&'a Lock>>, /// Used to prevent layout from recursing too deeply. pub layout_depth: usize, /// The current dep graph task. This is used to add dependencies to queries - /// when executing them + /// when executing them. pub task_deps: Option<&'a Lock>, } - /// Sets Rayon's thread local variable which is preserved for Rayon jobs + /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs /// to `value` during the call to `f`. It is restored to its previous value after. - /// This is used to set the pointer to the new ImplicitCtxt. + /// This is used to set the pointer to the new `ImplicitCtxt`. #[cfg(parallel_compiler)] #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { rayon_core::tlv::with(value, f) } - /// Gets Rayon's thread local variable which is preserved for Rayon jobs. - /// This is used to get the pointer to the current ImplicitCtxt. + /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs. + /// This is used to get the pointer to the current `ImplicitCtxt`. #[cfg(parallel_compiler)] #[inline] fn get_tlv() -> usize { @@ -1749,13 +1811,13 @@ pub mod tls { #[cfg(not(parallel_compiler))] thread_local! { - /// A thread local variable which stores a pointer to the current ImplicitCtxt. + /// A thread local variable that stores a pointer to the current `ImplicitCtxt`. static TLV: Cell = Cell::new(0); } /// Sets TLV to `value` during the call to `f`. /// It is restored to its previous value after. - /// This is used to set the pointer to the new ImplicitCtxt. + /// This is used to set the pointer to the new `ImplicitCtxt`. #[cfg(not(parallel_compiler))] #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { @@ -1765,14 +1827,14 @@ pub mod tls { f() } - /// This is used to get the pointer to the current ImplicitCtxt. + /// Gets the pointer to the current `ImplicitCtxt`. #[cfg(not(parallel_compiler))] fn get_tlv() -> usize { TLV.with(|tlv| tlv.get()) } /// This is a callback from libsyntax as it cannot access the implicit state - /// in librustc otherwise + /// in librustc otherwise. fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_opt(|tcx| { if let Some(tcx) = tcx { @@ -1797,7 +1859,7 @@ pub mod tls { }) } - /// Sets up the callbacks from libsyntax on the current thread + /// Sets up the callbacks from libsyntax on the current thread. pub fn with_thread_locals(f: F) -> R where F: FnOnce() -> R { @@ -1822,7 +1884,7 @@ pub mod tls { }) } - /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` + /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`. #[inline] pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R where @@ -1833,19 +1895,19 @@ pub mod tls { }) } - /// Enters GlobalCtxt by setting up libsyntax callbacks and - /// creating a initial TyCtxt and ImplicitCtxt. - /// This happens once per rustc session and TyCtxts only exists + /// Enters `GlobalCtxt` by setting up libsyntax callbacks and + /// creating a initial `TyCtxt` and `ImplicitCtxt`. + /// This happens once per rustc session and `TyCtxt`s only exists /// inside the `f` function. pub fn enter_global<'tcx, F, R>(gcx: &'tcx GlobalCtxt<'tcx>, f: F) -> R where F: FnOnce(TyCtxt<'tcx>) -> R, { - // Update GCX_PTR to indicate there's a GlobalCtxt available + // Update `GCX_PTR` to indicate there's a `GlobalCtxt` available. GCX_PTR.with(|lock| { *lock.lock() = gcx as *const _ as usize; }); - // Set GCX_PTR back to 0 when we exit + // Set `GCX_PTR` back to 0 when we exit. let _on_drop = OnDrop(move || { GCX_PTR.with(|lock| *lock.lock() = 0); }); @@ -1866,12 +1928,12 @@ pub mod tls { } scoped_thread_local! { - /// Stores a pointer to the GlobalCtxt if one is available. - /// This is used to access the GlobalCtxt in the deadlock handler given to Rayon. + /// Stores a pointer to the `GlobalCtxt` if one is available. + /// This is used to access the `GlobalCtxt` in the deadlock handler given to Rayon. pub static GCX_PTR: Lock } - /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local. + /// Creates a `TyCtxt` and `ImplicitCtxt` based on the `GCX_PTR` thread local. /// This is used in the deadlock handler. pub unsafe fn with_global(f: F) -> R where @@ -1893,7 +1955,7 @@ pub mod tls { enter_context(&icx, |_| f(tcx)) } - /// Allows access to the current ImplicitCtxt in a closure if one is available + /// Allows access to the current `ImplicitCtxt` in a closure if one is available. #[inline] pub fn with_context_opt(f: F) -> R where @@ -1903,16 +1965,16 @@ pub mod tls { if context == 0 { f(None) } else { - // We could get a ImplicitCtxt pointer from another thread. - // Ensure that ImplicitCtxt is Sync + // We could get a `ImplicitCtxt` pointer from another thread. + // Ensure that `ImplicitCtxt` is `Sync`. sync::assert_sync::>(); unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) } } } - /// Allows access to the current ImplicitCtxt. - /// Panics if there is no ImplicitCtxt available + /// Allows access to the current `ImplicitCtxt`. + /// Panics if there is no `ImplicitCtxt` available. #[inline] pub fn with_context(f: F) -> R where @@ -1921,11 +1983,11 @@ pub mod tls { with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls"))) } - /// Allows access to the current ImplicitCtxt whose tcx field has the same global - /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt - /// with the same 'tcx lifetime as the TyCtxt passed in. - /// This will panic if you pass it a TyCtxt which has a different global interner from - /// the current ImplicitCtxt's tcx field. + /// Allows access to the current `ImplicitCtxt` whose tcx field has the same global + /// interner as the tcx argument passed in. This means the closure is given an `ImplicitCtxt` + /// with the same `'tcx` lifetime as the `TyCtxt` passed in. + /// This will panic if you pass it a `TyCtxt` which has a different global interner from + /// the current `ImplicitCtxt`'s `tcx` field. #[inline] pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R where @@ -1940,8 +2002,8 @@ pub mod tls { }) } - /// Allows access to the TyCtxt in the current ImplicitCtxt. - /// Panics if there is no ImplicitCtxt available + /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`. + /// Panics if there is no `ImplicitCtxt` available. #[inline] pub fn with(f: F) -> R where @@ -1950,8 +2012,8 @@ pub mod tls { with_context(|context| f(context.tcx)) } - /// Allows access to the TyCtxt in the current ImplicitCtxt. - /// The closure is passed None if there is no ImplicitCtxt available + /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`. + /// The closure is passed None if there is no `ImplicitCtxt` available. #[inline] pub fn with_opt(f: F) -> R where @@ -1963,7 +2025,7 @@ pub mod tls { macro_rules! sty_debug_print { ($ctxt: expr, $($variant: ident),*) => {{ - // curious inner module to allow variant names to be used as + // Curious inner module to allow variant names to be used as // variable names. #[allow(non_snake_case)] mod inner { @@ -2076,7 +2138,7 @@ impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Borrow> for Interned<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.sty @@ -2237,9 +2299,9 @@ slice_interners!( projs: _intern_projs(ProjectionKind) ); -// This isn't a perfect fit: CanonicalVarInfo slices are always +// This isn't a perfect fit: `CanonicalVarInfo` slices are always // allocated in the global arena, so this `intern_method!` macro is -// overly general. But we just return false for the code that checks +// overly general. However, we just return `false` for the code that checks // whether they belong in the thread-local arena, so no harm done, and // seems better than open-coding the rest. intern_method! { @@ -2291,7 +2353,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_fn_ptr(converted_sig) } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { self.interners.intern_ty(st) @@ -2338,7 +2400,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside + // Take a copy of substs so that we own the vectors inside. self.mk_ty(Adt(def, substs)) } @@ -2370,13 +2432,19 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); + let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem, None); self.mk_generic_adt(def_id, ty) } + #[inline] + pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem) -> Option> { + let def_id = self.lang_items().require(item).ok()?; + Some(self.mk_generic_adt(def_id, ty)) + } + #[inline] pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem); + let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None); self.mk_generic_adt(def_id, ty) } @@ -2566,10 +2634,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - #[inline] - pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_ty_param(0, kw::SelfUpper.as_interned_str()) - } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> { match param.kind { @@ -2885,6 +2949,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(id, LOCAL_CRATE); tcx.arena.alloc(middle::lang_items::collect(tcx)) }; + providers.diagnostic_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + middle::diagnostic_items::collect(tcx) + }; + providers.all_diagnostic_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + middle::diagnostic_items::collect_all(tcx) + }; providers.maybe_unused_trait_import = |tcx, id| { tcx.maybe_unused_trait_imports.contains(&id) }; diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 4a72794b61..125c48f5f3 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; use syntax::ast; +use syntax::errors::pluralise; use errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; @@ -46,6 +47,8 @@ pub enum TypeError<'tcx> { ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), + + IntrinsicCast, } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -80,12 +83,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } }; - macro_rules! pluralise { - ($x:expr) => { - if $x != 1 { "s" } else { "" } - }; - } - match *self { CyclicTy(_) => write!(f, "cyclic type of infinite size"), Mismatch => write!(f, "types differ"), @@ -179,6 +176,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ConstMismatch(ref values) => { write!(f, "expected `{}`, found `{}`", values.expected, values.found) } + IntrinsicCast => { + write!(f, "cannot coerce intrinsics to function pointers") + } } } } @@ -195,7 +195,9 @@ impl<'tcx> ty::TyS<'tcx> { ty::Array(_, n) => { let n = tcx.lift_to_global(&n).unwrap(); match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { - Some(n) => format!("array of {} elements", n).into(), + Some(n) => { + format!("array of {} element{}", n, pluralise!(n)).into() + } None => "array".into(), } } @@ -239,13 +241,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), ty::Projection(_) => "associated type".into(), ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), - ty::Param(ref p) => { - if p.is_self() { - "Self".into() - } else { - "type parameter".into() - } - } + ty::Param(_) => "type parameter".into(), ty::Opaque(..) => "opaque type".into(), ty::Error => "type error".into(), } @@ -253,13 +249,15 @@ impl<'tcx> ty::TyS<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - pub fn note_and_explain_type_err(self, - db: &mut DiagnosticBuilder<'_>, - err: &TypeError<'tcx>, - sp: Span) { + pub fn note_and_explain_type_err( + self, + db: &mut DiagnosticBuilder<'_>, + err: &TypeError<'tcx>, + sp: Span, + ) { use self::TypeError::*; - match err.clone() { + match err { Sorts(values) => { let expected_str = values.expected.sort_string(self); let found_str = values.found.sort_string(self); @@ -267,10 +265,20 @@ impl<'tcx> TyCtxt<'tcx> { db.note("no two closures, even if identical, have the same type"); db.help("consider boxing your closure and/or using it as a trait object"); } - if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) = - (&values.found.sty, &values.expected.sty) // Issue #53280 - { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) { + if expected_str == found_str && expected_str == "opaque type" { // Issue #63167 + db.note("distinct uses of `impl Trait` result in different opaque types"); + let e_str = values.expected.to_string(); + let f_str = values.found.to_string(); + if &e_str == &f_str && &e_str == "impl std::future::Future" { + // FIXME: use non-string based check. + db.help("if both `Future`s have the same `Output` type, consider \ + `.await`ing on both of them"); + } + } + match (&values.expected.sty, &values.found.sty) { + (ty::Float(_), ty::Infer(ty::IntVar(_))) => if let Ok( // Issue #53280 + snippet, + ) = self.sess.source_map().span_to_snippet(sp) { if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') { db.span_suggestion( sp, @@ -279,8 +287,96 @@ impl<'tcx> TyCtxt<'tcx> { Applicability::MachineApplicable ); } + }, + (ty::Param(_), ty::Param(_)) => { + db.note("a type parameter was expected, but a different one was found; \ + you might be missing a type parameter or trait bound"); + db.note("for more information, visit \ + https://doc.rust-lang.org/book/ch10-02-traits.html\ + #traits-as-parameters"); + } + (ty::Projection(_), ty::Projection(_)) => { + db.note("an associated type was expected, but a different one was found"); + } + (ty::Param(_), ty::Projection(_)) | (ty::Projection(_), ty::Param(_)) => { + db.note("you might be missing a type parameter or trait bound"); + } + (ty::Param(_), _) | (_, ty::Param(_)) => { + db.help("type parameters must be constrained to match other types"); + if self.sess.teach(&db.get_code().unwrap()) { + db.help("given a type parameter `T` and a method `foo`: +``` +trait Trait { fn foo(&self) -> T; } +``` +the only ways to implement method `foo` are: +- constrain `T` with an explicit type: +``` +impl Trait for X { + fn foo(&self) -> String { String::new() } +} +``` +- add a trait bound to `T` and call a method on that trait that returns `Self`: +``` +impl Trait for X { + fn foo(&self) -> T { ::default() } +} +``` +- change `foo` to return an argument of type `T`: +``` +impl Trait for X { + fn foo(&self, x: T) -> T { x } +} +```"); + } + db.note("for more information, visit \ + https://doc.rust-lang.org/book/ch10-02-traits.html\ + #traits-as-parameters"); + } + (ty::Projection(_), _) => { + db.note(&format!( + "consider constraining the associated type `{}` to `{}` or calling a \ + method that returns `{}`", + values.expected, + values.found, + values.expected, + )); + if self.sess.teach(&db.get_code().unwrap()) { + db.help("given an associated type `T` and a method `foo`: +``` +trait Trait { + type T; + fn foo(&self) -> Self::T; +} +``` +the only way of implementing method `foo` is to constrain `T` with an explicit associated type: +``` +impl Trait for X { + type T = String; + fn foo(&self) -> Self::T { String::new() } +} +```"); + } + db.note("for more information, visit \ + https://doc.rust-lang.org/book/ch19-03-advanced-traits.html"); + } + (_, ty::Projection(_)) => { + db.note(&format!( + "consider constraining the associated type `{}` to `{}`", + values.found, + values.expected, + )); + db.note("for more information, visit \ + https://doc.rust-lang.org/book/ch19-03-advanced-traits.html"); } + _ => {} } + debug!( + "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})", + values.expected, + values.expected.sty, + values.found, + values.found.sty, + ); }, CyclicTy(ty) => { // Watch out for various cases of cyclic types and try to explain. diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 411b18e043..b2d74f963b 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -1,5 +1,5 @@ use crate::ty::subst::{SubstsRef, UnpackedKind}; -use crate::ty::{self, Ty, TypeFlags, TypeFoldable, InferConst}; +use crate::ty::{self, Ty, TypeFlags, InferConst}; use crate::mir::interpret::ConstValue; #[derive(Debug)] @@ -18,7 +18,7 @@ impl FlagComputation { } } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] pub fn for_sty(st: &ty::TyKind<'_>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_sty(st); @@ -62,7 +62,7 @@ impl FlagComputation { } // otherwise, this binder captures nothing } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] fn add_sty(&mut self, st: &ty::TyKind<'_>) { match st { &ty::Bool | @@ -86,13 +86,9 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_TY_ERR) } - &ty::Param(ref p) => { + &ty::Param(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - if p.is_self() { - self.add_flags(TypeFlags::HAS_SELF); - } else { - self.add_flags(TypeFlags::HAS_PARAMS); - } + self.add_flags(TypeFlags::HAS_PARAMS); } &ty::Generator(_, ref substs, _) => { @@ -143,11 +139,6 @@ impl FlagComputation { } &ty::Projection(ref data) => { - // currently we can't normalize projections that - // include bound regions, so track those separately. - if !data.has_escaping_bound_vars() { - self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); - } self.add_flags(TypeFlags::HAS_PROJECTION); self.add_projection_ty(data); } @@ -243,7 +234,7 @@ impl FlagComputation { match c.val { ConstValue::Unevaluated(_, substs) => { self.add_substs(substs); - self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_PROJECTION); }, ConstValue::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index ab7df8e4e8..1e08ae4595 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -39,8 +39,8 @@ use std::collections::BTreeMap; use std::fmt; use crate::util::nodemap::FxHashSet; -/// The TypeFoldable trait is implemented for every type that can be folded. -/// Basically, every type that has a corresponding method in TypeFolder. +/// This trait is implemented for every type that can be folded. +/// Basically, every type that has a corresponding method in `TypeFolder`. /// /// To implement this conveniently, use the /// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`. @@ -85,9 +85,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_param_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PARAMS) } - fn has_self_ty(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_SELF) - } fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 4453624fa4..63cc60d80a 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -4,20 +4,20 @@ use rustc::hir::CRATE_HIR_ID; use crate::ty::context::TyCtxt; use crate::ty::{DefId, DefIdTree}; -/// Represents a forest of DefIds closed under the ancestor relation. That is, -/// if a DefId representing a module is contained in the forest then all -/// DefIds defined in that module or submodules are also implicitly contained +/// Represents a forest of `DefId`s closed under the ancestor relation. That is, +/// if a `DefId` representing a module is contained in the forest then all +/// `DefId`s defined in that module or submodules are also implicitly contained /// in the forest. /// /// This is used to represent a set of modules in which a type is visibly /// uninhabited. #[derive(Clone)] pub struct DefIdForest { - /// The minimal set of DefIds required to represent the whole set. - /// If A and B are DefIds in the DefIdForest, and A is a descendant - /// of B, then only B will be in root_ids. - /// We use a SmallVec here because (for its use for caching inhabitedness) - /// its rare that this will contain even two ids. + /// The minimal set of `DefId`s required to represent the whole set. + /// If A and B are DefIds in the `DefIdForest`, and A is a descendant + /// of B, then only B will be in `root_ids`. + /// We use a `SmallVec` here because (for its use for caching inhabitedness) + /// its rare that this will contain even two IDs. root_ids: SmallVec<[DefId; 1]>, } @@ -37,7 +37,7 @@ impl<'tcx> DefIdForest { DefIdForest::from_id(crate_id) } - /// Creates a forest containing a DefId and all its descendants. + /// Creates a forest containing a `DefId` and all its descendants. pub fn from_id(id: DefId) -> DefIdForest { let mut root_ids = SmallVec::new(); root_ids.push(id); diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 2b32916566..1a0e351733 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -1,3 +1,5 @@ +pub use self::def_id_forest::DefIdForest; + use crate::ty::context::TyCtxt; use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use crate::ty::{DefId, SubstsRef}; @@ -5,12 +7,10 @@ use crate::ty::{AdtKind, Visibility}; use crate::ty::TyKind::*; use crate::ty; -pub use self::def_id_forest::DefIdForest; - mod def_id_forest; -// The methods in this module calculate DefIdForests of modules in which a -// AdtDef/VariantDef/FieldDef is visibly uninhabited. +// The methods in this module calculate `DefIdForest`s of modules in which a +// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited. // // # Example // ```rust @@ -36,24 +36,25 @@ mod def_id_forest; // y: c::AlsoSecretlyUninhabited, // } // ``` -// In this code, the type Foo will only be visibly uninhabited inside the -// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will -// return the forest of modules {b, c->d} (represented in a DefIdForest by the -// set {b, c}) +// In this code, the type `Foo` will only be visibly uninhabited inside the +// modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will +// return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the +// set {`b`, `c`}). // -// We need this information for pattern-matching on Foo or types that contain -// Foo. +// We need this information for pattern-matching on `Foo` or types that contain +// `Foo`. // // # Example // ```rust // let foo_result: Result = ... ; // let Ok(t) = foo_result; // ``` -// This code should only compile in modules where the uninhabitedness of Foo is +// This code should only compile in modules where the uninhabitedness of `Foo` is // visible. impl<'tcx> TyCtxt<'tcx> { /// Checks whether a type is visibly uninhabited from a particular module. + /// /// # Example /// ```rust /// enum Void {} @@ -91,7 +92,7 @@ impl<'tcx> TyCtxt<'tcx> { /// visible. pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { // To check whether this type is uninhabited at all (not just from the - // given node) you could check whether the forest is empty. + // given node), you could check whether the forest is empty. // ``` // forest.is_empty() // ``` @@ -108,7 +109,7 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'tcx> AdtDef { - /// Calculate the forest of DefIds from which this adt is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { // Non-exhaustive ADTs from other crates are always considered inhabited. if self.is_variant_list_non_exhaustive() && !self.did.is_local() { @@ -122,7 +123,7 @@ impl<'tcx> AdtDef { } impl<'tcx> VariantDef { - /// Calculate the forest of DefIds from which this variant is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited. pub fn uninhabited_from( &self, tcx: TyCtxt<'tcx>, @@ -148,7 +149,7 @@ impl<'tcx> VariantDef { } impl<'tcx> FieldDef { - /// Calculate the forest of DefIds from which this field is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this field is visibly uninhabited. fn uninhabited_from( &self, tcx: TyCtxt<'tcx>, @@ -159,7 +160,7 @@ impl<'tcx> FieldDef { self.ty(tcx, substs).uninhabited_from(tcx) }; // FIXME(canndrew): Currently enum fields are (incorrectly) stored with - // Visibility::Invisible so we need to override self.vis if we're + // `Visibility::Invisible` so we need to override `self.vis` if we're // dealing with an enum. if is_enum { data_uninhabitedness() @@ -178,7 +179,7 @@ impl<'tcx> FieldDef { } impl<'tcx> TyS<'tcx> { - /// Calculate the forest of DefIds from which this type is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest { match self.sty { Adt(def, substs) => def.uninhabited_from(tcx, substs), diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 457d018f01..a26fa72f33 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -298,8 +298,9 @@ impl<'tcx> Instance<'tcx> { ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); let fn_sig = tcx.fn_sig(def_id); - let is_vtable_shim = - fn_sig.inputs().skip_binder().len() > 0 && fn_sig.input(0).skip_binder().is_self(); + let is_vtable_shim = fn_sig.inputs().skip_binder().len() > 0 + && fn_sig.input(0).skip_binder().is_param(0) + && tcx.generics_of(def_id).has_self; if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); Some(Instance { @@ -326,7 +327,7 @@ impl<'tcx> Instance<'tcx> { } pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { - let def_id = tcx.require_lang_item(DropInPlaceFnLangItem); + let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None); let substs = tcx.intern_substs(&[ty.into()]); Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap() } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 19c753bc30..e52feea162 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -127,6 +127,7 @@ impl IntegerExt for Integer { pub trait PrimitiveExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; + fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; } impl PrimitiveExt for Primitive { @@ -138,6 +139,16 @@ impl PrimitiveExt for Primitive { Pointer => tcx.mk_mut_ptr(tcx.mk_unit()), } } + + /// Return an *integer* type matching this primitive. + /// Useful in particular when dealing with enum discriminants. + fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match *self { + Int(i, signed) => i.to_ty(tcx, signed), + Pointer => tcx.types.usize, + Float(..) => bug!("floats do not have an int type"), + } + } } /// The first half of a fat pointer. @@ -273,14 +284,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { repr: &ReprOptions, kind: StructKind) -> Result> { let dl = self.data_layout(); - let packed = repr.packed(); - if packed && repr.align > 0 { + let pack = repr.pack; + if pack.is_some() && repr.align.is_some() { bug!("struct cannot be packed and aligned"); } - let pack = Align::from_bytes(repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align @@ -303,7 +312,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let optimizing = &mut inverse_memory_index[..end]; let field_align = |f: &TyLayout<'_>| { - if packed { f.align.abi.min(pack) } else { f.align.abi } + if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } }; match kind { StructKind::AlwaysSized | @@ -334,7 +343,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut largest_niche_available = 0; if let StructKind::Prefixed(prefix_size, prefix_align) = kind { - let prefix_align = if packed { + let prefix_align = if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align @@ -355,7 +364,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Invariant: offset < dl.obj_size_bound() <= 1<<61 - let field_align = if packed { + let field_align = if let Some(pack) = pack { field.align.min(AbiAndPrefAlign::new(pack)) } else { field.align @@ -379,10 +388,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .ok_or(LayoutError::SizeOverflow(ty))?; } - if repr.align > 0 { - let repr_align = repr.align as u64; - align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); - debug!("univariant repr_align: {:?}", repr_align); + if let Some(repr_align) = repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } debug!("univariant min_size: {:?}", offset); @@ -730,23 +737,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }).collect::, _>>()?; if def.is_union() { - let packed = def.repr.packed(); - if packed && def.repr.align > 0 { - bug!("Union cannot be packed and aligned"); + if def.repr.pack.is_some() && def.repr.align.is_some() { + bug!("union cannot be packed and aligned"); } - let pack = Align::from_bytes(def.repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if def.repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - if def.repr.align > 0 { - let repr_align = def.repr.align as u64; - align = align.max( - AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); + if let Some(repr_align) = def.repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -755,13 +757,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let index = VariantIdx::new(0); for field in &variants[index] { assert!(!field.is_unsized()); - - let field_align = if packed { - field.align.min(AbiAndPrefAlign::new(pack)) - } else { - field.align - }; - align = align.max(field_align); + align = align.max(field.align); // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { @@ -796,6 +792,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size = cmp::max(size, field.size); } + if let Some(pack) = def.repr.pack { + align = align.min(AbiAndPrefAlign::new(pack)); + } + return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), @@ -1601,7 +1601,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // resulting from the final codegen session. if layout.ty.has_param_types() || - layout.ty.has_self_ty() || !self.param_env.caller_bounds.is_empty() { return; @@ -1638,7 +1637,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let adt_kind = adt_def.adt_kind(); - let adt_packed = adt_def.repr.packed(); + let adt_packed = adt_def.repr.pack.is_some(); let build_variant_info = |n: Option, flds: &[ast::Name], @@ -1767,7 +1766,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); match tail.sty { ty::Param(_) | ty::Projection(_) => { - debug_assert!(tail.has_param_types() || tail.has_self_ty()); + debug_assert!(tail.has_param_types()); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(&tail) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9d563e290d..f879693eee 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -33,6 +33,7 @@ use arena::SyncDroplessArena; use crate::session::DataTypeKind; use rustc_serialize::{self, Encodable, Encoder}; +use rustc_target::abi::Align; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -45,7 +46,7 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::ExpnId; -use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; use smallvec; @@ -75,7 +76,7 @@ pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; pub use self::context::{TyCtxt, FreeRegionInfo, AllArenas, tls, keep_local}; -pub use self::context::{Lift, TypeckTables, CtxtInterners, GlobalCtxt}; +pub use self::context::{Lift, GeneratorInteriorTypeCause, TypeckTables, CtxtInterners, GlobalCtxt}; pub use self::context::{ UserTypeAnnotationIndex, UserType, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy, @@ -414,61 +415,53 @@ pub struct CReaderCacheKey { bitflags! { pub struct TypeFlags: u32 { const HAS_PARAMS = 1 << 0; - const HAS_SELF = 1 << 1; - const HAS_TY_INFER = 1 << 2; - const HAS_RE_INFER = 1 << 3; - const HAS_RE_PLACEHOLDER = 1 << 4; + const HAS_TY_INFER = 1 << 1; + const HAS_RE_INFER = 1 << 2; + const HAS_RE_PLACEHOLDER = 1 << 3; /// Does this have any `ReEarlyBound` regions? Used to /// determine whether substitition is required, since those /// represent regions that are bound in a `ty::Generics` and /// hence may be substituted. - const HAS_RE_EARLY_BOUND = 1 << 5; + const HAS_RE_EARLY_BOUND = 1 << 4; /// Does this have any region that "appears free" in the type? /// Basically anything but `ReLateBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 6; + const HAS_FREE_REGIONS = 1 << 5; /// Is an error type reachable? - const HAS_TY_ERR = 1 << 7; - const HAS_PROJECTION = 1 << 8; + const HAS_TY_ERR = 1 << 6; + const HAS_PROJECTION = 1 << 7; // FIXME: Rename this to the actual property since it's used for generators too - const HAS_TY_CLOSURE = 1 << 9; + const HAS_TY_CLOSURE = 1 << 8; /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = 1 << 10; + const HAS_FREE_LOCAL_NAMES = 1 << 9; /// Present if the type belongs in a local type context. /// Only set for Infer other than Fresh. - const KEEP_IN_LOCAL_TCX = 1 << 11; - - // Is there a projection that does not involve a bound region? - // Currently we can't normalize projections w/ bound regions. - const HAS_NORMALIZABLE_PROJECTION = 1 << 12; + const KEEP_IN_LOCAL_TCX = 1 << 10; /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 13; + const HAS_RE_LATE_BOUND = 1 << 11; - const HAS_TY_PLACEHOLDER = 1 << 14; + const HAS_TY_PLACEHOLDER = 1 << 12; - const HAS_CT_INFER = 1 << 15; - const HAS_CT_PLACEHOLDER = 1 << 16; + const HAS_CT_INFER = 1 << 13; + const HAS_CT_PLACEHOLDER = 1 << 14; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | - TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits; /// Flags representing the nominal content of a type, /// computed by FlagsComputation. If you add a new nominal /// flag, it should be added here too. const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | - TypeFlags::HAS_SELF.bits | TypeFlags::HAS_TY_INFER.bits | TypeFlags::HAS_RE_INFER.bits | - TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_RE_PLACEHOLDER.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits | TypeFlags::HAS_FREE_REGIONS.bits | @@ -479,11 +472,12 @@ bitflags! { TypeFlags::KEEP_IN_LOCAL_TCX.bits | TypeFlags::HAS_RE_LATE_BOUND.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | + TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits; } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] pub struct TyS<'tcx> { pub sty: TyKind<'tcx>, pub flags: TypeFlags, @@ -587,6 +581,7 @@ impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { } } +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")] pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {} @@ -595,7 +590,7 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for Ty<'tcx> {} pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>; extern { - /// A dummy type used to force List to by unsized without requiring fat pointers + /// A dummy type used to force `List` to by unsized without requiring fat pointers. type OpaqueListContents; } @@ -1734,7 +1729,6 @@ impl<'tcx> ParamEnv<'tcx> { if value.has_placeholders() || value.needs_infer() || value.has_param_types() - || value.has_self_ty() { ParamEnvAnd { param_env: self, @@ -1944,9 +1938,15 @@ pub struct FieldDef { pub vis: Visibility, } -/// The definition of an abstract data type -- a struct or enum. +/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`. /// /// These are all interned (by `intern_adt_def`) into the `adt_defs` table. +/// +/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt]. +/// This is slightly wrong because `union`s are not ADTs. +/// Moreover, Rust only allows recursive data types through indirection. +/// +/// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type pub struct AdtDef { /// `DefId` of the struct, enum or union item. pub did: DefId, @@ -2065,8 +2065,8 @@ impl_stable_hash_for!(struct ReprFlags { #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { pub int: Option, - pub align: u32, - pub pack: u32, + pub align: Option, + pub pack: Option, pub flags: ReprFlags, } @@ -2081,18 +2081,19 @@ impl ReprOptions { pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let mut flags = ReprFlags::empty(); let mut size = None; - let mut max_align = 0; - let mut min_pack = 0; + let mut max_align: Option = None; + let mut min_pack: Option = None; for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess.parse_sess, attr) { flags.insert(match r { attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { - min_pack = if min_pack > 0 { - cmp::min(pack, min_pack) + let pack = Align::from_bytes(pack as u64).unwrap(); + min_pack = Some(if let Some(min_pack) = min_pack { + min_pack.min(pack) } else { pack - }; + }); ReprFlags::empty() }, attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, @@ -2102,7 +2103,7 @@ impl ReprOptions { ReprFlags::empty() }, attr::ReprAlign(align) => { - max_align = cmp::max(align, max_align); + max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); ReprFlags::empty() }, }); @@ -2121,7 +2122,7 @@ impl ReprOptions { #[inline] pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } #[inline] - pub fn packed(&self) -> bool { self.pack > 0 } + pub fn packed(&self) -> bool { self.pack.is_some() } #[inline] pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) } #[inline] @@ -2141,8 +2142,12 @@ impl ReprOptions { /// Returns `true` if this `#[repr()]` should inhibit struct field reordering /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr()`. pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || - self.int.is_some() + if let Some(pack) = self.pack { + if pack.bytes() == 1 { + return true; + } + } + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. @@ -2596,12 +2601,12 @@ impl<'tcx> ClosureKind { pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId { match *self { - ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), + ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem, None), ClosureKind::FnMut => { - tcx.require_lang_item(FnMutTraitLangItem) + tcx.require_lang_item(FnMutTraitLangItem, None) } ClosureKind::FnOnce => { - tcx.require_lang_item(FnOnceTraitLangItem) + tcx.require_lang_item(FnOnceTraitLangItem, None) } } } @@ -2792,6 +2797,10 @@ impl<'tcx> TyCtxt<'tcx> { }) } + pub fn opt_item_name(self, def_id: DefId) -> Option { + self.hir().as_local_hir_id(def_id).and_then(|hir_id| self.hir().get(hir_id).ident()) + } + pub fn opt_associated_item(self, def_id: DefId) -> Option { let is_associated_item = if let Some(hir_id) = self.hir().as_local_hir_id(def_id) { match self.hir().get(hir_id) { @@ -2895,6 +2904,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> Option { + // If either trait impl references an error, they're allowed to overlap, + // as one of them essentially doesn't exist. + if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) || + self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) { + return Some(ImplOverlapKind::Permitted); + } + let is_legit = if self.features().overlapping_marker_traits { let trait1_is_empty = self.impl_trait_ref(def_id1) .map_or(false, |trait_ref| { @@ -3337,6 +3353,22 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } +/// Check if a function is async. +fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(|| { + bug!("asyncness: expected local `DefId`, got `{:?}`", def_id) + }); + + let node = tcx.hir().get(hir_id); + + let fn_like = hir::map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| { + bug!("asyncness: expected fn-like node but got `{:?}`", def_id); + }); + + fn_like.asyncness() +} + + pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); @@ -3344,6 +3376,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { + asyncness, associated_item, associated_item_def_ids, adt_sized_constraint, @@ -3387,10 +3420,6 @@ impl SymbolName { name: InternedString::intern(name) } } - - pub fn as_str(&self) -> LocalInternedString { - self.name.as_str() - } } impl fmt::Display for SymbolName { diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 092e7c6f3f..50789bf621 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -27,7 +27,8 @@ pub trait Print<'tcx, P> { /// which the associated types allow passing through the methods. /// /// For pretty-printing/formatting in particular, see `PrettyPrinter`. -// FIXME(eddyb) find a better name, this is more general than "printing". +// +// FIXME(eddyb) find a better name; this is more general than "printing". pub trait Printer<'tcx>: Sized { type Error; @@ -46,6 +47,7 @@ pub trait Printer<'tcx>: Sized { ) -> Result { self.default_print_def_path(def_id, substs) } + fn print_impl_path( self, impl_def_id: DefId, @@ -80,6 +82,7 @@ pub trait Printer<'tcx>: Sized { self, cnum: CrateNum, ) -> Result; + fn path_qualified( self, self_ty: Ty<'tcx>, @@ -93,11 +96,13 @@ pub trait Printer<'tcx>: Sized { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result; + fn path_append( self, print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, ) -> Result; + fn path_generic_args( self, print_prefix: impl FnOnce(Self) -> Result, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index bf6741dde4..d99580116e 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -8,10 +8,11 @@ use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; use crate::ty::subst::{Kind, Subst, UnpackedKind}; use crate::ty::layout::{Integer, IntegerExt, Size}; use crate::mir::interpret::{ConstValue, sign_extend, Scalar, truncate}; -use syntax::ast; + use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_target::spec::abi::Abi; +use syntax::ast; use syntax::attr::{SignedInt, UnsignedInt}; use syntax::symbol::{kw, InternedString}; @@ -194,7 +195,7 @@ pub trait PrettyPrinter<'tcx>: value.skip_binder().print(self) } - /// Print comma-separated elements. + /// Prints comma-separated elements. fn comma_sep(mut self, mut elems: impl Iterator) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error>, @@ -209,14 +210,14 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - /// Print `<...>` around what `f` prints. + /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, f: impl FnOnce(Self) -> Result, ) -> Result; - /// Return `true` if the region should be printed in - /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`. + /// Returns `true` if the region should be printed in + /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`. /// This is typically the case for all non-`'_` regions. fn region_should_not_be_omitted( &self, @@ -226,7 +227,7 @@ pub trait PrettyPrinter<'tcx>: // Defaults (should not be overriden): /// If possible, this returns a global path resolving to `def_id` that is visible - /// from at least one local module and returns true. If the crate defining `def_id` is + /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path( self, @@ -267,11 +268,11 @@ pub trait PrettyPrinter<'tcx>: // In local mode, when we encounter a crate other than // LOCAL_CRATE, execution proceeds in one of two ways: // - // 1. for a direct dependency, where user added an + // 1. For a direct dependency, where user added an // `extern crate` manually, we put the `extern // crate` as the parent. So you wind up with // something relative to the current crate. - // 2. for an extern inferred from a path or an indirect crate, + // 2. For an extern inferred from a path or an indirect crate, // where there is no explicit `extern crate`, we just prepend // the crate name. match self.tcx().extern_crate(def_id) { @@ -304,13 +305,13 @@ pub trait PrettyPrinter<'tcx>: let mut cur_def_key = self.tcx().def_key(def_id); debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); - // For a constructor we want the name of its parent rather than . + // For a constructor, we want the name of its parent rather than . match cur_def_key.disambiguated_data.data { DefPathData::Ctor => { let parent = DefId { krate: def_id.krate, index: cur_def_key.parent - .expect("DefPathData::Ctor/VariantData missing a parent"), + .expect("`DefPathData::Ctor` / `VariantData` missing a parent"), }; cur_def_key = self.tcx().def_key(parent); @@ -630,7 +631,7 @@ pub trait PrettyPrinter<'tcx>: sep = ", "; } } else { - // cross-crate closure types should only be + // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); let mut sep = " "; @@ -673,7 +674,7 @@ pub trait PrettyPrinter<'tcx>: sep = ", "; } } else { - // cross-crate closure types should only be + // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); let mut sep = " "; @@ -944,10 +945,16 @@ pub trait PrettyPrinter<'tcx>: .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) }, (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - Some(&data.bytes[start..end]) + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active slice reference here). We don't use this + // result to affect interpreter execution. + Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) }, (ConstValue::Slice { data, start, end }, ty::Str) => { - let slice = &data.bytes[start..end]; + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); let s = ::std::str::from_utf8(slice) .expect("non utf8 str from miri"); p!(write("{:?}", s)); @@ -1167,6 +1174,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } Ok(self) } + fn path_qualified( mut self, self_ty: Ty<'tcx>, @@ -1195,6 +1203,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { self.empty_path = false; Ok(self) } + fn path_append( mut self, print_prefix: impl FnOnce(Self) -> Result, @@ -1232,6 +1241,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(self) } + fn path_generic_args( mut self, print_prefix: impl FnOnce(Self) -> Result, diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 00871a1cbf..c20e758688 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -5,9 +5,6 @@ use crate::hir::map::definitions::DefPathHash; use crate::ich::{CachingSourceMapView, Fingerprint}; use crate::mir::{self, interpret}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque, - SpecializedDecoder, SpecializedEncoder, - UseSpecializedDecodable, UseSpecializedEncodable}; use crate::session::{CrateDisambiguator, Session}; use crate::ty::{self, Ty}; use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; @@ -19,35 +16,38 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_serialize::{ + Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder, + UseSpecializedDecodable, UseSpecializedEncodable, opaque, +}; use std::mem; -use syntax::ast::NodeId; +use syntax::ast::{Ident, NodeId}; use syntax::source_map::{SourceMap, StableSourceFileId}; use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile}; -use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnInfo}; +use syntax_pos::hygiene::{ExpnId, SyntaxContext}; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; -const TAG_NO_EXPANSION_INFO: u8 = 0; -const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1; -const TAG_EXPANSION_INFO_INLINE: u8 = 2; +const TAG_NO_EXPN_DATA: u8 = 0; +const TAG_EXPN_DATA_SHORTHAND: u8 = 1; +const TAG_EXPN_DATA_INLINE: u8 = 2; const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; -/// `OnDiskCache` provides an interface to incr. comp. data cached from the +/// Provides an interface to incremental compilation data cached from the /// previous compilation session. This data will eventually include the results /// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and /// any diagnostics that have been emitted during a query. pub struct OnDiskCache<'sess> { - // The complete cache data in serialized form. serialized_data: Vec, - // This field collects all Diagnostics emitted during the current - // compilation session. + // Collects all `Diagnostic`s emitted during the current compilation + // session. current_diagnostics: Lock>>, prev_cnums: Vec<(u32, String, CrateDisambiguator)>, @@ -56,9 +56,9 @@ pub struct OnDiskCache<'sess> { source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap, - // These two fields caches that are populated lazily during decoding. + // Caches that are populated lazily during decoding. file_index_to_file: Lock>>, - synthetic_expansion_infos: Lock>, + synthetic_syntax_contexts: Lock>, // A map from dep-node to the position of the cached query result in // `serialized_data`. @@ -78,7 +78,7 @@ struct Footer { prev_cnums: Vec<(u32, String, CrateDisambiguator)>, query_result_index: EncodedQueryResultIndex, diagnostics_index: EncodedQueryResultIndex, - // the location of all allocations + // The location of all allocations. interpret_alloc_index: Vec, } @@ -104,28 +104,28 @@ impl AbsoluteBytePos { } impl<'sess> OnDiskCache<'sess> { - /// Creates a new OnDiskCache instance from the serialized data in `data`. - pub fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> OnDiskCache<'sess> { + /// Creates a new `OnDiskCache` instance from the serialized data in `data`. + pub fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> Self { debug_assert!(sess.opts.incremental.is_some()); - // Wrapping in a scope so we can borrow `data` + // Wrap in a scope so we can borrow `data`. let footer: Footer = { let mut decoder = opaque::Decoder::new(&data[..], start_pos); - // Decode the *position* of the footer which can be found in the + // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE); - let query_result_index_pos = IntEncodedWithFixedSize::decode(&mut decoder) - .expect("Error while trying to decode query result index position.") + let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder) + .expect("error while trying to decode footer position") .0 as usize; - // Decoder the file footer which contains all the lookup tables, etc. - decoder.set_position(query_result_index_pos); + // Decode the file footer, which contains all the lookup tables, etc. + decoder.set_position(footer_pos); decode_tagged(&mut decoder, TAG_FILE_FOOTER) - .expect("Error while trying to decode query result index position.") + .expect("error while trying to decode footer position") }; - OnDiskCache { + Self { serialized_data: data, file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), @@ -135,13 +135,13 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(), - synthetic_expansion_infos: Default::default(), + synthetic_syntax_contexts: Default::default(), alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index), } } - pub fn new_empty(source_map: &'sess SourceMap) -> OnDiskCache<'sess> { - OnDiskCache { + pub fn new_empty(source_map: &'sess SourceMap) -> Self { + Self { serialized_data: Vec::new(), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), @@ -151,18 +151,18 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: Default::default(), query_result_index: Default::default(), prev_diagnostics_index: Default::default(), - synthetic_expansion_infos: Default::default(), + synthetic_syntax_contexts: Default::default(), alloc_decoding_state: AllocDecodingState::new(Vec::new()), } } pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error> where - E: ty_codec::TyEncoder, + E: TyEncoder, { - // Serializing the DepGraph should not modify it: + // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { - // Allocate SourceFileIndices + // Allocate `SourceFileIndex`es. let (file_to_file_index, file_index_to_stable_id) = { let files = tcx.sess.source_map().files(); let mut file_to_file_index = FxHashMap::with_capacity_and_hasher( @@ -185,7 +185,7 @@ impl<'sess> OnDiskCache<'sess> { encoder, type_shorthands: Default::default(), predicate_shorthands: Default::default(), - expn_info_shorthands: Default::default(), + expn_data_shorthands: Default::default(), interpret_allocs: Default::default(), interpret_allocs_inverse: Vec::new(), source_map: CachingSourceMapView::new(tcx.sess.source_map()), @@ -197,7 +197,7 @@ impl<'sess> OnDiskCache<'sess> { // be in memory, so this should be a cheap operation. tcx.dep_graph.exec_cache_promotions(tcx); - // Encode query results + // Encode query results. let mut query_result_index = EncodedQueryResultIndex::new(); time(tcx.sess, "encode query results", || { @@ -221,29 +221,28 @@ impl<'sess> OnDiskCache<'sess> { Ok(()) })?; - // Encode diagnostics + // Encode diagnostics. let diagnostics_index: EncodedDiagnosticsIndex = self.current_diagnostics.borrow() .iter() - .map(|(dep_node_index, diagnostics)| - { - let pos = AbsoluteBytePos::new(encoder.position()); - // Let's make sure we get the expected type here: - let diagnostics: &EncodedDiagnostics = diagnostics; - let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, diagnostics)?; - - Ok((dep_node_index, pos)) - }) - .collect::>()?; + .map(|(dep_node_index, diagnostics)| { + let pos = AbsoluteBytePos::new(encoder.position()); + // Let's make sure we get the expected type here. + let diagnostics: &EncodedDiagnostics = diagnostics; + let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); + encoder.encode_tagged(dep_node_index, diagnostics)?; + + Ok((dep_node_index, pos)) + }) + .collect::>()?; let interpret_alloc_index = { let mut interpret_alloc_index = Vec::new(); let mut n = 0; loop { let new_n = encoder.interpret_allocs_inverse.len(); - // if we have found new ids, serialize those, too + // If we have found new IDs, serialize those too. if n == new_n { - // otherwise, abort + // Otherwise, abort. break; } interpret_alloc_index.reserve(new_n - n); @@ -263,13 +262,15 @@ impl<'sess> OnDiskCache<'sess> { }; let sorted_cnums = sorted_cnums_including_local_crate(tcx); - let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| { - let crate_name = tcx.original_crate_name(cnum).as_str().to_string(); - let crate_disambiguator = tcx.crate_disambiguator(cnum); - (cnum.as_u32(), crate_name, crate_disambiguator) - }).collect(); - - // Encode the file footer + let prev_cnums: Vec<_> = sorted_cnums.iter() + .map(|&cnum| { + let crate_name = tcx.original_crate_name(cnum).as_str().to_string(); + let crate_disambiguator = tcx.crate_disambiguator(cnum); + (cnum.as_u32(), crate_name, crate_disambiguator) + }) + .collect(); + + // Encode the file footer. let footer_pos = encoder.position() as u64; encoder.encode_tagged(TAG_FILE_FOOTER, &Footer { file_index_to_stable_id, @@ -371,7 +372,7 @@ impl<'sess> OnDiskCache<'sess> { { let pos = index.get(&dep_node_index).cloned()?; - // Initialize the cnum_map using the value from the thread which finishes the closure first + // Initialize `cnum_map` using the value from the thread that finishes the closure first. self.cnum_map.init_nonlocking_same(|| { Self::compute_cnum_map(tcx, &self.prev_cnums[..]) }); @@ -381,25 +382,21 @@ impl<'sess> OnDiskCache<'sess> { opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), source_map: self.source_map, cnum_map: self.cnum_map.get(), + synthetic_syntax_contexts: &self.synthetic_syntax_contexts, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, - synthetic_expansion_infos: &self.synthetic_expansion_infos, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), }; match decode_tagged(&mut decoder, dep_node_index) { - Ok(value) => { - Some(value) - } - Err(e) => { - bug!("Could not decode cached {}: {}", debug_tag, e) - } + Ok(v) => Some(v), + Err(e) => bug!("could not decode cached {}: {}", debug_tag, e), } } - // This function builds mapping from previous-session-CrateNum to - // current-session-CrateNum. There might be CrateNums from the previous - // Session that don't occur in the current one. For these, the mapping + // This function builds mapping from previous-session-`CrateNum` to + // current-session-`CrateNum`. There might be `CrateNum`s from the previous + // `Session` that don't occur in the current one. For these, the mapping // maps to None. fn compute_cnum_map( tcx: TyCtxt<'_>, @@ -432,15 +429,15 @@ impl<'sess> OnDiskCache<'sess> { //- DECODING ------------------------------------------------------------------- -/// A decoder that can read the incr. comp. cache. It is similar to the one -/// we use for crate metadata decoding in that it can rebase spans and -/// eventually will also handle things that contain `Ty` instances. +/// A decoder that can read fro the incr. comp. cache. It is similar to the one +/// we use for crate metadata decoding in that it can rebase spans and eventually +/// will also handle things that contain `Ty` instances. struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, opaque: opaque::Decoder<'a>, source_map: &'a SourceMap, cnum_map: &'a IndexVec>, - synthetic_expansion_infos: &'a Lock>, + synthetic_syntax_contexts: &'a Lock>, file_index_to_file: &'a Lock>>, file_index_to_stable_id: &'a FxHashMap, alloc_decoding_session: AllocDecodingSession<'a>, @@ -458,7 +455,7 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { let stable_id = file_index_to_stable_id[&index]; source_map.source_file_by_stable_id(stable_id) - .expect("Failed to lookup SourceFile in new context.") + .expect("failed to lookup `SourceFile` in new context") }).clone() } } @@ -479,7 +476,7 @@ impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> { } } -// Decode something that was encoded with encode_tagged() and verify that the +// Decodes something that was encoded with `encode_tagged()` and verify that the // tag matches and the correct amount of bytes was read. fn decode_tagged(decoder: &mut D, expected_tag: T) -> Result where @@ -500,7 +497,7 @@ where Ok(value) } -impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { +impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx @@ -534,7 +531,7 @@ impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { } let ty = or_insert_with(self)?; - // This may overwrite the entry, but it should overwrite with the same value + // This may overwrite the entry, but it should overwrite with the same value. tcx.rcache.borrow_mut().insert_same(cache_key, ty); Ok(ty) } @@ -553,7 +550,7 @@ impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { self.cnum_map[cnum].unwrap_or_else(|| { - bug!("Could not find new CrateNum for {:?}", cnum) + bug!("could not find new `CrateNum` for {:?}", cnum) }) } } @@ -586,37 +583,38 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { let lo = file_lo.lines[line_lo - 1] + col_lo; let hi = lo + len; - let expn_info_tag = u8::decode(self)?; + let expn_data_tag = u8::decode(self)?; - // FIXME(mw): This method does not restore `InternalExpnData::parent` or + // FIXME(mw): This method does not restore `ExpnData::parent` or // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things // don't seem to be used after HIR lowering, so everything should be fine - // as long as incremental compilation does not kick in before that. - let location = || Span::new(lo, hi, SyntaxContext::empty()); - let recover_from_expn_info = |this: &Self, expn_info, pos| { - let span = location().fresh_expansion(ExpnId::root(), expn_info); - this.synthetic_expansion_infos.borrow_mut().insert(pos, span.ctxt()); + // until we want incremental compilation to serialize Spans that we need + // full hygiene information for. + let location = || Span::with_root_ctxt(lo, hi); + let recover_from_expn_data = |this: &Self, expn_data, transparency, pos| { + let span = location().fresh_expansion_with_transparency(expn_data, transparency); + this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt()); span }; - Ok(match expn_info_tag { - TAG_NO_EXPANSION_INFO => { + Ok(match expn_data_tag { + TAG_NO_EXPN_DATA => { location() } - TAG_EXPANSION_INFO_INLINE => { - let expn_info = Decodable::decode(self)?; - recover_from_expn_info( - self, expn_info, AbsoluteBytePos::new(self.opaque.position()) + TAG_EXPN_DATA_INLINE => { + let (expn_data, transparency) = Decodable::decode(self)?; + recover_from_expn_data( + self, expn_data, transparency, AbsoluteBytePos::new(self.opaque.position()) ) } - TAG_EXPANSION_INFO_SHORTHAND => { + TAG_EXPN_DATA_SHORTHAND => { let pos = AbsoluteBytePos::decode(self)?; - let cached_ctxt = self.synthetic_expansion_infos.borrow().get(&pos).cloned(); + let cached_ctxt = self.synthetic_syntax_contexts.borrow().get(&pos).cloned(); if let Some(ctxt) = cached_ctxt { Span::new(lo, hi, ctxt) } else { - let expn_info = - self.with_position(pos.to_usize(), |this| ExpnInfo::decode(this))?; - recover_from_expn_info(self, expn_info, pos) + let (expn_data, transparency) = + self.with_position(pos.to_usize(), |this| Decodable::decode(this))?; + recover_from_expn_data(self, expn_data, transparency, pos) } } _ => { @@ -626,26 +624,33 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } +impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result { + // FIXME: Handle hygiene in incremental + bug!("Trying to decode Ident for incremental"); + } +} + // This impl makes sure that we get a runtime error when we try decode a -// DefIndex that is not contained in a DefId. Such a case would be problematic -// because we would not know how to transform the DefIndex to the current +// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic +// because we would not know how to transform the `DefIndex` to the current // context. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - bug!("Trying to decode DefIndex outside the context of a DefId") + bug!("trying to decode `DefIndex` outside the context of a `DefId`") } } -// Both the CrateNum and the DefIndex of a DefId can change in between two -// compilation sessions. We use the DefPathHash, which is stable across -// sessions, to map the old DefId to the new one. +// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two +// compilation sessions. We use the `DefPathHash`, which is stable across +// sessions, to map the old `DefId` to the new one. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - // Load the DefPathHash which is was we encoded the DefId as. + // Load the `DefPathHash` which is was we encoded the `DefId` as. let def_path_hash = DefPathHash::decode(self)?; - // Using the DefPathHash, we can lookup the new DefId + // Using the `DefPathHash`, we can lookup the new `DefId`. Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash]) } } @@ -659,10 +664,10 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - // Load the DefPathHash which is was we encoded the DefIndex as. + // Load the `DefPathHash` which is what we encoded the `DefIndex` as. let def_path_hash = DefPathHash::decode(self)?; - // Use the DefPathHash to map to the current DefId. + // Use the `DefPathHash` to map to the current `DefId`. let def_id = self.tcx() .def_path_hash_to_def_id .as_ref() @@ -670,10 +675,10 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { debug_assert!(def_id.is_local()); - // The ItemLocalId needs no remapping. + // The `ItemLocalId` needs no remapping. let local_id = hir::ItemLocalId::decode(self)?; - // Reconstruct the HirId and look up the corresponding NodeId in the + // Reconstruct the `HirId` and look up the corresponding `NodeId` in the // context of the current session. Ok(hir::HirId { owner: def_id.index, @@ -682,8 +687,8 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } -// NodeIds are not stable across compilation sessions, so we store them in their -// HirId representation. This allows use to map them to the current NodeId. +// `NodeId`s are not stable across compilation sessions, so we store them in their +// `HirId` representation. This allows use to map them to the current `NodeId`. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { @@ -720,12 +725,13 @@ impl<'a, 'tcx, T: Decodable> SpecializedDecoder> //- ENCODING ------------------------------------------------------------------- +/// An encoder that can write the incr. comp. cache. struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> { tcx: TyCtxt<'tcx>, encoder: &'a mut E, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, - expn_info_shorthands: FxHashMap, + expn_data_shorthands: FxHashMap, interpret_allocs: FxHashMap, interpret_allocs_inverse: Vec, source_map: CachingSourceMapView<'tcx>, @@ -734,7 +740,7 @@ struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> { impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn source_file_index(&mut self, source_file: Lrc) -> SourceFileIndex { self.file_to_file_index[&(&*source_file as *const SourceFile)] @@ -745,11 +751,11 @@ where /// encode the specified tag, then the given value, then the number of /// bytes taken up by tag and value. On decoding, we can then verify that /// we get the expected tag and read the expected number of bytes. - fn encode_tagged(&mut self, - tag: T, - value: &V) - -> Result<(), E::Error> - { + fn encode_tagged( + &mut self, + tag: T, + value: &V + ) -> Result<(), E::Error> { let start_pos = self.position(); tag.encode(self)?; @@ -762,7 +768,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { use std::collections::hash_map::Entry; @@ -782,10 +788,9 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> { - if *span == DUMMY_SP { return TAG_INVALID_SPAN.encode(self); } @@ -816,30 +821,39 @@ where col_lo.encode(self)?; len.encode(self)?; - if span_data.ctxt == SyntaxContext::empty() { - TAG_NO_EXPANSION_INFO.encode(self) + if span_data.ctxt == SyntaxContext::root() { + TAG_NO_EXPN_DATA.encode(self) } else { - let (expn_id, expn_info) = span_data.ctxt.outer_expn_with_info(); - if let Some(expn_info) = expn_info { - if let Some(pos) = self.expn_info_shorthands.get(&expn_id).cloned() { - TAG_EXPANSION_INFO_SHORTHAND.encode(self)?; - pos.encode(self) - } else { - TAG_EXPANSION_INFO_INLINE.encode(self)?; - let pos = AbsoluteBytePos::new(self.position()); - self.expn_info_shorthands.insert(expn_id, pos); - expn_info.encode(self) - } + let (expn_id, transparency, expn_data) = span_data.ctxt.outer_mark_with_data(); + if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() { + TAG_EXPN_DATA_SHORTHAND.encode(self)?; + pos.encode(self) } else { - TAG_NO_EXPANSION_INFO.encode(self) + TAG_EXPN_DATA_INLINE.encode(self)?; + let pos = AbsoluteBytePos::new(self.position()); + self.expn_data_shorthands.insert(expn_id, pos); + (expn_data, transparency).encode(self) } } } } -impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E> +impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where E: 'a + ty_codec::TyEncoder, +{ + fn specialized_encode(&mut self, _: &Ident) -> Result<(), Self::Error> { + // We don't currently encode enough information to ensure hygiene works + // with incremental, so panic rather than risk incremental bugs. + + // FIXME: handle hygiene in incremental. + bug!("trying to encode `Ident` for incremental"); + } +} + +impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E> +where + E: 'a + TyEncoder, { #[inline] fn position(&self) -> usize { @@ -849,7 +863,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -859,7 +873,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { @@ -870,7 +884,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, @@ -883,7 +897,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> { @@ -901,7 +915,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> { @@ -912,7 +926,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> { @@ -922,18 +936,18 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> { - bug!("Encoding DefIndex without context.") + bug!("encoding `DefIndex` without context"); } } -// NodeIds are not stable across compilation sessions, so we store them in their -// HirId representation. This allows use to map them to the current NodeId. +// `NodeId`s are not stable across compilation sessions, so we store them in their +// `HirId` representation. This allows use to map them to the current `NodeId`. impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> { @@ -950,7 +964,7 @@ impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque impl<'a, 'tcx, E, T> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, T: Encodable, { #[inline] @@ -979,7 +993,7 @@ macro_rules! encoder_methods { impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { type Error = E::Error; @@ -1023,7 +1037,7 @@ impl UseSpecializedDecodable for IntEncodedWithFixedSize {} impl SpecializedEncoder for opaque::Encoder { fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> { let start_pos = self.position(); - for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE { + for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { ((x.0 >> i * 8) as u8).encode(self)?; } let end_pos = self.position(); @@ -1068,10 +1082,10 @@ where if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) { let dep_node = SerializedDepNodeIndex::new(entry.index.index()); - // Record position of the cache entry + // Record position of the cache entry. query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position()))); - // Encode the type check tables with the SerializedDepNodeIndex + // Encode the type check tables with the `SerializedDepNodeIndex` // as tag. encoder.encode_tagged(dep_node, &entry.value)?; } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 4dce55f589..a1828bb5ab 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -61,7 +61,7 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } } -// If enabled, send a message to the profile-queries thread +// If enabled, sends a message to the profile-queries thread. macro_rules! profq_msg { ($tcx:expr, $msg:expr) => { if cfg!(debug_assertions) { @@ -72,7 +72,7 @@ macro_rules! profq_msg { } } -// If enabled, format a key using its debug string, which can be +// If enabled, formats a key using its debug string, which can be // expensive to compute (in terms of time). macro_rules! profq_query_msg { ($query:expr, $tcx:expr, $key:expr) => {{ @@ -98,7 +98,7 @@ pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// Either gets a `JobOwner` corresponding the query, allowing us to - /// start executing the query, or it returns with the result of the query. + /// start executing the query, or returns with the result of the query. /// If the query is executing elsewhere, this will wait for it. /// If the query panicked, this will silently panic. /// @@ -215,30 +215,30 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { #[inline(never)] #[cold] fn drop(&mut self) { - // Poison the query so jobs waiting on it panic + // Poison the query so jobs waiting on it panic. let shard = self.cache.get_shard_by_value(&self.key); shard.lock().active.insert(self.key.clone(), QueryResult::Poisoned); // Also signal the completion of the job, so waiters - // will continue execution + // will continue execution. self.job.signal_complete(); } } #[derive(Clone)] pub struct CycleError<'tcx> { - /// The query and related span which uses the cycle + /// The query and related span that uses the cycle. pub(super) usage: Option<(Span, Query<'tcx>)>, pub(super) cycle: Vec>, } -/// The result of `try_get_lock` +/// The result of `try_get_lock`. pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { /// The query is not yet started. Contains a guard to the cache eventually used to start it. NotYetStarted(JobOwner<'a, 'tcx, D>), /// The query was already completed. - /// Returns the result of the query and its dep node index - /// if it succeeded or a cycle error if it failed + /// Returns the result of the query and its dep-node index + /// if it succeeded or a cycle error if it failed. JobCompleted((D::Value, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. @@ -246,7 +246,7 @@ pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { } impl<'tcx> TyCtxt<'tcx> { - /// Executes a job by changing the ImplicitCtxt to point to the + /// Executes a job by changing the `ImplicitCtxt` to point to the /// new query job while it executes. It returns the diagnostics /// captured during execution and the actual result. #[inline(always)] @@ -259,11 +259,11 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnOnce(TyCtxt<'tcx>) -> R, { - // The TyCtxt stored in TLS has the same global interner lifetime + // The `TyCtxt` stored in TLS has the same global interner lifetime // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes - // when accessing the ImplicitCtxt + // when accessing the `ImplicitCtxt`. tls::with_related_context(self, move |current_icx| { - // Update the ImplicitCtxt to point to our new query job + // Update the `ImplicitCtxt` to point to our new query job. let new_icx = tls::ImplicitCtxt { tcx: self.global_tcx(), query: Some(job), @@ -272,7 +272,7 @@ impl<'tcx> TyCtxt<'tcx> { task_deps: current_icx.task_deps, }; - // Use the ImplicitCtxt while we execute the query + // Use the `ImplicitCtxt` while we execute the query. tls::enter_context(&new_icx, |_| { compute(self.global_tcx()) }) @@ -330,14 +330,13 @@ impl<'tcx> TyCtxt<'tcx> { let mut i = 0; while let Some(query) = current_query { - let mut db = DiagnosticBuilder::new(icx.tcx.sess.diagnostic(), - Level::FailureNote, + let mut diag = Diagnostic::new(Level::FailureNote, &format!("#{} [{}] {}", i, query.info.query.name(), query.info.query.describe(icx.tcx))); - db.set_span(icx.tcx.sess.source_map().def_span(query.info.span)); - icx.tcx.sess.diagnostic().force_print_db(db); + diag.span = icx.tcx.sess.source_map().def_span(query.info.span).into(); + icx.tcx.sess.diagnostic().force_print_diagnostic(diag); current_query = query.parent.clone(); i += 1; @@ -372,7 +371,7 @@ impl<'tcx> TyCtxt<'tcx> { }; // Fast path for when incr. comp. is off. `to_dep_node` is - // expensive for some DepKinds. + // expensive for some `DepKind`s. if !self.dep_graph.is_fully_enabled() { let null_dep_node = DepNode::new_no_params(crate::dep_graph::DepKind::Null); return self.force_query_with_job::(key, job, null_dep_node).0; @@ -410,7 +409,7 @@ impl<'tcx> TyCtxt<'tcx> { if !Q::EVAL_ALWAYS { // The diagnostics for this query will be // promoted to the current session during - // try_mark_green(), so we can ignore them here. + // `try_mark_green()`, so we can ignore them here. let loaded = self.start_query(job.job.clone(), None, |tcx| { let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node); marked.map(|(prev_dep_node_index, dep_node_index)| { @@ -441,11 +440,11 @@ impl<'tcx> TyCtxt<'tcx> { dep_node: &DepNode, ) -> Q::Value { // Note this function can be called concurrently from the same query - // We must ensure that this is handled correctly + // We must ensure that this is handled correctly. debug_assert!(self.dep_graph.is_green(dep_node)); - // First we try to load the result from the on-disk cache + // First we try to load the result from the on-disk cache. let result = if Q::cache_on_disk(self.global_tcx(), key.clone(), None) && self.sess.opts.debugging_opts.incremental_queries { self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME)); @@ -453,10 +452,10 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.profiler(|p| p.incremental_load_result_end(Q::NAME)); // We always expect to find a cached result for things that - // can be forced from DepNode. + // can be forced from `DepNode`. debug_assert!(!dep_node.kind.can_reconstruct_query_key() || result.is_some(), - "Missing on-disk cache entry for {:?}", + "missing on-disk cache entry for {:?}", dep_node); result } else { @@ -475,8 +474,7 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.profiler(|p| p.start_query(Q::NAME)); - // The dep-graph for this computation is already in - // place + // The dep-graph for this computation is already in-place. let result = self.dep_graph.with_ignore(|| { Q::compute(self, key) }); @@ -485,7 +483,7 @@ impl<'tcx> TyCtxt<'tcx> { result }; - // If -Zincremental-verify-ich is specified, re-hash results from + // If `-Zincremental-verify-ich` is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) { self.incremental_verify_ich::(&result, dep_node, dep_node_index); @@ -508,10 +506,12 @@ impl<'tcx> TyCtxt<'tcx> { ) { use crate::ich::Fingerprint; - assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == + assert!( + Some(self.dep_graph.fingerprint_of(dep_node_index)) == self.dep_graph.prev_fingerprint_of(dep_node), - "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); + "fingerprint for green query instance not loaded from cache: {:?}", + dep_node, + ); debug!("BEGIN verify_ich({:?})", dep_node); let mut hcx = self.create_stable_hashing_context(); @@ -521,8 +521,11 @@ impl<'tcx> TyCtxt<'tcx> { let old_hash = self.dep_graph.fingerprint_of(dep_node_index); - assert!(new_hash == old_hash, "Found unstable fingerprints \ - for {:?}", dep_node); + assert!( + new_hash == old_hash, + "found unstable fingerprints for {:?}", + dep_node, + ); } #[inline(always)] @@ -534,11 +537,11 @@ impl<'tcx> TyCtxt<'tcx> { ) -> (Q::Value, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: // 1. Something is wrong with DepNode creation, either here or - // in DepGraph::try_mark_green() - // 2. Two distinct query keys get mapped to the same DepNode - // (see for example #48923) + // in `DepGraph::try_mark_green()`. + // 2. Two distinct query keys get mapped to the same `DepNode` + // (see for example #48923). assert!(!self.dep_graph.dep_node_exists(&dep_node), - "Forcing query with already existing DepNode.\n\ + "forcing query with already existing `DepNode`\n\ - query-key: {:?}\n\ - dep-node: {:?}", key, dep_node); @@ -584,7 +587,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Ensure that either this query has all green inputs or been executed. - /// Executing query::ensure(D) is considered a read of the dep-node D. + /// Executing `query::ensure(D)` is considered a read of the dep-node `D`. /// /// This function is particularly useful when executing passes for their /// side-effects -- e.g., in order to report errors for erroneous programs. @@ -899,13 +902,13 @@ macro_rules! define_queries_inner { } } - // FIXME(eddyb) Get more valid Span's on queries. + // FIXME(eddyb) Get more valid `Span`s on queries. pub fn default_span(&self, tcx: TyCtxt<$tcx>, span: Span) -> Span { if !span.is_dummy() { return span; } - // The def_span query is used to calculate default_span, - // so exit to avoid infinite recursion + // The `def_span` query is used to calculate `default_span`, + // so exit to avoid infinite recursion. if let Query::def_span(..) = *self { return span } @@ -1116,7 +1119,7 @@ macro_rules! define_provider_struct { impl<$tcx> Default for Providers<$tcx> { fn default() -> Self { $(fn $name<$tcx>(_: TyCtxt<$tcx>, key: $K) -> $R { - bug!("tcx.{}({:?}) unsupported by its crate", + bug!("`tcx.{}({:?})` unsupported by its crate", stringify!($name), key); })* Providers { $($name),* } @@ -1128,26 +1131,26 @@ macro_rules! define_provider_struct { /// The red/green evaluation system will try to mark a specific DepNode in the /// dependency graph as green by recursively trying to mark the dependencies of -/// that DepNode as green. While doing so, it will sometimes encounter a DepNode +/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` /// where we don't know if it is red or green and we therefore actually have /// to recompute its value in order to find out. Since the only piece of -/// information that we have at that point is the DepNode we are trying to +/// information that we have at that point is the `DepNode` we are trying to /// re-evaluate, we need some way to re-run a query from just that. This is what /// `force_from_dep_node()` implements. /// -/// In the general case, a DepNode consists of a DepKind and an opaque +/// In the general case, a `DepNode` consists of a `DepKind` and an opaque /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint /// is usually constructed by computing a stable hash of the query-key that the -/// DepNode corresponds to. Consequently, it is not in general possible to go +/// `DepNode` corresponds to. Consequently, it is not in general possible to go /// back from hash to query-key (since hash functions are not reversible). For /// this reason `force_from_dep_node()` is expected to fail from time to time -/// because we just cannot find out, from the DepNode alone, what the +/// because we just cannot find out, from the `DepNode` alone, what the /// corresponding query-key is and therefore cannot re-run the query. /// /// The system deals with this case letting `try_mark_green` fail which forces /// the root query to be re-evaluated. /// -/// Now, if force_from_dep_node() would always fail, it would be pretty useless. +/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. /// Fortunately, we can use some contextual information that will allow us to /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a @@ -1171,9 +1174,9 @@ macro_rules! define_provider_struct { pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { use crate::dep_graph::RecoverKey; - // We must avoid ever having to call force_from_dep_node() for a - // DepNode::codegen_unit: - // Since we cannot reconstruct the query key of a DepNode::codegen_unit, we + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we // would always end up having to evaluate the first caller of the // `codegen_unit` query that *is* reconstructible. This might very well be // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just @@ -1196,7 +1199,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { if let Some(def_id) = dep_node.extract_def_id(tcx) { def_id } else { - // return from the whole function + // Return from the whole function. return false } } @@ -1224,20 +1227,20 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { rustc_dep_node_force!([dep_node, tcx] // These are inputs that are expected to be pre-allocated and that - // should therefore always be red or green already + // should therefore always be red or green already. DepKind::AllLocalTraitImpls | DepKind::Krate | DepKind::CrateMetadata | DepKind::HirBody | DepKind::Hir | - // This are anonymous nodes + // These are anonymous nodes. DepKind::TraitSelect | // We don't have enough information to reconstruct the query key of - // these + // these. DepKind::CompileCodegenUnit => { - bug!("force_from_dep_node() - Encountered {:?}", dep_node) + bug!("force_from_dep_node: encountered {:?}", dep_node) } DepKind::Analysis => { force!(analysis, krate!()); } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 945e3e158e..565447dd7e 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{Kind, UnpackedKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, Scalar, GlobalId}; +use crate::mir::interpret::{ConstValue, Scalar}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -551,26 +551,8 @@ pub fn super_relate_consts>( let tcx = relation.tcx(); let eagerly_eval = |x: &'tcx ty::Const<'tcx>| { - if let ConstValue::Unevaluated(def_id, substs) = x.val { - // FIXME(eddyb) get the right param_env. - let param_env = ty::ParamEnv::empty(); - if !substs.has_local_value() { - let instance = ty::Instance::resolve( - tcx.global_tcx(), - param_env, - def_id, - substs, - ); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(ct) = tcx.const_eval(param_env.and(cid)) { - return ct.val; - } - } - } + if !x.val.has_local_value() { + return x.eval(tcx, relation.param_env()).val; } x.val }; diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 649a524472..ec7cf1a13c 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -748,6 +748,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Sorts(ref x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), + IntrinsicCast => IntrinsicCast, }) } } @@ -1338,6 +1339,7 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::Sorts)(x), (ty::error::TypeError::ExistentialMismatch)(x), (ty::error::TypeError::ConstMismatch)(x), + (ty::error::TypeError::IntrinsicCast), } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 129ea9b5b6..e73a51e6f7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1,6 +1,6 @@ //! This module contains `TyKind` and its major components. -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#![allow(rustc::usage_of_ty_tykind)] use crate::hir; use crate::hir::def_id::DefId; @@ -86,6 +86,7 @@ impl BoundRegion { /// AST structure in `libsyntax/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, Debug)] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. Bool, @@ -385,7 +386,7 @@ impl<'tcx> ClosureSubsts<'tcx> { let ty = self.closure_sig_ty(def_id, tcx); match ty.sty { ty::FnPtr(sig) => sig, - _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty), + _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty), } } } @@ -643,7 +644,7 @@ impl<'tcx> Binder> { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List> {} impl<'tcx> List> { - /// Returns the "principal def id" of this set of existential predicates. + /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) /// of a set of trait bounds, which are separated into any number @@ -1051,7 +1052,7 @@ impl<'tcx> PolyGenSig<'tcx> { } } -/// Signature of a function type, which I have arbitrarily +/// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. /// /// - `inputs`: is the list of arguments and their modes. @@ -1075,7 +1076,8 @@ impl<'tcx> FnSig<'tcx> { self.inputs_and_output[self.inputs_and_output.len() - 1] } - // Create a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible method + // Creates a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible + // method. fn fake() -> FnSig<'tcx> { FnSig { inputs_and_output: List::empty(), @@ -1117,7 +1119,6 @@ impl<'tcx> PolyFnSig<'tcx> { pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { @@ -1141,13 +1142,6 @@ impl<'tcx> ParamTy { pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.mk_ty_param(self.index, self.name) } - - pub fn is_self(&self) -> bool { - // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, - // but this should only be possible when using `-Z continue-parse-after-error` like - // `compile-fail/issue-36638.rs`. - self.name.as_symbol() == kw::SelfUpper && self.index == 0 - } } #[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, @@ -1789,14 +1783,6 @@ impl<'tcx> TyS<'tcx> { } } - #[inline] - pub fn is_self(&self) -> bool { - match self.sty { - Param(ref p) => p.is_self(), - _ => false, - } - } - #[inline] pub fn is_slice(&self) -> bool { match self.sty { @@ -2068,6 +2054,9 @@ impl<'tcx> TyS<'tcx> { Error => { // ignore errors (#54954) ty::Binder::dummy(FnSig::fake()) } + Closure(..) => bug!( + "to get the signature of a closure, use `closure_sig()` not `fn_sig()`", + ), _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } @@ -2311,23 +2300,33 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty, ty); // if `ty` does not depend on generic parameters, use an empty param_env let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; + self.eval(tcx, param_env).val.try_to_bits(size) + } + + #[inline] + pub fn eval( + &self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> &Const<'tcx> { + // FIXME(const_generics): this doesn't work right now, + // because it tries to relate an `Infer` to a `Param`. match self.val { - // FIXME(const_generics): this doesn't work right now, - // because it tries to relate an `Infer` to a `Param`. ConstValue::Unevaluated(did, substs) => { // if `substs` has no unresolved components, use and empty param_env let (param_env, substs) = param_env.with_reveal_all().and(substs).into_parts(); // try to resolve e.g. associated constants to their definition on an impl - let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; + let instance = match ty::Instance::resolve(tcx, param_env, did, substs) { + Some(instance) => instance, + None => return self, + }; let gid = GlobalId { instance, promoted: None, }; - let evaluated = tcx.const_eval(param_env.and(gid)).ok()?; - evaluated.val.try_to_bits(size) + tcx.const_eval(param_env.and(gid)).unwrap_or(self) }, - // otherwise just extract a `ConstValue`'s bits if possible - _ => self.val.try_to_bits(size), + _ => self, } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 96e16efd13..2bb009ddf9 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -697,6 +697,9 @@ impl<'tcx> TyCtxt<'tcx> { // that type, and when we finish expanding that type we remove the // its DefId. seen_opaque_tys: FxHashSet, + // Cache of all expansions we've seen so far. This is a critical + // optimization for some large types produced by async fn trees. + expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>, primary_def_id: DefId, found_recursion: bool, tcx: TyCtxt<'tcx>, @@ -709,11 +712,20 @@ impl<'tcx> TyCtxt<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { if self.found_recursion { - None - } else if self.seen_opaque_tys.insert(def_id) { - let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx, substs); - let expanded_ty = self.fold_ty(concrete_ty); + return None; + } + let substs = substs.fold_with(self); + if self.seen_opaque_tys.insert(def_id) { + let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { + Some(expanded_ty) => expanded_ty, + None => { + let generic_ty = self.tcx.type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx, substs); + let expanded_ty = self.fold_ty(concrete_ty); + self.expanded_cache.insert((def_id, substs), expanded_ty); + expanded_ty + } + }; self.seen_opaque_tys.remove(&def_id); Some(expanded_ty) } else { @@ -733,14 +745,17 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if let ty::Opaque(def_id, substs) = t.sty { self.expand_opaque_ty(def_id, substs).unwrap_or(t) - } else { + } else if t.has_projections() { t.super_fold_with(self) + } else { + t } } } let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), + expanded_cache: FxHashMap::default(), primary_def_id: def_id, found_recursion: false, tcx: self, @@ -994,11 +1009,29 @@ impl<'tcx> ty::TyS<'tcx> { debug!("is_type_representable: {:?} is {:?}", self, r); r } + + /// Peel off all reference types in this type until there are none left. + /// + /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`. + /// + /// # Examples + /// + /// - `u8` -> `u8` + /// - `&'a mut u8` -> `u8` + /// - `&'a &'b u8` -> `u8` + /// - `&'a *const &'b u8 -> *const &'b u8` + pub fn peel_refs(&'tcx self) -> Ty<'tcx> { + let mut ty = self; + while let Ref(_, inner_ty, _) = ty.sty { + ty = inner_ty; + } + ty + } } fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1011,7 +1044,7 @@ fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1024,7 +1057,7 @@ fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index d32c32af29..d6de217f79 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { - def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate())); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 7118d05204..2475b93d95 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -5,17 +5,13 @@ use rustc_data_structures::{fx::FxHashMap, sync::Lock}; use std::cell::{RefCell, Cell}; use std::fmt::Debug; use std::hash::Hash; -use std::panic; -use std::env; use std::time::{Duration, Instant}; use std::sync::mpsc::{Sender}; use syntax_pos::{SpanData}; use syntax::symbol::{Symbol, sym}; use rustc_macros::HashStable; -use crate::ty::TyCtxt; use crate::dep_graph::{DepNode}; -use lazy_static; use crate::session::Session; #[cfg(test)] @@ -31,39 +27,6 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); -lazy_static! { - static ref DEFAULT_HOOK: Box) + Sync + Send + 'static> = { - let hook = panic::take_hook(); - panic::set_hook(Box::new(panic_hook)); - hook - }; -} - -fn panic_hook(info: &panic::PanicInfo<'_>) { - (*DEFAULT_HOOK)(info); - - let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false); - - if backtrace { - TyCtxt::try_print_query_stack(); - } - - #[cfg(windows)] - unsafe { - if env::var("RUSTC_BREAK_ON_ICE").is_ok() { - extern "system" { - fn DebugBreak(); - } - // Trigger a debugger if we crashed during bootstrap. - DebugBreak(); - } - } -} - -pub fn install_panic_hook() { - lazy_static::initialize(&DEFAULT_HOOK); -} - /// Parameters to the `Dump` variant of type `ProfileQueriesMsg`. #[derive(Clone,Debug)] pub struct ProfQDumpParams { diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 9f68d770b9..18d968fbdd 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -1,13 +1,13 @@ use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO}; use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd}; +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt::{self, Write}; +use core::marker::PhantomData; +use core::mem; +use core::ops::Neg; use smallvec::{SmallVec, smallvec}; -use std::cmp::{self, Ordering}; -use std::convert::TryFrom; -use std::fmt::{self, Write}; -use std::marker::PhantomData; -use std::mem; -use std::ops::Neg; #[must_use] pub struct IeeeFloat { @@ -2287,8 +2287,8 @@ impl Loss { /// Implementation details of IeeeFloat significands, such as big integer arithmetic. /// As a rule of thumb, no functions in this module should dynamically allocate. mod sig { - use std::cmp::Ordering; - use std::mem; + use core::cmp::Ordering; + use core::mem; use super::{ExpInt, Limb, LIMB_BITS, limbs_for_bits, Loss}; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 9e6d5a6f62..1190cea21a 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -31,15 +31,19 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![no_std] #![forbid(unsafe_code)] #![feature(nll)] -use std::cmp::Ordering; -use std::fmt; -use std::ops::{Neg, Add, Sub, Mul, Div, Rem}; -use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use std::str::FromStr; +#[macro_use] +extern crate alloc; + +use core::cmp::Ordering; +use core::fmt; +use core::ops::{Neg, Add, Sub, Mul, Div, Rem}; +use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use core::str::FromStr; bitflags::bitflags! { /// IEEE-754R 7: Default exception handling. @@ -587,7 +591,7 @@ macro_rules! float_common_impls { } } - impl<$t> ::std::str::FromStr for $ty<$t> where Self: Float { + impl<$t> ::core::str::FromStr for $ty<$t> where Self: Float { type Err = ParseError; fn from_str(s: &str) -> Result { Self::from_str_r(s, Round::NearestTiesToEven).map(|x| x.value) @@ -596,66 +600,66 @@ macro_rules! float_common_impls { // Rounding ties to the nearest even, by default. - impl<$t> ::std::ops::Add for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Add for $ty<$t> where Self: Float { type Output = StatusAnd; fn add(self, rhs: Self) -> StatusAnd { self.add_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Sub for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Sub for $ty<$t> where Self: Float { type Output = StatusAnd; fn sub(self, rhs: Self) -> StatusAnd { self.sub_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Mul for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Mul for $ty<$t> where Self: Float { type Output = StatusAnd; fn mul(self, rhs: Self) -> StatusAnd { self.mul_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Div for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Div for $ty<$t> where Self: Float { type Output = StatusAnd; fn div(self, rhs: Self) -> StatusAnd { self.div_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Rem for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Rem for $ty<$t> where Self: Float { type Output = StatusAnd; fn rem(self, rhs: Self) -> StatusAnd { self.c_fmod(rhs) } } - impl<$t> ::std::ops::AddAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::AddAssign for $ty<$t> where Self: Float { fn add_assign(&mut self, rhs: Self) { *self = (*self + rhs).value; } } - impl<$t> ::std::ops::SubAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::SubAssign for $ty<$t> where Self: Float { fn sub_assign(&mut self, rhs: Self) { *self = (*self - rhs).value; } } - impl<$t> ::std::ops::MulAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::MulAssign for $ty<$t> where Self: Float { fn mul_assign(&mut self, rhs: Self) { *self = (*self * rhs).value; } } - impl<$t> ::std::ops::DivAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::DivAssign for $ty<$t> where Self: Float { fn div_assign(&mut self, rhs: Self) { *self = (*self / rhs).value; } } - impl<$t> ::std::ops::RemAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::RemAssign for $ty<$t> where Self: Float { fn rem_assign(&mut self, rhs: Self) { *self = (*self % rhs).value; } diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index ddccfd6ca6..8e2e390568 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -1,9 +1,9 @@ use crate::{Category, ExpInt, Float, FloatConvert, Round, ParseError, Status, StatusAnd}; use crate::ieee; -use std::cmp::Ordering; -use std::fmt; -use std::ops::Neg; +use core::cmp::Ordering; +use core::fmt; +use core::ops::Neg; #[must_use] #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index a2b4b090ef..645707ccc0 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -4,6 +4,10 @@ use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { + println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); + if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { + return; + } if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { build_helper::restore_library_path(); diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs index 3bbd7ae5c3..23d5480c60 100644 --- a/src/librustc_ast_borrowck/borrowck/mod.rs +++ b/src/librustc_ast_borrowck/borrowck/mod.rs @@ -9,7 +9,6 @@ use InteriorKind::*; use rustc::hir::HirId; use rustc::hir::Node; -use rustc::cfg; use rustc::middle::borrowck::{BorrowCheckResult, SignalledError}; use rustc::hir::def_id::{DefId, LocalDefId}; use rustc::middle::mem_categorization as mc; @@ -28,6 +27,7 @@ use log::debug; use rustc::hir; +use crate::cfg; use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; pub mod check_loans; diff --git a/src/librustc_ast_borrowck/borrowck/move_data.rs b/src/librustc_ast_borrowck/borrowck/move_data.rs index 887a0e2f20..67d818161b 100644 --- a/src/librustc_ast_borrowck/borrowck/move_data.rs +++ b/src/librustc_ast_borrowck/borrowck/move_data.rs @@ -4,7 +4,7 @@ use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; use crate::borrowck::*; -use rustc::cfg; +use crate::cfg; use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::FxHashMap; diff --git a/src/librustc/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs similarity index 84% rename from src/librustc/cfg/construct.rs rename to src/librustc_ast_borrowck/cfg/construct.rs index ca852fe762..0dc999083a 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc_ast_borrowck/cfg/construct.rs @@ -1,11 +1,12 @@ use crate::cfg::*; -use crate::middle::region; -use rustc_data_structures::graph::implementation as graph; -use crate::ty::{self, TyCtxt}; -use crate::hir::{self, PatKind}; -use crate::hir::def_id::DefId; -use crate::hir::ptr::P; +use rustc::hir::{self, PatKind}; +use rustc::hir::def_id::DefId; +use rustc::hir::ptr::P; +use rustc::middle::region; +use rustc::ty::{self, TyCtxt}; + +use rustc_data_structures::graph::implementation as graph; struct CFGBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -19,18 +20,18 @@ struct CFGBuilder<'a, 'tcx> { #[derive(Copy, Clone)] struct BlockScope { - block_expr_id: hir::ItemLocalId, // id of breakable block expr node + block_expr_id: hir::ItemLocalId, // ID of breakable block expr node break_index: CFGIndex, // where to go on `break` } #[derive(Copy, Clone)] struct LoopScope { - loop_id: hir::ItemLocalId, // id of loop/while node + loop_id: hir::ItemLocalId, // ID of `loop`/`while` node continue_index: CFGIndex, // where to go on a `loop` - break_index: CFGIndex, // where to go on a `break` + break_index: CFGIndex, // where to go on a `break` } -pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { +pub(super) fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { let mut graph = graph::Graph::new(); let entry = graph.add_node(CFGNodeData::Entry); @@ -103,9 +104,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let init_exit = self.opt_expr(&local.init, pred); self.pat(&local.pat, init_exit) } - hir::StmtKind::Item(_) => { - pred - } + hir::StmtKind::Item(_) => pred, hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { self.expr(&expr, pred) @@ -136,10 +135,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } PatKind::Struct(_, ref subpats, _) => { - let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); + let pats_exit = self.pats_all(subpats.iter().map(|f| &f.pat), pred); self.add_ast_node(pat.hir_id.local_id, &[pats_exit]) } + PatKind::Or(ref pats) => { + let branches: Vec<_> = pats.iter().map(|p| self.pat(p, pred)).collect(); + self.add_ast_node(pat.hir_id.local_id, &branches) + } + PatKind::Slice(ref pre, ref vec, ref post) => { let pre_exit = self.pats_all(pre.iter(), pred); let vec_exit = self.pats_all(vec.iter(), pre_exit); @@ -149,12 +153,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn pats_all<'b, I: Iterator>>( + /// Handles case where all of the patterns must match. + fn pats_all<'b, I: Iterator>>( &mut self, pats: I, - pred: CFGIndex + pred: CFGIndex, ) -> CFGIndex { - //! Handles case where all of the patterns must match. pats.fold(pred, |pred, pat| self.pat(&pat, pred)) } @@ -180,15 +184,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Note that `break` and `loop` statements // may cause additional edges. - let loopback = self.add_dummy_node(&[pred]); // 1 - let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 + let loopback = self.add_dummy_node(&[pred]); // 1 + let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 self.loop_scopes.push(LoopScope { loop_id: expr.hir_id.local_id, continue_index: loopback, break_index: expr_exit, }); - let body_exit = self.block(&body, loopback); // 3 - self.add_contained_edge(body_exit, loopback); // 4 + let body_exit = self.block(&body, loopback); // 3 + self.add_contained_edge(body_exit, loopback); // 4 self.loop_scopes.pop(); expr_exit } @@ -212,9 +216,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // v 3 v 4 // [..exit..] // - let l_exit = self.expr(&l, pred); // 1 - let r_exit = self.expr(&r, l_exit); // 2 - self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 + let l_exit = self.expr(&l, pred); // 1 + let r_exit = self.expr(&r, l_exit); // 2 + self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 } hir::ExprKind::Ret(ref v) => { @@ -308,11 +312,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn call<'b, I: Iterator>(&mut self, - call_expr: &hir::Expr, - pred: CFGIndex, - func_or_rcvr: &hir::Expr, - args: I) -> CFGIndex { + fn call<'b, I: Iterator>( + &mut self, + call_expr: &hir::Expr, + pred: CFGIndex, + func_or_rcvr: &hir::Expr, + args: I, + ) -> CFGIndex { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); let m = self.tcx.hir().get_module_parent(call_expr.hir_id); @@ -323,33 +329,38 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn exprs<'b, I: Iterator>(&mut self, - exprs: I, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `exprs` evaluated in order + /// Constructs graph for `exprs` evaluated in order. + fn exprs<'b, I: Iterator>( + &mut self, + exprs: I, + pred: CFGIndex, + ) -> CFGIndex { exprs.fold(pred, |p, e| self.expr(e, p)) } - fn opt_expr(&mut self, - opt_expr: &Option>, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `opt_expr` evaluated, if Some + /// Constructs graph for `opt_expr` evaluated, if `Some`. + fn opt_expr( + &mut self, + opt_expr: &Option>, + pred: CFGIndex, + ) -> CFGIndex { opt_expr.iter().fold(pred, |p, e| self.expr(&e, p)) } - fn straightline<'b, I: Iterator>(&mut self, - expr: &hir::Expr, - pred: CFGIndex, - subexprs: I) -> CFGIndex { - //! Handles case of an expression that evaluates `subexprs` in order - + /// Handles case of an expression that evaluates `subexprs` in order. + fn straightline<'b, I: Iterator>( + &mut self, + expr: &hir::Expr, + pred: CFGIndex, + subexprs: I, + ) -> CFGIndex { let subexprs_exit = self.exprs(subexprs, pred); self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit]) } fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr, arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex { - // The CFG for match expression is quite complex, so no ASCII + // The CFG for match expressions is quite complex, so no ASCII // art for it (yet). // // The CFG generated below matches roughly what MIR contains. @@ -364,13 +375,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // // What is going on is explained in further comments. - // Visit the discriminant expression + // Visit the discriminant expression. let discr_exit = self.expr(discr, pred); // Add a node for the exit of the match expression as a whole. let expr_exit = self.add_ast_node(id, &[]); - // Keep track of the previous guard expressions + // Keep track of the previous guard expressions. let mut prev_guard = None; let match_scope = region::Scope { id, data: region::ScopeData::Node }; @@ -383,12 +394,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the pattern, coming from the discriminant exit let mut pat_exit = self.pat(&pat, discr_exit); - // If there is a guard expression, handle it here + // If there is a guard expression, handle it here. if let Some(ref guard) = arm.guard { // Add a dummy node for the previous guard - // expression to target + // expression to target. let guard_start = self.add_dummy_node(&[pat_exit]); - // Visit the guard expression + // Visit the guard expression. let guard_exit = match guard { hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)), }; @@ -402,24 +413,23 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start); } - // Push the guard onto the list of previous guards + // Push the guard onto the list of previous guards. prev_guard = Some(guard_exit); - // Update the exit node for the pattern + // Update the exit node for the pattern. pat_exit = guard_exit.1; } - // Add an edge from the exit of this pattern to the - // exit of the arm + // Add an edge from the exit of this pattern to the exit of the arm. self.add_contained_edge(pat_exit, bindings_exit); } - // Visit the body of this arm + // Visit the body of this arm. let body_exit = self.expr(&arm.body, bindings_exit); let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]); - // Link the body to the exit of the expression + // Link the body to the exit of the expression. self.add_contained_edge(arm_exit, expr_exit); } @@ -446,18 +456,22 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { node } - fn add_contained_edge(&mut self, - source: CFGIndex, - target: CFGIndex) { + fn add_contained_edge( + &mut self, + source: CFGIndex, + target: CFGIndex, + ) { let data = CFGEdgeData {exiting_scopes: vec![] }; self.graph.add_edge(source, target, data); } - fn add_exiting_edge(&mut self, - from_expr: &hir::Expr, - from_index: CFGIndex, - target_scope: region::Scope, - to_index: CFGIndex) { + fn add_exiting_edge( + &mut self, + from_expr: &hir::Expr, + from_index: CFGIndex, + target_scope: region::Scope, + to_index: CFGIndex, + ) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; let mut scope = region::Scope { id: from_expr.hir_id.local_id, @@ -471,9 +485,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.graph.add_edge(from_index, to_index, data); } - fn add_returning_edge(&mut self, - _from_expr: &hir::Expr, - from_index: CFGIndex) { + fn add_returning_edge( + &mut self, + _from_expr: &hir::Expr, + from_index: CFGIndex, + ) { let data = CFGEdgeData { exiting_scopes: self.loop_scopes.iter() .rev() @@ -483,11 +499,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.graph.add_edge(from_index, self.fn_exit, data); } - fn find_scope_edge(&self, - expr: &hir::Expr, - destination: hir::Destination, - scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) { - + fn find_scope_edge( + &self, + expr: &hir::Expr, + destination: hir::Destination, + scope_cf_kind: ScopeCfKind, + ) -> (region::Scope, CFGIndex) { match destination.target_id { Ok(loop_id) => { for b in &self.breakable_block_scopes { @@ -514,7 +531,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { }); } } - span_bug!(expr.span, "no scope for id {}", loop_id); + span_bug!(expr.span, "no scope for ID {}", loop_id); } Err(err) => span_bug!(expr.span, "scope error: {}", err), } diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc_ast_borrowck/cfg/graphviz.rs similarity index 88% rename from src/librustc/cfg/graphviz.rs rename to src/librustc_ast_borrowck/cfg/graphviz.rs index 918120057d..99c6b49cad 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc_ast_borrowck/cfg/graphviz.rs @@ -1,21 +1,18 @@ -/// This module provides linkage between rustc::middle::graph and +/// This module provides linkage between `rustc::middle::graph` and /// libgraphviz traits. -// For clarity, rename the graphviz crate locally to dot. -use graphviz as dot; - use crate::cfg; -use crate::hir; -use crate::ty::TyCtxt; +use rustc::hir; +use rustc::ty::TyCtxt; -pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); -pub type Edge<'a> = &'a cfg::CFGEdge; +pub(crate) type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); +pub(crate) type Edge<'a> = &'a cfg::CFGEdge; pub struct LabelledCFG<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub cfg: &'a cfg::CFG, pub name: String, - /// `labelled_edges` controls whether we emit labels on the edges + /// `labelled_edges` controls whether we emit labels on the edges. pub labelled_edges: bool, } @@ -28,12 +25,12 @@ impl<'a, 'tcx> LabelledCFG<'a, 'tcx> { }; let s = self.tcx.hir().node_to_string(hir_id); - // Replacing newlines with \\l causes each line to be left-aligned, + // Replacing newlines with `\\l` causes each line to be left-aligned, // improving presentation of (long) pretty-printed expressions. if s.contains("\n") { let mut s = s.replace("\n", "\\l"); // Apparently left-alignment applies to the line that precedes - // \l, not the line that follows; so, add \l at end of string + // `\l`, not the line that follows; so, add `\l` at end of string // if not already present, ensuring last line gets left-aligned // as well. let mut last_two: Vec<_> = @@ -112,8 +109,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG { } } -impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> -{ +impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> { type Node = Node<'a>; type Edge = Edge<'a>; fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() } diff --git a/src/librustc/cfg/mod.rs b/src/librustc_ast_borrowck/cfg/mod.rs similarity index 51% rename from src/librustc/cfg/mod.rs rename to src/librustc_ast_borrowck/cfg/mod.rs index 88fc7fbfad..981199c91d 100644 --- a/src/librustc/cfg/mod.rs +++ b/src/librustc_ast_borrowck/cfg/mod.rs @@ -2,18 +2,18 @@ //! Uses `Graph` as the underlying representation. use rustc_data_structures::graph::implementation as graph; -use crate::ty::TyCtxt; -use crate::hir; -use crate::hir::def_id::DefId; +use rustc::ty::TyCtxt; +use rustc::hir; +use rustc::hir::def_id::DefId; mod construct; pub mod graphviz; pub struct CFG { - pub owner_def_id: DefId, - pub graph: CFGGraph, - pub entry: CFGIndex, - pub exit: CFGIndex, + owner_def_id: DefId, + pub(crate) graph: CFGGraph, + pub(crate) entry: CFGIndex, + exit: CFGIndex, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -26,7 +26,7 @@ pub enum CFGNodeData { } impl CFGNodeData { - pub fn id(&self) -> hir::ItemLocalId { + pub(crate) fn id(&self) -> hir::ItemLocalId { if let CFGNodeData::AST(id) = *self { id } else { @@ -37,24 +37,19 @@ impl CFGNodeData { #[derive(Debug)] pub struct CFGEdgeData { - pub exiting_scopes: Vec + pub(crate) exiting_scopes: Vec } -pub type CFGIndex = graph::NodeIndex; +pub(crate) type CFGIndex = graph::NodeIndex; -pub type CFGGraph = graph::Graph; +pub(crate) type CFGGraph = graph::Graph; -pub type CFGNode = graph::Node; +pub(crate) type CFGNode = graph::Node; -pub type CFGEdge = graph::Edge; +pub(crate) type CFGEdge = graph::Edge; impl CFG { pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { construct::construct(tcx, body) } - - pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool { - self.graph.depth_traverse(self.entry, graph::OUTGOING) - .any(|idx| self.graph.node_data(idx).id() == id) - } } diff --git a/src/librustc_ast_borrowck/dataflow.rs b/src/librustc_ast_borrowck/dataflow.rs index 94849728a9..a8562901d9 100644 --- a/src/librustc_ast_borrowck/dataflow.rs +++ b/src/librustc_ast_borrowck/dataflow.rs @@ -3,9 +3,7 @@ //! and thus uses bitvectors. Your job is simply to specify the so-called //! GEN and KILL bits for each expression. -use rustc::cfg; -use rustc::cfg::CFGIndex; -use rustc::ty::TyCtxt; +use crate::cfg::{self, CFGIndex}; use std::mem; use std::usize; use log::debug; @@ -16,6 +14,7 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir; use rustc::hir::intravisit; use rustc::hir::print as pprust; +use rustc::ty::TyCtxt; #[derive(Copy, Clone, Debug)] pub enum EntryOrExit { @@ -186,8 +185,8 @@ fn build_local_id_to_index(body: Option<&hir::Body>, index: &'a mut FxHashMap>, } let mut formals = Formals { entry: entry, index: index }; - for arg in &body.arguments { - formals.visit_pat(&arg.pat); + for param in &body.params { + formals.visit_pat(¶m.pat); } impl<'a, 'v> Visitor<'v> for Formals<'a> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> { diff --git a/src/librustc_ast_borrowck/graphviz.rs b/src/librustc_ast_borrowck/graphviz.rs index 7a8a23ca76..c077dc828a 100644 --- a/src/librustc_ast_borrowck/graphviz.rs +++ b/src/librustc_ast_borrowck/graphviz.rs @@ -4,13 +4,12 @@ pub use Variant::*; -pub use rustc::cfg::graphviz::{Node, Edge}; -use rustc::cfg::graphviz as cfg_dot; - +pub(crate) use crate::cfg::graphviz::{Node, Edge}; +use crate::cfg::graphviz as cfg_dot; +use crate::cfg::CFGIndex; use crate::borrowck::{self, BorrowckCtxt, LoanPath}; use crate::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use log::debug; -use rustc::cfg::CFGIndex; use std::rc::Rc; #[derive(Debug, Copy, Clone)] diff --git a/src/librustc_ast_borrowck/lib.rs b/src/librustc_ast_borrowck/lib.rs index dc818278a4..aea97fea1a 100644 --- a/src/librustc_ast_borrowck/lib.rs +++ b/src/librustc_ast_borrowck/lib.rs @@ -18,5 +18,6 @@ mod borrowck; pub mod graphviz; mod dataflow; +pub mod cfg; pub use borrowck::provide; diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 5e1b0eafde..98efa6a580 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -11,11 +11,7 @@ crate-type = ["dylib"] test = false [dependencies] -cc = "1.0.1" # Used to locate MSVC -num_cpus = "1.0" -tempfile = "3.0" rustc_llvm = { path = "../librustc_llvm" } -memmap = "0.6" [features] # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm` diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index ff87afe0c4..2ca517dc3b 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -229,7 +229,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { // We instead thus allocate some scratch space... let scratch_size = cast.size(bx); let scratch_align = cast.align(bx); - let llscratch = bx.alloca(cast.llvm_type(bx), "abi_cast", scratch_align); + let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); bx.lifetime_start(llscratch, scratch_size); // ...where we first store the value... diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 9763d523a2..b68ee2cb44 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -6,9 +6,9 @@ use crate::value::Value; use rustc::hir; use rustc_codegen_ssa::traits::*; - use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; +use syntax_pos::Span; use std::ffi::{CStr, CString}; use libc::{c_uint, c_char}; @@ -19,7 +19,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { &mut self, ia: &hir::InlineAsm, outputs: Vec>, - mut inputs: Vec<&'ll Value> + mut inputs: Vec<&'ll Value>, + span: Span, ) -> bool { let mut ext_constraints = vec![]; let mut output_types = vec![]; @@ -102,7 +103,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let kind = llvm::LLVMGetMDKindIDInContext(self.llcx, key.as_ptr() as *const c_char, key.len() as c_uint); - let val: &'ll Value = self.const_i32(ia.ctxt.outer_expn().as_u32() as i32); + let val: &'ll Value = self.const_i32(span.ctxt().outer_expn().as_u32() as i32); llvm::LLVMSetMetadata(r, kind, llvm::LLVMMDNodeInContext(self.llcx, &val, 1)); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 33b50401b2..423a2df352 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -273,25 +273,51 @@ pub fn from_fn_attrs( } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { // Special attribute for allocator functions, which can't unwind false - } else if let Some(id) = id { + } else if let Some(_) = id { + // rust-lang/rust#64655, rust-lang/rust#63909: to minimize + // risk associated with changing cases where nounwind + // attribute is attached, this code is deliberately mimicking + // old control flow based on whether `id` is `Some` or `None`. + // + // However, in the long term we should either: + // - fold this into final else (i.e. stop inspecting `id`) + // - or, adopt Rust PR #63909. + // + // see also Rust RFC 2753. + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - if cx.tcx.is_foreign_item(id) { - // Foreign items like `extern "C" { fn foo(); }` are assumed not to - // unwind - false - } else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { - // Any items defined in Rust that *don't* have the `extern` ABI are - // defined to not unwind. We insert shims to abort if an unwind - // happens to enforce this. - false - } else { - // Anything else defined in Rust is assumed that it can possibly - // unwind + if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { + // Any Rust method (or `extern "Rust" fn` or `extern + // "rust-call" fn`) is explicitly allowed to unwind + // (unless it has no-unwind attribute, handled above). true + } else { + // Anything else is either: + // + // 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or + // + // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`). + // + // Foreign items (case 1) are assumed to not unwind; it is + // UB otherwise. (At least for now; see also + // rust-lang/rust#63909 and Rust RFC 2753.) + // + // Items defined in Rust with non-Rust ABIs (case 2) are also + // not supposed to unwind. Whether this should be enforced + // (versus stating it is UB) and *how* it would be enforced + // is currently under discussion; see rust-lang/rust#58794. + // + // In either case, we mark item as explicitly nounwind. + false } } else { // assume this can possibly unwind, avoiding the application of a // `nounwind` attribute below. + // + // (But: See comments in previous branch. Specifically, it is + // unclear whether there is real value in the assumption this + // can unwind. The conservatism here may just be papering over + // a real problem by making some UB a bit harder to hit.) true }); diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index e3b7cb235c..68d3f90cd3 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -12,6 +12,7 @@ use crate::llvm::{self, ArchiveKind}; use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library}; use rustc::session::Session; +use syntax::symbol::Symbol; struct ArchiveConfig<'a> { pub sess: &'a Session, @@ -109,7 +110,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. - fn add_native_library(&mut self, name: &str) { + fn add_native_library(&mut self, name: Symbol) { let location = find_library(name, &self.config.lib_search_paths, self.config.sess); self.add_archive(&location, |_| false).unwrap_or_else(|e| { diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 5ed08943fe..a43fbb68db 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -183,7 +183,7 @@ pub(crate) fn prepare_thin( fn fat_lto(cgcx: &CodegenContext, diag_handler: &Handler, - mut modules: Vec>, + modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, symbol_white_list: &[*const libc::c_char]) @@ -191,6 +191,32 @@ fn fat_lto(cgcx: &CodegenContext, { info!("going for a fat lto"); + // Sort out all our lists of incoming modules into two lists. + // + // * `serialized_modules` (also and argument to this function) contains all + // modules that are serialized in-memory. + // * `in_memory` contains modules which are already parsed and in-memory, + // such as from multi-CGU builds. + // + // All of `cached_modules` (cached from previous incremental builds) can + // immediately go onto the `serialized_modules` modules list and then we can + // split the `modules` array into these two lists. + let mut in_memory = Vec::new(); + serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| { + info!("pushing cached module {:?}", wp.cgu_name); + (buffer, CString::new(wp.cgu_name).unwrap()) + })); + for module in modules { + match module { + FatLTOInput::InMemory(m) => in_memory.push(m), + FatLTOInput::Serialized { name, buffer } => { + info!("pushing serialized module {:?}", name); + let buffer = SerializedModule::Local(buffer); + serialized_modules.push((buffer, CString::new(name).unwrap())); + } + } + } + // Find the "costliest" module and merge everything into that codegen unit. // All the other modules will be serialized and reparsed into the new // context, so this hopefully avoids serializing and parsing the largest @@ -200,14 +226,8 @@ fn fat_lto(cgcx: &CodegenContext, // file copy operations in the backend work correctly. The only other kind // of module here should be an allocator one, and if your crate is smaller // than the allocator module then the size doesn't really matter anyway. - let costliest_module = modules.iter() + let costliest_module = in_memory.iter() .enumerate() - .filter_map(|(i, module)| { - match module { - FatLTOInput::InMemory(m) => Some((i, m)), - FatLTOInput::Serialized { .. } => None, - } - }) .filter(|&(_, module)| module.kind == ModuleKind::Regular) .map(|(i, module)| { let cost = unsafe { @@ -223,26 +243,14 @@ fn fat_lto(cgcx: &CodegenContext, // re-executing the LTO passes. If that's the case deserialize the first // module and create a linker with it. let module: ModuleCodegen = match costliest_module { - Some((_cost, i)) => { - match modules.remove(i) { - FatLTOInput::InMemory(m) => m, - FatLTOInput::Serialized { .. } => unreachable!(), - } - } + Some((_cost, i)) => in_memory.remove(i), None => { - let pos = modules.iter().position(|m| { - match m { - FatLTOInput::InMemory(_) => false, - FatLTOInput::Serialized { .. } => true, - } - }).expect("must have at least one serialized module"); - let (name, buffer) = match modules.remove(pos) { - FatLTOInput::Serialized { name, buffer } => (name, buffer), - FatLTOInput::InMemory(_) => unreachable!(), - }; + assert!(serialized_modules.len() > 0, "must have at least one serialized module"); + let (buffer, name) = serialized_modules.remove(0); + info!("no in-memory regular modules to choose from, parsing {:?}", name); ModuleCodegen { - module_llvm: ModuleLlvm::parse(cgcx, &name, &buffer, diag_handler)?, - name, + module_llvm: ModuleLlvm::parse(cgcx, &name, buffer.data(), diag_handler)?, + name: name.into_string().unwrap(), kind: ModuleKind::Regular, } } @@ -265,25 +273,13 @@ fn fat_lto(cgcx: &CodegenContext, // and we want to move everything to the same LLVM context. Currently the // way we know of to do that is to serialize them to a string and them parse // them later. Not great but hey, that's why it's "fat" LTO, right? - let mut new_modules = modules.into_iter().map(|module| { - match module { - FatLTOInput::InMemory(module) => { - let buffer = ModuleBuffer::new(module.module_llvm.llmod()); - let llmod_id = CString::new(&module.name[..]).unwrap(); - (SerializedModule::Local(buffer), llmod_id) - } - FatLTOInput::Serialized { name, buffer } => { - let llmod_id = CString::new(name).unwrap(); - (SerializedModule::Local(buffer), llmod_id) - } - } - }).collect::>(); + for module in in_memory { + let buffer = ModuleBuffer::new(module.module_llvm.llmod()); + let llmod_id = CString::new(&module.name[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } // Sort the modules to ensure we produce deterministic results. - new_modules.sort_by(|module1, module2| module1.1.partial_cmp(&module2.1).unwrap()); - serialized_modules.extend(new_modules); - serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| { - (buffer, CString::new(wp.cgu_name).unwrap()) - })); + serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1)); // For all serialized bitcode files we parse them and link them in as we did // above, this is all mostly handled in C++. Like above, though, we don't @@ -850,7 +846,7 @@ fn module_name_to_str(c_str: &CStr) -> &str { bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e)) } -fn parse_module<'a>( +pub fn parse_module<'a>( cx: &'a llvm::Context, name: &CStr, data: &[u8], diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 894e5c2fd3..423a01ad1f 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -5,7 +5,6 @@ use crate::context::CodegenCx; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use syntax::symbol::LocalInternedString; use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate}; use rustc_codegen_ssa::MemFlags; use libc::{c_uint, c_char}; @@ -24,6 +23,7 @@ use std::ffi::CStr; use std::ops::{Deref, Range}; use std::ptr; use std::iter::TrustedLen; +use syntax::symbol::Symbol; // All Builders must have an llfn associated with them #[must_use] @@ -387,23 +387,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) } - fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); - bx.dynamic_alloca(ty, name, align) + bx.dynamic_alloca(ty, align) } - fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { unsafe { - let alloca = if name.is_empty() { - llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED) - } else { - let name = SmallCStr::new(name); - llvm::LLVMBuildAlloca(self.llbuilder, ty, - name.as_ptr()) - }; + let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } @@ -412,16 +406,9 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, - name: &str, align: Align) -> &'ll Value { unsafe { - let alloca = if name.is_empty() { - llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED) - } else { - let name = SmallCStr::new(name); - llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, - name.as_ptr()) - }; + let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } @@ -561,7 +548,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem.val.store(&mut body_bx, - PlaceRef::new_sized(current, cg_elem.layout, align)); + PlaceRef::new_sized_aligned(current, cg_elem.layout, align)); let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]); body_bx.br(header_bx.llbb()); @@ -1082,8 +1069,8 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { fn static_panic_msg( &mut self, - msg: Option, - filename: LocalInternedString, + msg: Option, + filename: Symbol, line: Self::Value, col: Self::Value, kind: &str, diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 2c0a6f631b..35d5107842 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -37,7 +37,7 @@ pub fn get_fn( return llfn; } - let sym = tcx.symbol_name(instance).as_str(); + let sym = tcx.symbol_name(instance).name.as_str(); debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); // Create a fn pointer with the substituted signature. diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index b0c94a139b..6fbea9646b 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -17,7 +17,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use libc::{c_uint, c_char}; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax::ast::Mutability; pub use crate::context::CodegenCx; @@ -122,7 +122,7 @@ impl CodegenCx<'ll, 'tcx> { fn const_cstr( &self, - s: LocalInternedString, + s: Symbol, null_terminated: bool, ) -> &'ll Value { unsafe { @@ -130,9 +130,10 @@ impl CodegenCx<'ll, 'tcx> { return llval; } + let s_str = s.as_str(); let sc = llvm::LLVMConstStringInContext(self.llcx, - s.as_ptr() as *const c_char, - s.len() as c_uint, + s_str.as_ptr() as *const c_char, + s_str.len() as c_uint, !null_terminated as Bool); let sym = self.generate_local_symbol_name("str"); let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(||{ @@ -147,8 +148,8 @@ impl CodegenCx<'ll, 'tcx> { } } - pub fn const_str_slice(&self, s: LocalInternedString) -> &'ll Value { - let len = s.len(); + pub fn const_str_slice(&self, s: Symbol) -> &'ll Value { + let len = s.as_str().len(); let cs = consts::ptrcast(self.const_cstr(s, false), self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self))); self.const_fat_ptr(cs, self.const_usize(len as u64)) @@ -333,16 +334,22 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { offset: Size, ) -> PlaceRef<'tcx, &'ll Value> { assert_eq!(alloc.align, layout.align.abi); - let init = const_alloc_to_llvm(self, alloc); - let base_addr = self.static_addr_of(init, alloc.align, None); - - let llval = unsafe { llvm::LLVMConstInBoundsGEP( - self.const_bitcast(base_addr, self.type_i8p()), - &self.const_usize(offset.bytes()), - 1, - )}; - let llval = self.const_bitcast(llval, self.type_ptr_to(layout.llvm_type(self))); - PlaceRef::new_sized(llval, layout, alloc.align) + let llty = self.type_ptr_to(layout.llvm_type(self)); + let llval = if layout.size == Size::ZERO { + let llval = self.const_usize(alloc.align.bytes()); + unsafe { llvm::LLVMConstIntToPtr(llval, llty) } + } else { + let init = const_alloc_to_llvm(self, alloc); + let base_addr = self.static_addr_of(init, alloc.align, None); + + let llval = unsafe { llvm::LLVMConstInBoundsGEP( + self.const_bitcast(base_addr, self.type_i8p()), + &self.const_usize(offset.bytes()), + 1, + )}; + self.const_bitcast(llval, llty) + }; + PlaceRef::new_sized(llval, layout) } fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 0077df3cf5..e71d1fc169 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -11,12 +11,11 @@ use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint, Pointer, ErrorHandled, GlobalId}; use rustc::mir::mono::MonoItem; use rustc::hir::Node; -use syntax_pos::Span; use rustc_target::abi::HasDataLayout; -use syntax::symbol::sym; -use syntax_pos::symbol::LocalInternedString; use rustc::ty::{self, Ty, Instance}; use rustc_codegen_ssa::traits::*; +use syntax::symbol::{Symbol, sym}; +use syntax_pos::Span; use rustc::ty::layout::{self, Size, Align, LayoutOf}; @@ -25,21 +24,31 @@ use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; use std::ffi::{CStr, CString}; pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { - let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1); + let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, ((), alloc_id)) in alloc.relocations.iter() { + for &(offset, ((), alloc_id)) in alloc.relocations().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset])); + // This `inspect` is okay since we have checked that it is not within a relocation, it + // is within the bounds of the allocation, and it doesn't affect interpreter execution + // (we inspect the result after interpreter execution). Any undef byte is replaced with + // some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset); + llvals.push(cx.const_bytes(bytes)); } let ptr_offset = read_target_uint( dl.endian, - &alloc.bytes[offset..(offset + pointer_size)], + // This `inspect` is okay since it is within the bounds of the allocation, it doesn't + // affect interpreter execution (we inspect the result after interpreter execution), + // and we properly interpret the relocation as a relocation pointer offset. + alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64; llvals.push(cx.scalar_to_backend( Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(), @@ -51,8 +60,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll )); next_offset = offset + pointer_size; } - if alloc.bytes.len() >= next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..])); + if alloc.len() >= next_offset { + let range = next_offset..alloc.len(); + // This `inspect` is okay since we have check that it is after all relocations, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with some + // arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range); + llvals.push(cx.const_bytes(bytes)); } cx.const_struct(&llvals, true) @@ -104,10 +121,11 @@ fn check_and_apply_linkage( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, - sym: LocalInternedString, + sym: Symbol, span: Span ) -> &'ll Value { let llty = cx.layout_of(ty).llvm_type(cx); + let sym = sym.as_str(); if let Some(linkage) = attrs.linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -203,7 +221,7 @@ impl CodegenCx<'ll, 'tcx> { def_id); let ty = instance.ty(self.tcx); - let sym = self.tcx.symbol_name(instance).as_str(); + let sym = self.tcx.symbol_name(instance).name.as_symbol(); debug!("get_static: sym={} instance={:?}", sym, instance); @@ -214,11 +232,12 @@ impl CodegenCx<'ll, 'tcx> { Node::Item(&hir::Item { ref attrs, span, node: hir::ItemKind::Static(..), .. }) => { - if self.get_declared_value(&sym[..]).is_some() { + let sym_str = sym.as_str(); + if self.get_declared_value(&sym_str).is_some() { span_bug!(span, "Conflicting symbol names for static?"); } - let g = self.define_global(&sym[..], llty).unwrap(); + let g = self.define_global(&sym_str, llty).unwrap(); if !self.tcx.is_reachable_non_generic(def_id) { unsafe { @@ -437,7 +456,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.target.options.is_like_osx { - let sect_name = if alloc.bytes.iter().all(|b| *b == 0) { + assert_eq!(alloc.relocations().len(), 0); + + let is_zeroed = { + // Treats undefined bytes as if they were defined with the byte value that + // happens to be currently assigned in mir. This is valid since reading + // undef bytes may yield arbitrary values. + // + // FIXME: ignore undef bytes even with representation `!= 0`. + // + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state + // (not as part of the interpreter execution). + alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()) + .iter() + .all(|b| *b == 0) + }; + let sect_name = if is_zeroed { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0") } else { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0") @@ -456,10 +491,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { section.as_str().as_ptr() as *const _, section.as_str().len() as c_uint, ); + assert!(alloc.relocations().is_empty()); + + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state (not + // as part of the interpreter execution). + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter( + 0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, - alloc.bytes.as_ptr() as *const _, - alloc.bytes.len() as c_uint, + bytes.as_ptr() as *const _, + bytes.len() as c_uint, ); let data = [section, alloc]; let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index a2aaaddf09..58ce970390 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -29,7 +29,7 @@ use std::cell::{Cell, RefCell}; use std::iter; use std::str; use std::sync::Arc; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax::source_map::{DUMMY_SP, Span}; use crate::abi::Abi; @@ -52,7 +52,7 @@ pub struct CodegenCx<'ll, 'tcx> { pub vtables: RefCell, Option>), &'ll Value>>, /// Cache of constant strings, - pub const_cstr_cache: RefCell>, + pub const_cstr_cache: RefCell>, /// Reverse-direction for const ptrs cast from globals. /// Key is a Value holding a *T, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 928532a1f4..d0b607bd88 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -2251,7 +2251,7 @@ pub fn create_global_var_metadata( None } else { let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); - Some(SmallCStr::new(&linkage_name.as_str())) + Some(SmallCStr::new(&linkage_name.name.as_str())) }; let global_align = cx.align_of(variable_type); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 548ea0b103..6dedf10f0a 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -32,7 +32,7 @@ use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, Variable use libc::c_uint; use std::cell::RefCell; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use syntax_pos::{self, Span, Pos}; use syntax::ast; @@ -224,8 +224,37 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { gdb::insert_reference_to_gdb_debug_scripts_section_global(self) } - fn set_value_name(&mut self, value: &'ll Value, name: &str) { - let cname = SmallCStr::new(name); + fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) { + // Avoid wasting time if LLVM value names aren't even enabled. + if self.sess().fewer_names() { + return; + } + + // Only function parameters and instructions are local to a function, + // don't change the name of anything else (e.g. globals). + let param_or_inst = unsafe { + llvm::LLVMIsAArgument(value).is_some() || + llvm::LLVMIsAInstruction(value).is_some() + }; + if !param_or_inst { + return; + } + + let old_name = unsafe { + CStr::from_ptr(llvm::LLVMGetValueName(value)) + }; + match old_name.to_str() { + Ok("") => {} + Ok(_) => { + // Avoid replacing the name if it already exists. + // While we could combine the names somehow, it'd + // get noisy quick, and the usefulness is dubious. + return; + } + Err(_) => return, + } + + let cname = CString::new(name.to_string()).unwrap(); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } @@ -290,7 +319,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let scope_line = span_start(self, span).line; let function_name = CString::new(name).unwrap(); - let linkage_name = SmallCStr::new(&linkage_name.as_str()); + let linkage_name = SmallCStr::new(&linkage_name.name.as_str()); let mut flags = DIFlags::FlagPrototyped; diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs index c6b5dc03a6..042e51ed2b 100644 --- a/src/librustc_codegen_llvm/error_codes.rs +++ b/src/librustc_codegen_llvm/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +register_diagnostics! { E0511: r##" Invalid monomorphization of an intrinsic function was used. Erroneous code diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a9b8962f45..3f3c5ac146 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -15,6 +15,7 @@ use rustc_codegen_ssa::glue; use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; +use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; @@ -81,13 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, - callee_ty: Ty<'tcx>, + instance: ty::Instance<'tcx>, fn_ty: &FnType<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, &'ll Value>], llresult: &'ll Value, span: Span, ) { let tcx = self.tcx; + let callee_ty = instance.ty(tcx); let (def_id, substs) = match callee_ty.sty { ty::FnDef(def_id, substs) => (def_id, substs), @@ -101,7 +103,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let name = &*tcx.item_name(def_id).as_str(); let llret_ty = self.layout_of(ret_ty).llvm_type(self); - let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align.abi); + let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout); let simple = get_simple_intrinsic(self, name); let llval = match name { @@ -133,10 +135,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let llfn = self.get_intrinsic(&("llvm.debugtrap")); self.call(llfn, &[], None) } - "size_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.size_of(tp_ty).bytes()) - } "va_start" => { self.va_start(args[0].immediate()) } @@ -188,10 +186,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.const_usize(self.size_of(tp_ty).bytes()) } } - "min_align_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.align_of(tp_ty).bytes()) - } "min_align_of_val" => { let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { @@ -201,18 +195,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.const_usize(self.align_of(tp_ty).bytes()) } } - "pref_align_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.layout_of(tp_ty).align.pref.bytes()) - } + "size_of" | + "pref_align_of" | + "min_align_of" | + "needs_drop" | + "type_id" | "type_name" => { - let tp_ty = substs.type_at(0); - let ty_name = self.tcx.type_name(tp_ty); + let gid = GlobalId { + instance, + promoted: None, + }; + let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap(); OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self) } - "type_id" => { - self.const_u64(self.tcx.type_id_hash(substs.type_at(0))) - } "init" => { let ty = substs.type_at(0); if !self.layout_of(ty).is_zst() { @@ -235,11 +230,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "uninit" | "forget" => { return; } - "needs_drop" => { - let tp_ty = substs.type_at(0); - - self.const_bool(self.type_needs_drop(tp_ty)) - } "offset" => { let ptr = args[0].immediate(); let offset = args[1].immediate(); @@ -328,7 +318,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }, "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "bitreverse" | "add_with_overflow" | "sub_with_overflow" | - "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" | "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => { @@ -398,9 +388,9 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; }, - "overflowing_add" => self.add(args[0].immediate(), args[1].immediate()), - "overflowing_sub" => self.sub(args[0].immediate(), args[1].immediate()), - "overflowing_mul" => self.mul(args[0].immediate(), args[1].immediate()), + "wrapping_add" => self.add(args[0].immediate(), args[1].immediate()), + "wrapping_sub" => self.sub(args[0].immediate(), args[1].immediate()), + "wrapping_mul" => self.mul(args[0].immediate(), args[1].immediate()), "exact_div" => if signed { self.exactsdiv(args[0].immediate(), args[1].immediate()) @@ -871,7 +861,7 @@ fn codegen_msvc_try( // More information can be found in libstd's seh.rs implementation. let i64p = bx.type_ptr_to(bx.type_i64()); let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let slot = bx.alloca(i64p, "slot", ptr_align); + let slot = bx.alloca(i64p, ptr_align); bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); normal.ret(bx.const_i32(0)); diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 653dd8868f..34e39af3c3 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -14,7 +14,6 @@ #![feature(in_band_lifetimes)] #![feature(libc)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(optin_builtin_traits)] #![feature(concat_idents)] #![feature(link_args)] @@ -54,6 +53,7 @@ use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; use std::sync::{mpsc, Arc}; +use std::ffi::CStr; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; @@ -226,21 +226,21 @@ impl CodegenBackend for LlvmCodegenBackend { for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() { println!(" {}", name); } - println!(""); + println!(); } PrintRequest::CodeModels => { println!("Available code models:"); for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){ println!(" {}", name); } - println!(""); + println!(); } PrintRequest::TlsModels => { println!("Available TLS models:"); for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){ println!(" {}", name); } - println!(""); + println!(); } req => llvm_util::print(req, sess), } @@ -255,7 +255,7 @@ impl CodegenBackend for LlvmCodegenBackend { } fn diagnostics(&self) -> &[(&'static str, &'static str)] { - &DIAGNOSTICS + &error_codes::DIAGNOSTICS } fn target_features(&self, sess: &Session) -> Vec { @@ -386,13 +386,13 @@ impl ModuleLlvm { fn parse( cgcx: &CodegenContext, - name: &str, - buffer: &back::lto::ModuleBuffer, + name: &CStr, + buffer: &[u8], handler: &Handler, ) -> Result { unsafe { let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod_raw = buffer.parse(name, llcx, handler)?; + let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?; let tm = match (cgcx.tm_factory.0)() { Ok(m) => m, Err(e) => { @@ -424,5 +424,3 @@ impl Drop for ModuleLlvm { } } } - -__build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 9f9410560e..b07214fdc0 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -806,6 +806,7 @@ extern "C" { pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute); // Operations on parameters + pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; pub fn LLVMCountParams(Fn: &Value) -> c_uint; pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value; @@ -818,6 +819,7 @@ extern "C" { pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); // Operations on instructions + pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock; // Operations on call sites diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 89a6ec27fe..bc028d6624 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -17,8 +17,8 @@ memmap = "0.6" log = "0.4.5" libc = "0.2.44" jobserver = "0.1.11" -parking_lot = "0.7" -tempfile = "3.0.5" +parking_lot = "0.9" +tempfile = "3.1" rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs index 23d580ef08..8d2120a345 100644 --- a/src/librustc_codegen_ssa/back/archive.rs +++ b/src/librustc_codegen_ssa/back/archive.rs @@ -1,9 +1,10 @@ use rustc::session::Session; +use syntax::symbol::Symbol; use std::io; use std::path::{Path, PathBuf}; -pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) +pub fn find_library(name: Symbol, search_paths: &[PathBuf], sess: &Session) -> PathBuf { // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib @@ -40,7 +41,7 @@ pub trait ArchiveBuilder<'a> { lto: bool, skip_objects: bool, ) -> io::Result<()>; - fn add_native_library(&mut self, name: &str); + fn add_native_library(&mut self, name: Symbol); fn update_symbols(&mut self); fn build(self); diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index 340cc772e5..2d84d67e3c 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -8,12 +8,14 @@ use std::mem; use std::process::{self, Output}; use rustc_target::spec::LldFlavor; +use syntax::symbol::Symbol; #[derive(Clone)] pub struct Command { program: Program, args: Vec, env: Vec<(OsString, OsString)>, + env_remove: Vec, } #[derive(Clone)] @@ -41,6 +43,7 @@ impl Command { program, args: Vec::new(), env: Vec::new(), + env_remove: Vec::new(), } } @@ -49,6 +52,11 @@ impl Command { self } + pub fn sym_arg(&mut self, arg: Symbol) -> &mut Command { + self.arg(&arg.as_str()); + self + } + pub fn args(&mut self, args: I) -> &mut Command where I: IntoIterator>, @@ -75,6 +83,17 @@ impl Command { self.env.push((key.to_owned(), value.to_owned())); } + pub fn env_remove(&mut self, key: K) -> &mut Command + where K: AsRef, + { + self._env_remove(key.as_ref()); + self + } + + fn _env_remove(&mut self, key: &OsStr) { + self.env_remove.push(key.to_owned()); + } + pub fn output(&mut self) -> io::Result { self.command().output() } @@ -100,6 +119,9 @@ impl Command { }; ret.args(&self.args); ret.envs(self.env.clone()); + for k in &self.env_remove { + ret.env_remove(k); + } return ret } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 8fb0828285..9b044d9b45 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -13,6 +13,7 @@ use rustc::hir::def_id::CrateNum; use rustc_data_structures::fx::FxHashSet; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor}; +use syntax::symbol::Symbol; use crate::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION, CrateInfo, CodegenResults}; use super::archive::ArchiveBuilder; @@ -32,6 +33,7 @@ use std::path::{Path, PathBuf}; use std::process::{Output, Stdio, ExitStatus}; use std::str; use std::env; +use std::ffi::OsString; pub use rustc_codegen_utils::link::*; @@ -158,6 +160,36 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB } }; + // UWP apps have API restrictions enforced during Store submissions. + // To comply with the Windows App Certification Kit, + // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). + let t = &sess.target.target; + if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" { + if let Some(ref tool) = msvc_tool { + let original_path = tool.path(); + if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() { + let arch = match t.arch.as_str() { + "x86_64" => Some("x64".to_string()), + "x86" => Some("x86".to_string()), + "aarch64" => Some("arm64".to_string()), + _ => None, + }; + if let Some(ref a) = arch { + let mut arg = OsString::from("/LIBPATH:"); + arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a.to_string())); + cmd.arg(&arg); + } + else { + warn!("arch is not supported"); + } + } else { + warn!("MSVC root path lib location not found"); + } + } else { + warn!("link.exe not found"); + } + } + // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) @@ -285,7 +317,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, NativeLibraryKind::NativeUnknown => continue, } if let Some(name) = lib.name { - ab.add_native_library(&name.as_str()); + ab.add_native_library(name); } } @@ -501,6 +533,9 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, for &(ref k, ref v) in &sess.target.target.options.link_env { cmd.env(k, v); } + for k in &sess.target.target.options.link_env_remove { + cmd.env_remove(k); + } if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); @@ -1027,6 +1062,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, let t = &sess.target.target; cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { cmd.add_object(obj); } @@ -1241,15 +1277,14 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker, let search_path = archive_search_paths(sess); for lib in relevant_libs { let name = match lib.name { - Some(ref l) => l, + Some(l) => l, None => continue, }; match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&name.as_str()), - NativeLibraryKind::NativeFramework => cmd.link_framework(&name.as_str()), - NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&name.as_str()), - NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&name.as_str(), - &search_path) + NativeLibraryKind::NativeUnknown => cmd.link_dylib(name), + NativeLibraryKind::NativeFramework => cmd.link_framework(name), + NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(name), + NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path) } } } @@ -1562,7 +1597,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); } let filestem = cratepath.file_stem().unwrap().to_str().unwrap(); - cmd.link_rust_dylib(&unlib(&sess.target, filestem), + cmd.link_rust_dylib(Symbol::intern(&unlib(&sess.target, filestem)), parent.unwrap_or(Path::new(""))); } } @@ -1605,22 +1640,22 @@ pub fn add_upstream_native_libraries(cmd: &mut dyn Linker, for &(cnum, _) in crates { for lib in codegen_results.crate_info.native_libraries[&cnum].iter() { let name = match lib.name { - Some(ref l) => l, + Some(l) => l, None => continue, }; if !relevant_lib(sess, &lib) { continue } match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&name.as_str()), - NativeLibraryKind::NativeFramework => cmd.link_framework(&name.as_str()), + NativeLibraryKind::NativeUnknown => cmd.link_dylib(name), + NativeLibraryKind::NativeFramework => cmd.link_framework(name), NativeLibraryKind::NativeStaticNobundle => { // Link "static-nobundle" native libs only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically // or is an rlib already included via some other dylib crate, the symbols from // native libs will have already been included in that dylib. if data[cnum.as_usize() - 1] == Linkage::Static { - cmd.link_staticlib(&name.as_str()) + cmd.link_staticlib(name) } }, // ignore statically included native libraries here as we've diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 26091005f2..c42cd02492 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -17,6 +17,7 @@ use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use rustc_serialize::{json, Encoder}; +use syntax::symbol::Symbol; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -99,13 +100,13 @@ impl LinkerInfo { /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an /// MSVC linker (e.g., `link.exe`) is being used. pub trait Linker { - fn link_dylib(&mut self, lib: &str); - fn link_rust_dylib(&mut self, lib: &str, path: &Path); - fn link_framework(&mut self, framework: &str); - fn link_staticlib(&mut self, lib: &str); + fn link_dylib(&mut self, lib: Symbol); + fn link_rust_dylib(&mut self, lib: Symbol, path: &Path); + fn link_framework(&mut self, framework: Symbol); + fn link_staticlib(&mut self, lib: Symbol); fn link_rlib(&mut self, lib: &Path); fn link_whole_rlib(&mut self, lib: &Path); - fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]); + fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]); fn include_path(&mut self, path: &Path); fn framework_path(&mut self, path: &Path); fn output_filename(&mut self, path: &Path); @@ -215,9 +216,13 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { - fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); } - fn link_staticlib(&mut self, lib: &str) { - self.hint_static(); self.cmd.arg(format!("-l{}", lib)); + fn link_dylib(&mut self, lib: Symbol) { + self.hint_dynamic(); + self.cmd.arg(format!("-l{}", lib)); + } + fn link_staticlib(&mut self, lib: Symbol) { + self.hint_static(); + self.cmd.arg(format!("-l{}", lib)); } fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); } fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } @@ -232,14 +237,14 @@ impl<'a> Linker for GccLinker<'a> { fn build_static_executable(&mut self) { self.cmd.arg("-static"); } fn args(&mut self, args: &[String]) { self.cmd.args(args); } - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { + fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); } - fn link_framework(&mut self, framework: &str) { + fn link_framework(&mut self, framework: Symbol) { self.hint_dynamic(); - self.cmd.arg("-framework").arg(framework); + self.cmd.arg("-framework").sym_arg(framework); } // Here we explicitly ask that the entire archive is included into the @@ -248,7 +253,7 @@ impl<'a> Linker for GccLinker<'a> { // don't otherwise explicitly reference them. This can occur for // libraries which are just providing bindings, libraries with generic // functions, etc. - fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) { + fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) { self.hint_static(); let target = &self.sess.target.target; if !target.options.is_like_osx { @@ -430,10 +435,13 @@ impl<'a> Linker for GccLinker<'a> { // Write an LD version script let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); - writeln!(f, "{{\n global:")?; - for sym in self.info.exports[&crate_type].iter() { - debug!(" {};", sym); - writeln!(f, " {};", sym)?; + writeln!(f, "{{")?; + if !self.info.exports[&crate_type].is_empty() { + writeln!(f, " global:")?; + for sym in self.info.exports[&crate_type].iter() { + debug!(" {};", sym); + writeln!(f, " {};", sym)?; + } } writeln!(f, "\n local:\n *;\n}};")?; }; @@ -536,11 +544,11 @@ impl<'a> Linker for MsvcLinker<'a> { } } - fn link_dylib(&mut self, lib: &str) { + fn link_dylib(&mut self, lib: Symbol) { self.cmd.arg(&format!("{}.lib", lib)); } - fn link_rust_dylib(&mut self, lib: &str, path: &Path) { + fn link_rust_dylib(&mut self, lib: Symbol, path: &Path) { // When producing a dll, the MSVC linker may not actually emit a // `foo.lib` file if the dll doesn't actually export any symbols, so we // check to see if the file is there and just omit linking to it if it's @@ -551,7 +559,7 @@ impl<'a> Linker for MsvcLinker<'a> { } } - fn link_staticlib(&mut self, lib: &str) { + fn link_staticlib(&mut self, lib: Symbol) { self.cmd.arg(&format!("{}.lib", lib)); } @@ -602,11 +610,11 @@ impl<'a> Linker for MsvcLinker<'a> { fn framework_path(&mut self, _path: &Path) { bug!("frameworks are not supported on windows") } - fn link_framework(&mut self, _framework: &str) { + fn link_framework(&mut self, _framework: Symbol) { bug!("frameworks are not supported on windows") } - fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) { + fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) { // not supported? self.link_staticlib(lib); } @@ -737,8 +745,8 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.arg("-L").arg(path); } - fn link_staticlib(&mut self, lib: &str) { - self.cmd.arg("-l").arg(lib); + fn link_staticlib(&mut self, lib: Symbol) { + self.cmd.arg("-l").sym_arg(lib); } fn output_filename(&mut self, path: &Path) { @@ -749,12 +757,12 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.arg(path); } - fn link_dylib(&mut self, lib: &str) { + fn link_dylib(&mut self, lib: Symbol) { // Emscripten always links statically self.link_staticlib(lib); } - fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) { + fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) { // not supported? self.link_staticlib(lib); } @@ -764,7 +772,7 @@ impl<'a> Linker for EmLinker<'a> { self.link_rlib(lib); } - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { + fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) { self.link_dylib(lib); } @@ -800,7 +808,7 @@ impl<'a> Linker for EmLinker<'a> { bug!("frameworks are not supported on Emscripten") } - fn link_framework(&mut self, _framework: &str) { + fn link_framework(&mut self, _framework: Symbol) { bug!("frameworks are not supported on Emscripten") } @@ -945,12 +953,12 @@ impl<'a> WasmLd<'a> { } impl<'a> Linker for WasmLd<'a> { - fn link_dylib(&mut self, lib: &str) { - self.cmd.arg("-l").arg(lib); + fn link_dylib(&mut self, lib: Symbol) { + self.cmd.arg("-l").sym_arg(lib); } - fn link_staticlib(&mut self, lib: &str) { - self.cmd.arg("-l").arg(lib); + fn link_staticlib(&mut self, lib: Symbol) { + self.cmd.arg("-l").sym_arg(lib); } fn link_rlib(&mut self, lib: &Path) { @@ -992,16 +1000,16 @@ impl<'a> Linker for WasmLd<'a> { self.cmd.args(args); } - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { - self.cmd.arg("-l").arg(lib); + fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) { + self.cmd.arg("-l").sym_arg(lib); } - fn link_framework(&mut self, _framework: &str) { + fn link_framework(&mut self, _framework: Symbol) { panic!("frameworks not supported") } - fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) { - self.cmd.arg("-l").arg(lib); + fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) { + self.cmd.arg("-l").sym_arg(lib); } fn link_whole_rlib(&mut self, lib: &Path) { @@ -1159,19 +1167,19 @@ impl<'a> Linker for PtxLinker<'a> { ::std::mem::replace(&mut self.cmd, Command::new("")) } - fn link_dylib(&mut self, _lib: &str) { + fn link_dylib(&mut self, _lib: Symbol) { panic!("external dylibs not supported") } - fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) { + fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) { panic!("external dylibs not supported") } - fn link_staticlib(&mut self, _lib: &str) { + fn link_staticlib(&mut self, _lib: Symbol) { panic!("staticlibs not supported") } - fn link_whole_staticlib(&mut self, _lib: &str, _search_path: &[PathBuf]) { + fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) { panic!("staticlibs not supported") } @@ -1179,7 +1187,7 @@ impl<'a> Linker for PtxLinker<'a> { panic!("frameworks not supported") } - fn link_framework(&mut self, _framework: &str) { + fn link_framework(&mut self, _framework: Symbol) { panic!("frameworks not supported") } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 2d9220f897..7e700e6819 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -121,7 +121,7 @@ fn reachable_non_generics_provider( }) .map(|def_id| { let export_level = if special_runtime_crate { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str(); + let name = tcx.symbol_name(Instance::mono(tcx, def_id)).name.as_str(); // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index c9e4663fdb..1bba479c1f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -22,12 +22,11 @@ use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry}; use rustc::util::profiling::SelfProfiler; use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; -use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; +use rustc_errors::{Handler, Level, FatalError, DiagnosticId}; use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; use syntax::ext::hygiene::ExpnId; -use syntax_pos::MultiSpan; use syntax_pos::symbol::{Symbol, sym}; use jobserver::{Client, Acquired}; @@ -1725,7 +1724,7 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + fn emit_diagnostic(&mut self, db: &rustc_errors::Diagnostic) { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msg: db.message(), code: db.code.clone(), @@ -1760,25 +1759,15 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let handler = sess.diagnostic(); - match diag.code { - Some(ref code) => { - handler.emit_with_code(&MultiSpan::new(), - &diag.msg, - code.clone(), - diag.lvl); - } - None => { - handler.emit(&MultiSpan::new(), - &diag.msg, - diag.lvl); - } + let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg); + if let Some(code) = diag.code { + d.code(code); } + handler.emit_diagnostic(&d); + handler.abort_if_errors_and_should_abort(); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => { - match ExpnId::from_u32(cookie).expn_info() { - Some(ei) => sess.span_err(ei.call_site, &msg), - None => sess.err(&msg), - } + sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg) } Ok(SharedEmitterMessage::AbortIfErrors) => { sess.abort_if_errors(); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index cdc54bb179..4acbe0356b 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -456,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' let arg_argv = param_argv; let (start_fn, args) = if use_start_lang_item { - let start_def_id = cx.tcx().require_lang_item(StartFnLangItem); + let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); let start_fn = callee::resolve_and_get_fn( cx, start_def_id, diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs index 8d46dcb7c0..8ff41c275a 100644 --- a/src/librustc_codegen_ssa/error_codes.rs +++ b/src/librustc_codegen_ssa/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0668: r##" Malformed inline assembly rejected by LLVM. diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 68640abb04..1708d7235b 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -4,7 +4,7 @@ #![feature(box_syntax)] #![feature(core_intrinsics)] #![feature(libc)] -#![feature(rustc_diagnostic_macros)] +#![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] @@ -35,8 +35,6 @@ use rustc_data_structures::svh::Svh; use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary}; use syntax_pos::symbol::Symbol; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. mod error_codes; pub mod common; @@ -158,5 +156,3 @@ pub struct CodegenResults { pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } - -__build_diagnostic_array! { librustc_codegen_ssa, DIAGNOSTICS } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index cc0c733c22..d192f2ffb6 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -105,7 +105,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { ) { let cx = self.fx.cx; - if let Some(proj) = place_ref.projection { + if let [proj_base @ .., elem] = place_ref.projection { // Allow uses of projections that are ZSTs or from scalar fields. let is_consume = match context { PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | @@ -114,12 +114,12 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, &proj.base, self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. let elem_ty = base_ty - .projection_ty(cx.tcx(), &proj.elem) + .projection_ty(cx.tcx(), elem) .ty; let elem_ty = self.fx.monomorphize(&elem_ty); let span = if let mir::PlaceBase::Local(index) = place_ref.base { @@ -131,7 +131,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { return; } - if let mir::ProjectionElem::Field(..) = proj.elem { + if let mir::ProjectionElem::Field(..) = elem { let layout = cx.spanned_layout_of(base_ty.ty, span); if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) { // Recurse with the same context, instead of `Projection`, @@ -140,7 +140,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { self.process_place( &mir::PlaceRef { base: place_ref.base, - projection: &proj.base, + projection: proj_base, }, context, location, @@ -151,11 +151,11 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { } // A deref projection only reads the pointer, never needs the place. - if let mir::ProjectionElem::Deref = proj.elem { + if let mir::ProjectionElem::Deref = elem { self.process_place( &mir::PlaceRef { base: place_ref.base, - projection: &proj.base, + projection: proj_base, }, PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), location @@ -168,7 +168,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { // visit_place API let mut context = context; - if place_ref.projection.is_some() { + if !place_ref.projection.is_empty() { context = if context.is_mutating_use() { PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { @@ -177,10 +177,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { } self.visit_place_base(place_ref.base, context, location); - - if let Some(box proj) = place_ref.projection { - self.visit_projection(place_ref.base, proj, context, location); - } + self.visit_projection(place_ref.base, place_ref.projection, context, location); } } @@ -196,7 +193,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> if let mir::Place { base: mir::PlaceBase::Local(index), - projection: None, + projection: box [], } = *place { self.assign(index, location); let decl_span = self.fx.mir.local_decls[index].source_info.span; @@ -221,7 +218,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. - } => match c.ty.sty { + } => match c.literal.ty.sty { ty::FnDef(did, _) => Some((did, args)), _ => None, }, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ce98979cc0..1bb0ea5dae 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -14,7 +14,7 @@ use crate::traits::*; use std::borrow::Cow; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax_pos::Pos; use super::{FunctionCx, LocalRef}; @@ -253,7 +253,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { PassMode::Direct(_) | PassMode::Pair(..) => { let op = - self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_ref()); + self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); if let Ref(llval, _, align) = op.val { bx.load(llval, align) } else { @@ -276,7 +276,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llslot = match op.val { Immediate(_) | Pair(..) => { let scratch = - PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout, "ret"); + PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout); op.val.store(&mut bx, scratch); scratch.llval } @@ -397,7 +397,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Get the location information. let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = LocalInternedString::intern(&loc.file.name.to_string()); + let filename = Symbol::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -418,8 +418,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { vec![file_line_col, index, len]) } _ => { - let str = msg.description(); - let msg_str = LocalInternedString::intern(str); + let msg_str = Symbol::intern(msg.description()); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, @@ -531,7 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); if layout.abi.is_uninhabited() { let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = LocalInternedString::intern(&loc.file.name.to_string()); + let filename = Symbol::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -539,7 +538,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "Attempted to instantiate uninhabited type {}", ty ); - let msg_str = LocalInternedString::intern(&str); + let msg_str = Symbol::intern(&str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, @@ -609,19 +608,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Operand::Copy( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), - projection: None, + projection: box [], } ) | mir::Operand::Move( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), - projection: None, + projection: box [], } ) => { let param_env = ty::ParamEnv::reveal_all(); @@ -651,7 +652,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (llval, ty) = self.simd_shuffle_indices( &bx, constant.span, - constant.ty, + constant.literal.ty, c, ); return OperandRef { @@ -666,8 +667,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }).collect(); - let callee_ty = instance.as_ref().unwrap().ty(bx.tcx()); - bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest, + bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest, terminator.source_info.span); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { @@ -766,7 +766,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match (arg, op.val) { (&mir::Operand::Copy(_), Ref(_, None, _)) | (&mir::Operand::Constant(_), Ref(_, None, _)) => { - let tmp = PlaceRef::alloca(&mut bx, op.layout, "const"); + let tmp = PlaceRef::alloca(&mut bx, op.layout); op.val.store(&mut bx, tmp); op.val = Ref(tmp.llval, None, tmp.align); } @@ -924,7 +924,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Immediate(_) | Pair(..) => { match arg.mode { PassMode::Indirect(..) | PassMode::Cast(_) => { - let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); + let scratch = PlaceRef::alloca(bx, arg.layout); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) } @@ -939,7 +939,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't // have scary latent bugs around. - let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); + let scratch = PlaceRef::alloca(bx, arg.layout); base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align, op.layout, MemFlags::empty()); (scratch.llval, scratch.align, true) @@ -987,7 +987,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Handle both by-ref and immediate tuples. if let Ref(llval, None, align) = tuple.val { - let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align); + let tuple_ptr = PlaceRef::new_sized_aligned(llval, tuple.layout, align); for i in 0..tuple.layout.fields.count() { let field_ptr = tuple_ptr.project_field(bx, i); let field = bx.load_operand(field_ptr); @@ -1016,7 +1016,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cx.tcx().mk_mut_ptr(cx.tcx().types.u8), cx.tcx().types.i32 ])); - let slot = PlaceRef::alloca(bx, layout, "personalityslot"); + let slot = PlaceRef::alloca(bx, layout); self.personality_slot = Some(slot); slot } @@ -1104,7 +1104,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let dest = if let mir::Place { base: mir::PlaceBase::Local(index), - projection: None, + projection: box [], } = *dest { match self.locals[index] { LocalRef::Place(dest) => dest, @@ -1115,7 +1115,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return if fn_ret.is_indirect() { // Odd, but possible, case, we have an operand temporary, // but the calling convention has an indirect return. - let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, fn_ret.layout); tmp.storage_live(bx); llargs.push(tmp.llval); ReturnDest::IndirectOperand(tmp, index) @@ -1123,7 +1123,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Currently, intrinsics always need a location to store // the result, so we create a temporary `alloca` for the // result. - let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, fn_ret.layout); tmp.storage_live(bx); ReturnDest::IndirectOperand(tmp, index) } else { @@ -1165,7 +1165,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) { if let mir::Place { base: mir::PlaceBase::Local(index), - projection: None, + projection: box [], } = *dst { match self.locals[index] { LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), @@ -1173,7 +1173,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Operand(None) => { let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); assert!(!dst_layout.ty.has_erasable_regions()); - let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp"); + let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); self.codegen_transmute_into(bx, src, place); let op = bx.load_operand(place); @@ -1201,7 +1201,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llty = bx.backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); let align = src.layout.align.abi.min(dst.align); - src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align)); + src.val.store(bx, PlaceRef::new_sized_aligned(cast_ptr, src.layout, align)); } @@ -1226,7 +1226,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { DirectOperand(index) => { // If there is a cast, we have to store and reload. let op = if let PassMode::Cast(_) = ret_ty.mode { - let tmp = PlaceRef::alloca(bx, ret_ty.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, ret_ty.layout); tmp.storage_live(bx); bx.store_arg_ty(&ret_ty, llval, tmp); let op = bx.load_operand(tmp); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index e7517d6999..aa3971a1da 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -8,7 +8,7 @@ use crate::base; use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext}; use crate::traits::*; -use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; +use syntax_pos::{DUMMY_SP, BytePos, Span}; use syntax::symbol::kw; use std::iter; @@ -120,7 +120,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // In order to have a good line stepping behavior in debugger, we overwrite debug // locations of macro expansions with that of the outermost expansion site // (unless the crate is being compiled with `-Z debug-macros`). - if source_info.span.ctxt() == NO_EXPANSION || + if !source_info.span.from_expansion() || self.cx.sess().opts.debugging_opts.debug_macros { let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo()); (scope, source_info.span) @@ -268,11 +268,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug!("alloc: {:?} ({}) -> place", local, name); if layout.is_unsized() { let indirect_place = - PlaceRef::alloca_unsized_indirect(&mut bx, layout, &name.as_str()); + PlaceRef::alloca_unsized_indirect(&mut bx, layout); + bx.set_var_name(indirect_place.llval, name); // FIXME: add an appropriate debuginfo LocalRef::UnsizedPlace(indirect_place) } else { - let place = PlaceRef::alloca(&mut bx, layout, &name.as_str()); + let place = PlaceRef::alloca(&mut bx, layout); + bx.set_var_name(place.llval, name); if dbg { let (scope, span) = fx.debug_loc(mir::SourceInfo { span: decl.source_info.span, @@ -289,18 +291,17 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); let llretptr = bx.get_param(0); - LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi)) + LocalRef::Place(PlaceRef::new_sized(llretptr, layout)) } else if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); if layout.is_unsized() { - let indirect_place = PlaceRef::alloca_unsized_indirect( - &mut bx, - layout, - &format!("{:?}", local), - ); + let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout); + bx.set_var_name(indirect_place.llval, format_args!("{:?}", local)); LocalRef::UnsizedPlace(indirect_place) } else { - LocalRef::Place(PlaceRef::alloca(&mut bx, layout, &format!("{:?}", local))) + let place = PlaceRef::alloca(&mut bx, layout); + bx.set_var_name(place.llval, format_args!("{:?}", local)); + LocalRef::Place(place) } } else { // If this is an immediate local, we do not create an @@ -452,10 +453,11 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; + // FIXME(eddyb) don't allocate a `String` unless it gets used. let name = if let Some(name) = arg_decl.name { name.as_str().to_string() } else { - format!("arg{}", arg_index) + format!("{:?}", local) }; if Some(local) == mir.spread_arg { @@ -470,7 +472,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( _ => bug!("spread argument isn't a tuple?!") }; - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty), &name); + let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + bx.set_var_name(place.llval, name); for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_ty.args[idx]; idx += 1; @@ -518,19 +521,19 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( PassMode::Ignore(IgnoreMode::CVarArgs) => {} PassMode::Direct(_) => { let llarg = bx.get_param(llarg_idx); - bx.set_value_name(llarg, &name); + bx.set_var_name(llarg, &name); llarg_idx += 1; return local( OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout)); } PassMode::Pair(..) => { - let a = bx.get_param(llarg_idx); - bx.set_value_name(a, &(name.clone() + ".0")); - llarg_idx += 1; + let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1)); + llarg_idx += 2; - let b = bx.get_param(llarg_idx); - bx.set_value_name(b, &(name + ".1")); - llarg_idx += 1; + // FIXME(eddyb) these are scalar components, + // maybe extract the high-level fields? + bx.set_var_name(a, format_args!("{}.0", name)); + bx.set_var_name(b, format_args!("{}.1", name)); return local(OperandRef { val: OperandValue::Pair(a, b), @@ -546,9 +549,9 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // already put it in a temporary alloca and gave it up. // FIXME: lifetimes let llarg = bx.get_param(llarg_idx); - bx.set_value_name(llarg, &name); + bx.set_var_name(llarg, &name); llarg_idx += 1; - PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi) + PlaceRef::new_sized(llarg, arg.layout) } else if arg.is_unsized_indirect() { // As the storage for the indirect argument lives during // the whole function call, we just copy the fat pointer. @@ -558,11 +561,13 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( llarg_idx += 1; let indirect_operand = OperandValue::Pair(llarg, llextra); - let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout, &name); + let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); + bx.set_var_name(tmp.llval, name); indirect_operand.store(bx, tmp); tmp } else { - let tmp = PlaceRef::alloca(bx, arg.layout, &name); + let tmp = PlaceRef::alloca(bx, arg.layout); + bx.set_var_name(tmp.llval, name); if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) { let va_list_did = match tcx.lang_items().va_list() { Some(did) => did, diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 5e5804b726..daa25b2ea0 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -367,7 +367,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); - let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, "unsized_tmp", max_align); + let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align); bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags); // Store the allocated region and the extra to the indirect place. @@ -384,47 +384,45 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Option> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); - place_ref.iterate(|place_base, place_projection| { - if let mir::PlaceBase::Local(index) = place_base { - match self.locals[*index] { - LocalRef::Operand(Some(mut o)) => { - // Moves out of scalar and scalar pair fields are trivial. - for proj in place_projection { - match proj.elem { - mir::ProjectionElem::Field(ref f, _) => { - o = o.extract_field(bx, f.index()); - } - mir::ProjectionElem::Index(_) | - mir::ProjectionElem::ConstantIndex { .. } => { - // ZSTs don't require any actual memory access. - // FIXME(eddyb) deduplicate this with the identical - // checks in `codegen_consume` and `extract_field`. - let elem = o.layout.field(bx.cx(), 0); - if elem.is_zst() { - o = OperandRef::new_zst(bx, elem); - } else { - return None; - } + if let mir::PlaceBase::Local(index) = place_ref.base { + match self.locals[*index] { + LocalRef::Operand(Some(mut o)) => { + // Moves out of scalar and scalar pair fields are trivial. + for elem in place_ref.projection.iter() { + match elem { + mir::ProjectionElem::Field(ref f, _) => { + o = o.extract_field(bx, f.index()); + } + mir::ProjectionElem::Index(_) | + mir::ProjectionElem::ConstantIndex { .. } => { + // ZSTs don't require any actual memory access. + // FIXME(eddyb) deduplicate this with the identical + // checks in `codegen_consume` and `extract_field`. + let elem = o.layout.field(bx.cx(), 0); + if elem.is_zst() { + o = OperandRef::new_zst(bx, elem); + } else { + return None; } - _ => return None, } + _ => return None, } - - Some(o) - } - LocalRef::Operand(None) => { - bug!("use of {:?} before def", place_ref); - } - LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { - // watch out for locals that do not have an - // alloca; they are handled somewhat differently - None } + + Some(o) + } + LocalRef::Operand(None) => { + bug!("use of {:?} before def", place_ref); + } + LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { + // watch out for locals that do not have an + // alloca; they are handled somewhat differently + None } - } else { - None } - }) + } else { + None + } } pub fn codegen_consume( @@ -466,7 +464,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - let ty = self.monomorphize(&constant.ty); self.eval_mir_constant(constant) .map(|c| OperandRef::from_const(bx, c)) .unwrap_or_else(|err| { @@ -481,11 +478,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // the above error (or silence it under some conditions) will not cause UB bx.abort(); // We've errored, so we don't have to produce working code. + let ty = self.monomorphize(&constant.literal.ty); let layout = bx.cx().layout_of(ty); bx.load_operand(PlaceRef::new_sized( bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), layout, - layout.align.abi, )) }) } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index a632838ba2..a4b4cb53bb 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,4 +1,4 @@ -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Instance, Ty}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; @@ -30,6 +30,19 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized( llval: V, layout: TyLayout<'tcx>, + ) -> PlaceRef<'tcx, V> { + assert!(!layout.is_unsized()); + PlaceRef { + llval, + llextra: None, + layout, + align: layout.align.abi + } + } + + pub fn new_sized_aligned( + llval: V, + layout: TyLayout<'tcx>, align: Align, ) -> PlaceRef<'tcx, V> { assert!(!layout.is_unsized()); @@ -45,39 +58,34 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, llval: V, layout: TyLayout<'tcx>, - align: Align, ) -> PlaceRef<'tcx, V> { assert!(!bx.cx().type_has_metadata(layout.ty)); PlaceRef { llval, llextra: None, layout, - align + align: layout.align.abi } } pub fn alloca>( bx: &mut Bx, layout: TyLayout<'tcx>, - name: &str ) -> Self { - debug!("alloca({:?}: {:?})", name, layout); assert!(!layout.is_unsized(), "tried to statically allocate unsized place"); - let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align.abi); - Self::new_sized(tmp, layout, layout.align.abi) + let tmp = bx.alloca(bx.cx().backend_type(layout), layout.align.abi); + Self::new_sized(tmp, layout) } /// Returns a place for an indirect reference to an unsized place. pub fn alloca_unsized_indirect>( bx: &mut Bx, layout: TyLayout<'tcx>, - name: &str, ) -> Self { - debug!("alloca_unsized_indirect({:?}: {:?})", name, layout); assert!(layout.is_unsized(), "tried to allocate indirect place for sized values"); let ptr_ty = bx.cx().tcx().mk_mut_ptr(layout.ty); let ptr_layout = bx.cx().layout_of(ptr_ty); - Self::alloca(bx, ptr_layout, name) + Self::alloca(bx, ptr_layout) } pub fn len>( @@ -437,7 +445,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let result = match &place_ref { mir::PlaceRef { base: mir::PlaceBase::Local(index), - projection: None, + projection: [], } => { match self.locals[*index] { LocalRef::Place(place) => { @@ -454,13 +462,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Promoted(promoted), + kind: mir::StaticKind::Promoted(promoted, substs), + def_id, }), - projection: None, + projection: [], } => { let param_env = ty::ParamEnv::reveal_all(); + let instance = Instance::new(*def_id, self.monomorphize(substs)); let cid = mir::interpret::GlobalId { - instance: self.instance, + instance: instance, promoted: Some(*promoted), }; let layout = cx.layout_of(self.monomorphize(&ty)); @@ -480,29 +490,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llval = bx.cx().const_undef( bx.cx().type_ptr_to(bx.cx().backend_type(layout)) ); - PlaceRef::new_sized(llval, layout, layout.align.abi) + PlaceRef::new_sized(llval, layout) } } } mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Static(def_id), + kind: mir::StaticKind::Static, + def_id, }), - projection: None, + projection: [], } => { // NB: The layout of a static may be unsized as is the case when working // with a static that is an extern_type. let layout = cx.layout_of(self.monomorphize(&ty)); let static_ = bx.get_static(*def_id); - PlaceRef::new_thin_place(bx, static_, layout, layout.align.abi) + PlaceRef::new_thin_place(bx, static_, layout) }, mir::PlaceRef { base, - projection: Some(box mir::Projection { - base: proj_base, - elem: mir::ProjectionElem::Deref, - }), + projection: [proj_base @ .., mir::ProjectionElem::Deref], } => { // Load the pointer from its location. self.codegen_consume(bx, &mir::PlaceRef { @@ -512,22 +520,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::PlaceRef { base, - projection: Some(projection), + projection: [proj_base @ .., elem], } => { // FIXME turn this recursion into iteration let cg_base = self.codegen_place(bx, &mir::PlaceRef { base, - projection: &projection.base, + projection: proj_base, }); - match projection.elem { + match elem { mir::ProjectionElem::Deref => bug!(), mir::ProjectionElem::Field(ref field, _) => { cg_base.project_field(bx, field.index()) } mir::ProjectionElem::Index(index) => { let index = &mir::Operand::Copy( - mir::Place::from(index) + mir::Place::from(*index) ); let index = self.codegen_operand(bx, index); let llindex = index.immediate(); @@ -536,27 +544,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(*offset as u64); cg_base.project_index(bx, lloffset) } mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(*offset as u64); let lllen = cg_base.len(bx.cx()); let llindex = bx.sub(lllen, lloffset); cg_base.project_index(bx, llindex) } mir::ProjectionElem::Subslice { from, to } => { let mut subslice = cg_base.project_index(bx, - bx.cx().const_usize(from as u64)); + bx.cx().const_usize(*from as u64)); let projected_ty = PlaceTy::from_ty(cg_base.layout.ty) - .projection_ty(tcx, &projection.elem).ty; + .projection_ty(tcx, elem).ty; subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty)); if subslice.layout.is_unsized() { subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(), - bx.cx().const_usize((from as u64) + (to as u64)))); + bx.cx().const_usize((*from as u64) + (*to as u64)))); } // Cast the place pointer type to the new @@ -567,7 +575,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { subslice } mir::ProjectionElem::Downcast(_, v) => { - cg_base.project_downcast(bx, v) + cg_base.project_downcast(bx, *v) } } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9da1e5024b..f21836a953 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -64,14 +64,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // index into the struct, and this case isn't // important enough for it. debug!("codegen_rvalue: creating ugly alloca"); - let scratch = PlaceRef::alloca(&mut bx, operand.layout, "__unsize_temp"); + let scratch = PlaceRef::alloca(&mut bx, operand.layout); scratch.storage_live(&mut bx); operand.val.store(&mut bx, scratch); base::coerce_unsized_into(&mut bx, scratch, dest); scratch.storage_dead(&mut bx); } OperandValue::Ref(llref, None, align) => { - let source = PlaceRef::new_sized(llref, operand.layout, align); + let source = PlaceRef::new_sized_aligned(llref, operand.layout, align); base::coerce_unsized_into(&mut bx, source, dest); } OperandValue::Ref(_, Some(_), _) => { @@ -522,7 +522,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // because codegen_place() panics if Local is operand. if let mir::Place { base: mir::PlaceBase::Local(index), - projection: None, + projection: box [], } = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.sty { diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 3717be4b41..dab7dfc041 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -16,12 +16,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, statement.source_info); match statement.kind { - mir::StatementKind::Assign(ref place, ref rvalue) => { + mir::StatementKind::Assign(box(ref place, ref rvalue)) => { if let mir::Place { base: mir::PlaceBase::Local(index), - projection: None, - } = *place { - match self.locals[index] { + projection: box [], + } = place { + match self.locals[*index] { LocalRef::Place(cg_dest) => { self.codegen_rvalue(bx, cg_dest, rvalue) } @@ -29,8 +29,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue) } LocalRef::Operand(None) => { - let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue); - self.locals[index] = LocalRef::Operand(Some(operand)); + let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue); + if let Some(name) = self.mir.local_decls[*index].name { + match operand.val { + OperandValue::Ref(x, ..) | + OperandValue::Immediate(x) => { + bx.set_var_name(x, name); + } + OperandValue::Pair(a, b) => { + // FIXME(eddyb) these are scalar components, + // maybe extract the high-level fields? + bx.set_var_name(a, format_args!("{}.0", name)); + bx.set_var_name(b, format_args!("{}.1", name)); + } + } + } + self.locals[*index] = LocalRef::Operand(Some(operand)); bx } LocalRef::Operand(Some(op)) => { @@ -50,7 +64,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_rvalue(bx, cg_dest, rvalue) } } - mir::StatementKind::SetDiscriminant{ref place, variant_index} => { + mir::StatementKind::SetDiscriminant{box ref place, variant_index} => { self.codegen_place(&mut bx, &place.as_ref()) .codegen_set_discr(&mut bx, variant_index); bx @@ -89,7 +103,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }); if input_vals.len() == asm.inputs.len() { - let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals); + let res = bx.codegen_inline_asm( + &asm.asm, + outputs, + input_vals, + statement.source_info.span, + ); if !res { span_err!(bx.sess(), statement.source_info.span, E0668, "malformed inline assembly"); diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs index 4446f1a3a5..5801963c10 100644 --- a/src/librustc_codegen_ssa/mono_item.rs +++ b/src/librustc_codegen_ssa/mono_item.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { self.to_raw_string(), cx.codegen_unit().name()); - let symbol_name = self.symbol_name(cx.tcx()).as_str(); + let symbol_name = self.symbol_name(cx.tcx()).name.as_str(); debug!("symbol {}", &symbol_name); diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs index fd3c868bbc..c9e1ed86e9 100644 --- a/src/librustc_codegen_ssa/traits/asm.rs +++ b/src/librustc_codegen_ssa/traits/asm.rs @@ -1,6 +1,7 @@ use super::BackendTypes; use crate::mir::place::PlaceRef; use rustc::hir::{GlobalAsm, InlineAsm}; +use syntax_pos::Span; pub trait AsmBuilderMethods<'tcx>: BackendTypes { /// Take an inline assembly expression and splat it out via LLVM @@ -9,6 +10,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { ia: &InlineAsm, outputs: Vec>, inputs: Vec, + span: Span, ) -> bool; } diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 3a144f0b0e..1886701fb3 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -109,13 +109,12 @@ pub trait BuilderMethods<'a, 'tcx>: rhs: Self::Value, ) -> (Self::Value, Self::Value); - fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; + fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; + fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; fn array_alloca( &mut self, ty: Self::Type, len: Self::Value, - name: &str, align: Align, ) -> Self::Value; diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index be2fa7279a..9c16b864ef 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -57,5 +57,5 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes { span: Span, ); fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); - fn set_value_name(&mut self, value: Self::Value, name: &str); + fn set_var_name(&mut self, value: Self::Value, name: impl ToString); } diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index ede30a0bed..7c79cd6021 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -1,6 +1,6 @@ use super::BackendTypes; use crate::mir::operand::OperandRef; -use rustc::ty::Ty; +use rustc::ty::{self, Ty}; use rustc_target::abi::call::FnType; use syntax_pos::Span; @@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { /// add them to librustc_codegen_llvm/context.rs fn codegen_intrinsic_call( &mut self, - callee_ty: Ty<'tcx>, + instance: ty::Instance<'tcx>, fn_ty: &FnType<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], llresult: Self::Value, diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 6983311d79..73c4c05397 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -1,5 +1,5 @@ use super::BackendTypes; -use syntax_pos::symbol::LocalInternedString; +use syntax_pos::symbol::Symbol; use rustc::hir::def_id::DefId; use rustc::ty::layout::Align; @@ -12,8 +12,8 @@ pub trait StaticBuilderMethods: BackendTypes { fn get_static(&mut self, def_id: DefId) -> Self::Value; fn static_panic_msg( &mut self, - msg: Option, - filename: LocalInternedString, + msg: Option, + filename: Symbol, line: Self::Value, col: Self::Value, kind: &str, diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index d93589ea84..89b50c5dac 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,7 +13,7 @@ test = false flate2 = "1.0" log = "0.4" punycode = "0.4.0" -rustc-demangle = "0.1.15" +rustc-demangle = "0.1.16" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 4ea375b59b..1201446afb 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -10,7 +10,6 @@ #![feature(core_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(in_band_lifetimes)] #![recursion_limit="256"] diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 47601da8b7..8d6a1d757e 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -198,10 +198,14 @@ impl SymbolMangler<'tcx> { let lifetimes = regions.into_iter().map(|br| { match br { - ty::BrAnon(i) => i + 1, + ty::BrAnon(i) => { + // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`. + assert_ne!(i, 0); + i - 1 + }, _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), } - }).max().unwrap_or(0); + }).max().map_or(0, |max| max + 1); self.push_opt_integer_62("G", lifetimes as u64); lifetime_depths.end += lifetimes; @@ -297,6 +301,10 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. ty::ReLateBound(debruijn, ty::BrAnon(i)) => { + // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`. + assert_ne!(i, 0); + let i = i - 1; + let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs index f562744dbe..51269be4e9 100644 --- a/src/librustc_codegen_utils/symbol_names_test.rs +++ b/src/librustc_codegen_utils/symbol_names_test.rs @@ -40,7 +40,7 @@ impl SymbolNamesTest<'tcx> { let instance = Instance::mono(tcx, def_id); let mangled = self.tcx.symbol_name(instance); tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled)); - if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.as_str()) { + if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.name.as_str()) { tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 288676ce3f..be9f79c83b 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -26,5 +26,5 @@ rustc-hash = "1.0.1" smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } [dependencies.parking_lot] -version = "0.7" +version = "0.9" features = ["nightly"] diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 6f40d059be..6e80b48a68 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -149,7 +149,7 @@ macro_rules! newtype_index { #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { - unsafe { $type { private: value } } + $type { private: value } } /// Extracts the value of this index as an integer. diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 9f103437d3..f759350195 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -27,7 +27,7 @@ #![cfg_attr(unix, feature(libc))] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #[macro_use] extern crate log; diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs index a0363e165e..ddf89d9962 100644 --- a/src/librustc_data_structures/obligation_forest/graphviz.rs +++ b/src/librustc_data_structures/obligation_forest/graphviz.rs @@ -74,9 +74,7 @@ impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest ambiguous result. Obligation was neither a success +//! - `Unchanged` -> ambiguous result. Obligation was neither a success //! nor a failure. It is assumed that further attempts to process the //! obligation will yield the same result unless something in the //! surrounding environment changes. -//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The +//! - `Changed(C)` - the obligation was *shallowly successful*. The //! vector `C` is a list of subobligations. The meaning of this is that //! `O` was successful on the assumption that all the obligations in `C` //! are also successful. Therefore, `O` is only considered a "true" @@ -34,7 +34,7 @@ //! state and the obligations in `C` become the new pending //! obligations. They will be processed the next time you call //! `process_obligations`. -//! - `Err(E)` -> obligation failed with error `E`. We will collect this +//! - `Error(E)` -> obligation failed with error `E`. We will collect this //! error and return it from `process_obligations`, along with the //! "backtrace" of obligations (that is, the list of obligations up to //! and including the root of the failed obligation). No further @@ -47,50 +47,39 @@ //! - `completed`: a list of obligations where processing was fully //! completed without error (meaning that all transitive subobligations //! have also been completed). So, for example, if the callback from -//! `process_obligations` returns `Ok(Some(C))` for some obligation `O`, +//! `process_obligations` returns `Changed(C)` for some obligation `O`, //! then `O` will be considered completed right away if `C` is the //! empty vector. Otherwise it will only be considered completed once //! all the obligations in `C` have been found completed. //! - `errors`: a list of errors that occurred and associated backtraces //! at the time of error, which can be used to give context to the user. //! - `stalled`: if true, then none of the existing obligations were -//! *shallowly successful* (that is, no callback returned `Ok(Some(_))`). +//! *shallowly successful* (that is, no callback returned `Changed(_)`). //! This implies that all obligations were either errors or returned an //! ambiguous result, which means that any further calls to //! `process_obligations` would simply yield back further ambiguous //! results. This is used by the `FulfillmentContext` to decide when it //! has reached a steady state. //! -//! #### Snapshots -//! -//! The `ObligationForest` supports a limited form of snapshots; see -//! `start_snapshot`, `commit_snapshot`, and `rollback_snapshot`. In -//! particular, you can use a snapshot to roll back new root -//! obligations. However, it is an error to attempt to -//! `process_obligations` during a snapshot. -//! //! ### Implementation details //! //! For the most part, comments specific to the implementation are in the //! code. This file only contains a very high-level overview. Basically, //! the forest is stored in a vector. Each element of the vector is a node -//! in some tree. Each node in the vector has the index of an (optional) -//! parent and (for convenience) its root (which may be itself). It also -//! has a current state, described by `NodeState`. After each -//! processing step, we compress the vector to remove completed and error -//! nodes, which aren't needed anymore. +//! in some tree. Each node in the vector has the index of its dependents, +//! including the first dependent which is known as the parent. It also +//! has a current state, described by `NodeState`. After each processing +//! step, we compress the vector to remove completed and error nodes, which +//! aren't needed anymore. use crate::fx::{FxHashMap, FxHashSet}; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use std::collections::hash_map::Entry; use std::fmt::Debug; use std::hash; use std::marker::PhantomData; -mod node_index; -use self::node_index::NodeIndex; - mod graphviz; #[cfg(test)] @@ -148,18 +137,23 @@ pub struct ObligationForest { /// At the end of processing, those nodes will be removed by a /// call to `compress`. /// - /// At all times we maintain the invariant that every node appears - /// at a higher index than its parent. This is needed by the - /// backtrace iterator (which uses `split_at`). + /// `usize` indices are used here and throughout this module, rather than + /// `newtype_index!` indices, because this code is hot enough that the + /// `u32`-to-`usize` conversions that would be required are significant, + /// and space considerations are not important. nodes: Vec>, /// A cache of predicates that have been successfully completed. done_cache: FxHashSet, - /// An cache of the nodes in `nodes`, indexed by predicate. - waiting_cache: FxHashMap, + /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately, + /// its contents are not guaranteed to match those of `nodes`. See the + /// comments in `process_obligation` for details. + waiting_cache: FxHashMap, - scratch: Option>, + /// A scratch vector reused in various operations, to avoid allocating new + /// vectors. + scratch: RefCell>, obligation_tree_id_generator: ObligationTreeIdGenerator, @@ -178,19 +172,42 @@ struct Node { obligation: O, state: Cell, - /// The parent of a node - the original obligation of - /// which it is a subobligation. Except for error reporting, - /// it is just like any member of `dependents`. - parent: Option, + /// Obligations that depend on this obligation for their completion. They + /// must all be in a non-pending state. + dependents: Vec, - /// Obligations that depend on this obligation for their - /// completion. They must all be in a non-pending state. - dependents: Vec, + /// If true, dependents[0] points to a "parent" node, which requires + /// special treatment upon error but is otherwise treated the same. + /// (It would be more idiomatic to store the parent node in a separate + /// `Option` field, but that slows down the common case of + /// iterating over the parent and other descendants together.) + has_parent: bool, /// Identifier of the obligation tree to which this node belongs. obligation_tree_id: ObligationTreeId, } +impl Node { + fn new( + parent: Option, + obligation: O, + obligation_tree_id: ObligationTreeId + ) -> Node { + Node { + obligation, + state: Cell::new(NodeState::Pending), + dependents: + if let Some(parent_index) = parent { + vec![parent_index] + } else { + vec![] + }, + has_parent: parent.is_some(), + obligation_tree_id, + } + } +} + /// The state of one node in some tree within the forest. This /// represents the current state of processing for the obligation (of /// type `O`) associated with this node. @@ -262,7 +279,7 @@ impl ObligationForest { nodes: vec![], done_cache: Default::default(), waiting_cache: Default::default(), - scratch: Some(vec![]), + scratch: RefCell::new(vec![]), obligation_tree_id_generator: (0..).map(ObligationTreeId), error_cache: Default::default(), } @@ -275,17 +292,13 @@ impl ObligationForest { } /// Registers an obligation. - /// - /// This CAN be done in a snapshot pub fn register_obligation(&mut self, obligation: O) { // Ignore errors here - there is no guarantee of success. let _ = self.register_obligation_at(obligation, None); } - // returns Err(()) if we already know this obligation failed. - fn register_obligation_at(&mut self, obligation: O, parent: Option) - -> Result<(), ()> - { + // Returns Err(()) if we already know this obligation failed. + fn register_obligation_at(&mut self, obligation: O, parent: Option) -> Result<(), ()> { if self.done_cache.contains(obligation.as_predicate()) { return Ok(()); } @@ -294,15 +307,14 @@ impl ObligationForest { Entry::Occupied(o) => { debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!", obligation, parent, o.get()); - let node = &mut self.nodes[o.get().get()]; - if let Some(parent) = parent { - // If the node is already in `waiting_cache`, it's already - // been marked with a parent. (It's possible that parent - // has been cleared by `apply_rewrites`, though.) So just - // dump `parent` into `node.dependents`... unless it's - // already in `node.dependents` or `node.parent`. - if !node.dependents.contains(&parent) && Some(parent) != node.parent { - node.dependents.push(parent); + let node = &mut self.nodes[*o.get()]; + if let Some(parent_index) = parent { + // If the node is already in `waiting_cache`, it has + // already had its chance to be marked with a parent. So if + // it's not already present, just dump `parent` into the + // dependents as a non-parent. + if !node.dependents.contains(&parent_index) { + node.dependents.push(parent_index); } } if let NodeState::Error = node.state.get() { @@ -316,11 +328,8 @@ impl ObligationForest { obligation, parent, self.nodes.len()); let obligation_tree_id = match parent { - Some(p) => { - let parent_node = &self.nodes[p.get()]; - parent_node.obligation_tree_id - } - None => self.obligation_tree_id_generator.next().unwrap() + Some(parent_index) => self.nodes[parent_index].obligation_tree_id, + None => self.obligation_tree_id_generator.next().unwrap(), }; let already_failed = @@ -333,7 +342,7 @@ impl ObligationForest { if already_failed { Err(()) } else { - v.insert(NodeIndex::new(self.nodes.len())); + v.insert(self.nodes.len()); self.nodes.push(Node::new(parent, obligation, obligation_tree_id)); Ok(()) } @@ -342,12 +351,10 @@ impl ObligationForest { } /// Converts all remaining obligations to the given error. - /// - /// This cannot be done during a snapshot. pub fn to_errors(&mut self, error: E) -> Vec> { let mut errors = vec![]; - for index in 0..self.nodes.len() { - if let NodeState::Pending = self.nodes[index].state.get() { + for (index, node) in self.nodes.iter().enumerate() { + if let NodeState::Pending = node.state.get() { let backtrace = self.error_at(index); errors.push(Error { error: error.clone(), @@ -373,7 +380,6 @@ impl ObligationForest { fn insert_into_error_cache(&mut self, node_index: usize) { let node = &self.nodes[node_index]; - self.error_cache .entry(node.obligation_tree_id) .or_default() @@ -394,11 +400,17 @@ impl ObligationForest { let mut stalled = true; for index in 0..self.nodes.len() { - debug!("process_obligations: node {} == {:?}", index, self.nodes[index]); + let node = &mut self.nodes[index]; + + debug!("process_obligations: node {} == {:?}", index, node); - let result = match self.nodes[index] { - Node { ref state, ref mut obligation, .. } if state.get() == NodeState::Pending => - processor.process_obligation(obligation), + // `processor.process_obligation` can modify the predicate within + // `node.obligation`, and that predicate is the key used for + // `self.waiting_cache`. This means that `self.waiting_cache` can + // get out of sync with `nodes`. It's not very common, but it does + // happen, and code in `compress` has to allow for it. + let result = match node.state.get() { + NodeState::Pending => processor.process_obligation(&mut node.obligation), _ => continue }; @@ -411,15 +423,15 @@ impl ObligationForest { ProcessResult::Changed(children) => { // We are not (yet) stalled. stalled = false; - self.nodes[index].state.set(NodeState::Success); + node.state.set(NodeState::Success); for child in children { let st = self.register_obligation_at( child, - Some(NodeIndex::new(index)) + Some(index) ); if let Err(()) = st { - // error already reported - propagate it + // Error already reported - propagate it // to our node. self.error_at(index); } @@ -448,8 +460,6 @@ impl ObligationForest { self.mark_as_waiting(); self.process_cycles(processor); - - // Now we have to compress the result let completed = self.compress(do_completed); debug!("process_obligations: complete"); @@ -465,21 +475,20 @@ impl ObligationForest { /// report all cycles between them. This should be called /// after `mark_as_waiting` marks all nodes with pending /// subobligations as NodeState::Waiting. - fn process_cycles

(&mut self, processor: &mut P) + fn process_cycles

(&self, processor: &mut P) where P: ObligationProcessor { - let mut stack = self.scratch.take().unwrap(); + let mut stack = self.scratch.replace(vec![]); debug_assert!(stack.is_empty()); debug!("process_cycles()"); - for index in 0..self.nodes.len() { + for (index, node) in self.nodes.iter().enumerate() { // For rustc-benchmarks/inflate-0.1.0 this state test is extremely // hot and the state is almost always `Pending` or `Waiting`. It's // a win to handle the no-op cases immediately to avoid the cost of // the function call. - let state = self.nodes[index].state.get(); - match state { + match node.state.get() { NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {}, _ => self.find_cycles_from_node(&mut stack, processor, index), } @@ -488,84 +497,88 @@ impl ObligationForest { debug!("process_cycles: complete"); debug_assert!(stack.is_empty()); - self.scratch = Some(stack); + self.scratch.replace(stack); } - fn find_cycles_from_node

(&self, stack: &mut Vec, - processor: &mut P, index: usize) + fn find_cycles_from_node

(&self, stack: &mut Vec, processor: &mut P, index: usize) where P: ObligationProcessor { let node = &self.nodes[index]; - let state = node.state.get(); - match state { + match node.state.get() { NodeState::OnDfsStack => { - let index = - stack.iter().rposition(|n| *n == index).unwrap(); + let index = stack.iter().rposition(|&n| n == index).unwrap(); processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)), PhantomData); } NodeState::Success => { node.state.set(NodeState::OnDfsStack); stack.push(index); - for dependent in node.parent.iter().chain(node.dependents.iter()) { - self.find_cycles_from_node(stack, processor, dependent.get()); + for &index in node.dependents.iter() { + self.find_cycles_from_node(stack, processor, index); } stack.pop(); node.state.set(NodeState::Done); }, NodeState::Waiting | NodeState::Pending => { - // this node is still reachable from some pending node. We + // This node is still reachable from some pending node. We // will get to it when they are all processed. } NodeState::Done | NodeState::Error => { - // already processed that node + // Already processed that node. } }; } /// Returns a vector of obligations for `p` and all of its /// ancestors, putting them into the error state in the process. - fn error_at(&mut self, p: usize) -> Vec { - let mut error_stack = self.scratch.take().unwrap(); + fn error_at(&self, mut index: usize) -> Vec { + let mut error_stack = self.scratch.replace(vec![]); let mut trace = vec![]; - let mut n = p; loop { - self.nodes[n].state.set(NodeState::Error); - trace.push(self.nodes[n].obligation.clone()); - error_stack.extend(self.nodes[n].dependents.iter().map(|x| x.get())); - - // loop to the parent - match self.nodes[n].parent { - Some(q) => n = q.get(), - None => break + let node = &self.nodes[index]; + node.state.set(NodeState::Error); + trace.push(node.obligation.clone()); + if node.has_parent { + // The first dependent is the parent, which is treated + // specially. + error_stack.extend(node.dependents.iter().skip(1)); + index = node.dependents[0]; + } else { + // No parent; treat all dependents non-specially. + error_stack.extend(node.dependents.iter()); + break; } } - while let Some(i) = error_stack.pop() { - match self.nodes[i].state.get() { + while let Some(index) = error_stack.pop() { + let node = &self.nodes[index]; + match node.state.get() { NodeState::Error => continue, - _ => self.nodes[i].state.set(NodeState::Error), + _ => node.state.set(NodeState::Error), } - let node = &self.nodes[i]; - - error_stack.extend( - node.parent.iter().chain(node.dependents.iter()).map(|x| x.get()) - ); + error_stack.extend(node.dependents.iter()); } - self.scratch = Some(error_stack); + self.scratch.replace(error_stack); trace } - #[inline] - fn mark_neighbors_as_waiting_from(&self, node: &Node) { - for dependent in node.parent.iter().chain(node.dependents.iter()) { - self.mark_as_waiting_from(&self.nodes[dependent.get()]); + // This always-inlined function is for the hot call site. + #[inline(always)] + fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node) { + for &index in node.dependents.iter() { + self.mark_as_waiting_from(&self.nodes[index]); } } + // This never-inlined function is for the cold call site. + #[inline(never)] + fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node) { + self.inlined_mark_neighbors_as_waiting_from(node) + } + /// Marks all nodes that depend on a pending node as `NodeState::Waiting`. fn mark_as_waiting(&self) { for node in &self.nodes { @@ -576,7 +589,8 @@ impl ObligationForest { for node in &self.nodes { if node.state.get() == NodeState::Pending { - self.mark_neighbors_as_waiting_from(node); + // This call site is hot. + self.inlined_mark_neighbors_as_waiting_from(node); } } } @@ -588,7 +602,8 @@ impl ObligationForest { NodeState::Pending | NodeState::Done => {}, } - self.mark_neighbors_as_waiting_from(node); + // This call site is cold. + self.uninlined_mark_neighbors_as_waiting_from(node); } /// Compresses the vector, removing all popped nodes. This adjusts @@ -600,44 +615,48 @@ impl ObligationForest { #[inline(never)] fn compress(&mut self, do_completed: DoCompleted) -> Option> { let nodes_len = self.nodes.len(); - let mut node_rewrites: Vec<_> = self.scratch.take().unwrap(); + let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]); node_rewrites.extend(0..nodes_len); let mut dead_nodes = 0; // Now move all popped nodes to the end. Try to keep the order. // // LOOP INVARIANT: - // self.nodes[0..i - dead_nodes] are the first remaining nodes - // self.nodes[i - dead_nodes..i] are all dead - // self.nodes[i..] are unchanged - for i in 0..self.nodes.len() { - match self.nodes[i].state.get() { + // self.nodes[0..index - dead_nodes] are the first remaining nodes + // self.nodes[index - dead_nodes..index] are all dead + // self.nodes[index..] are unchanged + for index in 0..self.nodes.len() { + let node = &self.nodes[index]; + match node.state.get() { NodeState::Pending | NodeState::Waiting => { if dead_nodes > 0 { - self.nodes.swap(i, i - dead_nodes); - node_rewrites[i] -= dead_nodes; + self.nodes.swap(index, index - dead_nodes); + node_rewrites[index] -= dead_nodes; } } NodeState::Done => { - // Avoid cloning the key (predicate) in case it exists in the waiting cache + // This lookup can fail because the contents of + // `self.waiting_cache` is not guaranteed to match those of + // `self.nodes`. See the comment in `process_obligation` + // for more details. if let Some((predicate, _)) = self.waiting_cache - .remove_entry(self.nodes[i].obligation.as_predicate()) + .remove_entry(node.obligation.as_predicate()) { self.done_cache.insert(predicate); } else { - self.done_cache.insert(self.nodes[i].obligation.as_predicate().clone()); + self.done_cache.insert(node.obligation.as_predicate().clone()); } - node_rewrites[i] = nodes_len; + node_rewrites[index] = nodes_len; dead_nodes += 1; } NodeState::Error => { // We *intentionally* remove the node from the cache at this point. Otherwise // tests must come up with a different type on every type error they // check against. - self.waiting_cache.remove(self.nodes[i].obligation.as_predicate()); - node_rewrites[i] = nodes_len; + self.waiting_cache.remove(node.obligation.as_predicate()); + node_rewrites[index] = nodes_len; dead_nodes += 1; - self.insert_into_error_cache(i); + self.insert_into_error_cache(index); } NodeState::OnDfsStack | NodeState::Success => unreachable!() } @@ -646,12 +665,11 @@ impl ObligationForest { // No compression needed. if dead_nodes == 0 { node_rewrites.truncate(0); - self.scratch = Some(node_rewrites); + self.scratch.replace(node_rewrites); return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None }; } - // Pop off all the nodes we killed and extract the success - // stories. + // Pop off all the nodes we killed and extract the success stories. let successful = if do_completed == DoCompleted::Yes { Some((0..dead_nodes) .map(|_| self.nodes.pop().unwrap()) @@ -670,7 +688,7 @@ impl ObligationForest { self.apply_rewrites(&node_rewrites); node_rewrites.truncate(0); - self.scratch = Some(node_rewrites); + self.scratch.replace(node_rewrites); successful } @@ -679,59 +697,37 @@ impl ObligationForest { let nodes_len = node_rewrites.len(); for node in &mut self.nodes { - if let Some(index) = node.parent { - let new_index = node_rewrites[index.get()]; - if new_index >= nodes_len { - // parent dead due to error - node.parent = None; - } else { - node.parent = Some(NodeIndex::new(new_index)); - } - } - - let mut i = 0; - while i < node.dependents.len() { - let new_index = node_rewrites[node.dependents[i].get()]; + let mut index = 0; + while index < node.dependents.len() { + let new_index = node_rewrites[node.dependents[index]]; if new_index >= nodes_len { - node.dependents.swap_remove(i); + node.dependents.swap_remove(index); + if index == 0 && node.has_parent { + // We just removed the parent. + node.has_parent = false; + } } else { - node.dependents[i] = NodeIndex::new(new_index); - i += 1; + node.dependents[index] = new_index; + index += 1; } } } - let mut kill_list = vec![]; - for (predicate, index) in &mut self.waiting_cache { - let new_index = node_rewrites[index.get()]; + // This updating of `self.waiting_cache` is necessary because the + // removal of nodes within `compress` can fail. See above. + self.waiting_cache.retain(|_predicate, index| { + let new_index = node_rewrites[*index]; if new_index >= nodes_len { - kill_list.push(predicate.clone()); + false } else { - *index = NodeIndex::new(new_index); + *index = new_index; + true } - } - - for predicate in kill_list { self.waiting_cache.remove(&predicate); } - } -} - -impl Node { - fn new( - parent: Option, - obligation: O, - obligation_tree_id: ObligationTreeId - ) -> Node { - Node { - obligation, - state: Cell::new(NodeState::Pending), - parent, - dependents: vec![], - obligation_tree_id, - } + }); } } -// I need a Clone closure +// I need a Clone closure. #[derive(Clone)] struct GetObligation<'a, O>(&'a [Node]); diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs deleted file mode 100644 index 69ea473e05..0000000000 --- a/src/librustc_data_structures/obligation_forest/node_index.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::num::NonZeroU32; -use std::u32; - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct NodeIndex { - index: NonZeroU32, -} - -impl NodeIndex { - #[inline] - pub fn new(value: usize) -> NodeIndex { - assert!(value < (u32::MAX as usize)); - NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() } - } - - #[inline] - pub fn get(self) -> usize { - (self.index.get() - 1) as usize - } -} diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 1c0d9360f2..ea771d9f20 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -20,7 +20,6 @@ pub struct TinyList { } impl TinyList { - #[inline] pub fn new() -> TinyList { TinyList { @@ -60,20 +59,24 @@ impl TinyList { #[inline] pub fn contains(&self, data: &T) -> bool { - if let Some(ref head) = self.head { - head.contains(data) - } else { - false + let mut elem = self.head.as_ref(); + while let Some(ref e) = elem { + if &e.data == data { + return true; + } + elem = e.next.as_ref().map(|e| &**e); } + false } #[inline] pub fn len(&self) -> usize { - if let Some(ref head) = self.head { - head.len() - } else { - 0 + let (mut elem, mut count) = (self.head.as_ref(), 0); + while let Some(ref e) = elem { + count += 1; + elem = e.next.as_ref().map(|e| &**e); } + count } } @@ -84,40 +87,13 @@ struct Element { } impl Element { - fn remove_next(&mut self, data: &T) -> bool { - let new_next = if let Some(ref mut next) = self.next { - if next.data != *data { - return next.remove_next(data) - } else { - next.next.take() - } - } else { - return false + let new_next = match self.next { + Some(ref mut next) if next.data == *data => next.next.take(), + Some(ref mut next) => return next.remove_next(data), + None => return false, }; - self.next = new_next; - true } - - fn len(&self) -> usize { - if let Some(ref next) = self.next { - 1 + next.len() - } else { - 1 - } - } - - fn contains(&self, data: &T) -> bool { - if self.data == *data { - return true - } - - if let Some(ref next) = self.next { - next.contains(data) - } else { - false - } - } } diff --git a/src/librustc_data_structures/tiny_list/tests.rs b/src/librustc_data_structures/tiny_list/tests.rs index 8374659e1e..0142631590 100644 --- a/src/librustc_data_structures/tiny_list/tests.rs +++ b/src/librustc_data_structures/tiny_list/tests.rs @@ -1,7 +1,7 @@ use super::*; extern crate test; -use test::Bencher; +use test::{Bencher, black_box}; #[test] fn test_contains_and_insert() { @@ -98,36 +98,59 @@ fn test_remove_single() { #[bench] fn bench_insert_empty(b: &mut Bencher) { b.iter(|| { - let mut list = TinyList::new(); + let mut list = black_box(TinyList::new()); list.insert(1); + list }) } #[bench] fn bench_insert_one(b: &mut Bencher) { b.iter(|| { - let mut list = TinyList::new_single(0); + let mut list = black_box(TinyList::new_single(0)); list.insert(1); + list }) } +#[bench] +fn bench_contains_empty(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new()).contains(&1) + }); +} + +#[bench] +fn bench_contains_unknown(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new_single(0)).contains(&1) + }); +} + +#[bench] +fn bench_contains_one(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new_single(1)).contains(&1) + }); +} + #[bench] fn bench_remove_empty(b: &mut Bencher) { b.iter(|| { - TinyList::new().remove(&1) + black_box(TinyList::new()).remove(&1) }); } #[bench] fn bench_remove_unknown(b: &mut Bencher) { b.iter(|| { - TinyList::new_single(0).remove(&1) + black_box(TinyList::new_single(0)).remove(&1) }); } #[bench] fn bench_remove_one(b: &mut Bencher) { b.iter(|| { - TinyList::new_single(1).remove(&1) + black_box(TinyList::new_single(1)).remove(&1) }); } diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 42aa8203cb..25f67b3046 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -11,8 +11,9 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } +lazy_static = "1.0" log = "0.4" -env_logger = { version = "0.5", default-features = false } +env_logger = { version = "0.6", default-features = false } rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_ast_borrowck = { path = "../librustc_ast_borrowck" } @@ -20,6 +21,8 @@ rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } +rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the sysroot +rustc_plugin_impl = { path = "../librustc_plugin" } rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_interface = { path = "../librustc_interface" } diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs new file mode 100644 index 0000000000..0906d358ba --- /dev/null +++ b/src/librustc_driver/args.rs @@ -0,0 +1,53 @@ +use std::error; +use std::fmt; +use std::fs; +use std::io; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; + +static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); + +pub fn used_unstable_argsfile() -> bool { + USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) +} + +pub fn arg_expand(arg: String) -> Result, Error> { + if arg.starts_with("@") { + let path = &arg[1..]; + let file = match fs::read_to_string(path) { + Ok(file) => { + USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); + file + } + Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { + return Err(Error::Utf8Error(Some(path.to_string()))); + } + Err(err) => return Err(Error::IOError(path.to_string(), err)), + }; + Ok(file.lines().map(ToString::to_string).collect()) + } else { + Ok(vec![arg]) + } +} + +#[derive(Debug)] +pub enum Error { + Utf8Error(Option), + IOError(String, io::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Utf8Error(None) => write!(fmt, "Utf8 error"), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), + Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &'static str { + "argument error" + } +} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e9d85a53d1..f99e65b449 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -9,7 +9,6 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] #![feature(no_debug)] #![feature(integer_atomics)] @@ -21,6 +20,10 @@ pub extern crate getopts; extern crate libc; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; + +pub extern crate rustc_plugin_impl as plugin; use pretty::{PpMode, UserIdentifiedItem}; @@ -34,8 +37,8 @@ use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; use rustc::hir::def_id::LOCAL_CRATE; -use rustc::util::common::{ErrorReported, install_panic_hook, print_time_passes_entry}; -use rustc::util::common::{set_time_depth, time}; +use rustc::ty::TyCtxt; +use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -63,9 +66,10 @@ use syntax::source_map::FileLoader; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; +use syntax_pos::{DUMMY_SP, FileName}; pub mod pretty; +mod args; /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -130,8 +134,11 @@ pub struct TimePassesCallbacks { impl Callbacks for TimePassesCallbacks { fn config(&mut self, config: &mut interface::Config) { + // If a --prints=... option has been given, we don't print the "total" + // time because it will mess up the --prints output. See #64339. self.time_passes = - config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time; + config.opts.prints.is_empty() && + (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time); } } @@ -139,20 +146,26 @@ impl Callbacks for TimePassesCallbacks { // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler( - args: &[String], + at_args: &[String], callbacks: &mut (dyn Callbacks + Send), file_loader: Option>, emitter: Option> ) -> interface::Result<()> { + let mut args = Vec::new(); + for arg in at_args { + match args::arg_expand(arg.clone()) { + Ok(arg) => args.extend(arg), + Err(err) => early_error(ErrorOutputType::default(), + &format!("Failed to load argument file: {}", err)), + } + } let diagnostic_output = emitter.map(|emitter| DiagnosticOutput::Raw(emitter)) .unwrap_or(DiagnosticOutput::Default); - let matches = match handle_options(args) { + let matches = match handle_options(&args) { Some(matches) => matches, None => return Ok(()), }; - install_panic_hook(); - let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); let mut dummy_config = |sopts, cfg, diagnostic_output| { @@ -428,6 +441,15 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } else { None }; + if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE"). + expect("when UNSTABLE_RUSTDOC_TEST_PATH is set \ + UNSTABLE_RUSTDOC_TEST_LINE also needs to be set"); + let line = isize::from_str_radix(&line, 10). + expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number"); + let file_name = FileName::doc_test_source_code(PathBuf::from(path), line); + return Some((Input::Str { name: file_name, input: src }, None, err)); + } Some((Input::Str { name: FileName::anon_source_code(&src), input: src }, None, err)) } else { @@ -678,7 +700,7 @@ impl RustcDefaultCalls { let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)), + path: ast::Path::from_ident(ast::Ident::with_dummy_span(name)), node: ast::MetaItemKind::Word, span: DUMMY_SP, }); @@ -777,13 +799,19 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { "\n --help -v Print the full set of options rustc accepts" }; - println!("{}\nAdditional help: + let at_path = if verbose && nightly_options::is_nightly_build() { + " @path Read newline separated options from `path`\n" + } else { + "" + }; + println!("{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ - Print 'lint' options and default settings{}{}\n", - options.usage(message), - nightly_help, - verbose_help); + Print 'lint' options and default settings{nightly}{verbose}\n", + options = options.usage(message), + at_path = at_path, + nightly = nightly_help, + verbose = verbose_help); } fn print_wall_help() { @@ -1008,6 +1036,12 @@ pub fn handle_options(args: &[String]) -> Option { // (unstable option being used on stable) nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); + // Late check to see if @file was used without unstable options enabled + if crate::args::used_unstable_argsfile() && !nightly_options::is_unstable_enabled(&matches) { + early_error(ErrorOutputType::default(), + "@path is unstable - use -Z unstable-options to enable its use"); + } + if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); @@ -1120,59 +1154,104 @@ fn extra_compiler_flags() -> Option<(Vec, bool)> { } } -/// Runs a procedure which will detect panics in the compiler and print nicer -/// error messages rather than just failing the test. +/// Runs a closure and catches unwinds triggered by fatal errors. /// -/// The diagnostic emitter yielded to the procedure should be used for reporting -/// errors of the compiler. -pub fn report_ices_to_stderr_if_any R, R>(f: F) -> Result { +/// The compiler currently unwinds with a special sentinel value to abort +/// compilation on fatal errors. This function catches that sentinel and turns +/// the panic into a `Result` instead. +pub fn catch_fatal_errors R, R>(f: F) -> Result { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { if value.is::() { ErrorReported } else { - // Thread panicked without emitting a fatal diagnostic - eprintln!(""); - - let emitter = - Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, - None, - false, - false)); - let handler = errors::Handler::with_emitter(true, None, emitter); - - // a .span_bug or .bug call has already printed what - // it wants to print. - if !value.is::() { - handler.emit(&MultiSpan::new(), - "unexpected panic", - errors::Level::Bug); - } + panic::resume_unwind(value); + } + }) +} + +lazy_static! { + static ref DEFAULT_HOOK: Box) + Sync + Send + 'static> = { + let hook = panic::take_hook(); + panic::set_hook(Box::new(|info| report_ice(info, BUG_REPORT_URL))); + hook + }; +} + +/// Prints the ICE message, including backtrace and query stack. +/// +/// The message will point the user at `bug_report_url` to report the ICE. +/// +/// When `install_ice_hook` is called, this function will be called as the panic +/// hook. +pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { + // Invoke the default handler, which prints the actual panic message and optionally a backtrace + (*DEFAULT_HOOK)(info); + + // Separate the output with an empty line + eprintln!(); + + let emitter = Box::new(errors::emitter::EmitterWriter::stderr( + errors::ColorConfig::Auto, + None, + false, + false, + None, + false, + )); + let handler = errors::Handler::with_emitter(true, None, emitter); + + // a .span_bug or .bug call has already printed what + // it wants to print. + if !info.payload().is::() { + let d = errors::Diagnostic::new(errors::Level::Bug, "unexpected panic"); + handler.emit_diagnostic(&d); + handler.abort_if_errors_and_should_abort(); + } - let mut xs: Vec> = vec![ - "the compiler unexpectedly panicked. this is a bug.".into(), - format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(), - format!("rustc {} running on {}", - option_env!("CFG_VERSION").unwrap_or("unknown_version"), - config::host_triple()).into(), - ]; + let mut xs: Vec> = vec![ + "the compiler unexpectedly panicked. this is a bug.".into(), + format!("we would appreciate a bug report: {}", bug_report_url).into(), + format!("rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple()).into(), + ]; - if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { - xs.push(format!("compiler flags: {}", flags.join(" ")).into()); + if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + xs.push(format!("compiler flags: {}", flags.join(" ")).into()); - if excluded_cargo_defaults { - xs.push("some of the compiler flags provided by cargo are hidden".into()); - } - } + if excluded_cargo_defaults { + xs.push("some of the compiler flags provided by cargo are hidden".into()); + } + } - for note in &xs { - handler.emit(&MultiSpan::new(), - note, - errors::Level::Note); - } + for note in &xs { + handler.note_without_error(¬e); + } + + // If backtraces are enabled, also print the query stack + let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false); - panic::resume_unwind(Box::new(errors::FatalErrorMarker)); + if backtrace { + TyCtxt::try_print_query_stack(); + } + + #[cfg(windows)] + unsafe { + if env::var("RUSTC_BREAK_ON_ICE").is_ok() { + extern "system" { + fn DebugBreak(); + } + // Trigger a debugger if we crashed during bootstrap + DebugBreak(); } - }) + } +} + +/// Installs a panic hook that will print the ICE message on unexpected panics. +/// +/// A custom rustc driver can skip calling this to set up a custom ICE hook. +pub fn install_ice_hook() { + lazy_static::initialize(&DEFAULT_HOOK); } /// This allows tools to enable rust logging without having to magically match rustc's @@ -1185,10 +1264,11 @@ pub fn main() { let start = Instant::now(); init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); - let result = report_ices_to_stderr_if_any(|| { + install_ice_hook(); + let result = catch_fatal_errors(|| { let args = env::args_os().enumerate() .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { - early_error(ErrorOutputType::default(), + early_error(ErrorOutputType::default(), &format!("Argument {} is not valid Unicode: {:?}", i, arg)) })) .collect::>(); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index cb17401f62..fa9504e220 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -1,7 +1,5 @@ //! The various pretty-printing routines. -use rustc::cfg; -use rustc::cfg::graphviz::LabelledCFG; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::map::blocks; @@ -14,6 +12,7 @@ use rustc::util::common::ErrorReported; use rustc_interface::util::ReplaceBodyWithLoop; use rustc_ast_borrowck as borrowck; use rustc_ast_borrowck::graphviz as borrowck_dot; +use rustc_ast_borrowck::cfg::{self, graphviz::LabelledCFG}; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast; @@ -327,6 +326,7 @@ impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> { } fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) { match node { + pprust::AnnNode::Crate(_) | pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => {}, @@ -432,14 +432,18 @@ impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { match node { pprust::AnnNode::Ident(&ast::Ident { name, span }) => { s.s.space(); - // FIXME #16420: this doesn't display the connections - // between syntax contexts s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt())) } pprust::AnnNode::Name(&name) => { s.s.space(); s.synth_comment(name.as_u32().to_string()) } + pprust::AnnNode::Crate(_) => { + s.s.hardbreak(); + let verbose = self.sess.verbose(); + s.synth_comment(syntax_pos::hygiene::debug_hygiene_data(verbose)); + s.s.hardbreak_if_not_bol(); + } _ => {} } } diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 32f121f18f..1541845bb5 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -18,3 +18,4 @@ unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" annotate-snippets = "0.6.1" +term_size = "0.3.1" diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 96a9b6c5c4..0281d10fd9 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -7,7 +7,7 @@ use syntax_pos::{SourceFile, MultiSpan, Loc}; use crate::{ - Level, CodeSuggestion, DiagnosticBuilder, Emitter, + Level, CodeSuggestion, Diagnostic, Emitter, SourceMapperDyn, SubDiagnostic, DiagnosticId }; use crate::emitter::FileWithAnnotatedLines; @@ -25,17 +25,21 @@ pub struct AnnotateSnippetEmitterWriter { short_message: bool, /// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs. ui_testing: bool, + + external_macro_backtrace: bool, } impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let primary_span = db.span.clone(); - let children = db.children.clone(); - // FIXME(#59346): Collect suggestions (see emitter.rs) - let suggestions: &[_] = &[]; + fn emit_diagnostic(&mut self, db: &Diagnostic) { + let mut children = db.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&db); - // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs + self.fix_multispans_in_std_macros(&self.source_map, + &mut primary_span, + &mut children, + &db.level, + self.external_macro_backtrace); self.emit_messages_default(&db.level, db.message(), @@ -107,7 +111,7 @@ impl<'a> DiagnosticConverter<'a> { annotated_files: Vec, primary_lo: Loc ) -> Vec { - // FIXME(#59346): Provide a test case where `annotated_files` is > 1 + // FIXME(#64205): Provide a test case where `annotated_files` is > 1 annotated_files.iter().flat_map(|annotated_file| { annotated_file.lines.iter().map(|line| { let line_source = Self::source_string(annotated_file.file.clone(), &line); @@ -148,7 +152,7 @@ impl<'a> DiagnosticConverter<'a> { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::Fatal | Level::PhaseFatal | Level::Error => AnnotationType::Error, + Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Warning => AnnotationType::Warning, Level::Note => AnnotationType::Note, Level::Help => AnnotationType::Help, @@ -161,12 +165,14 @@ impl<'a> DiagnosticConverter<'a> { impl AnnotateSnippetEmitterWriter { pub fn new( source_map: Option>, - short_message: bool + short_message: bool, + external_macro_backtrace: bool, ) -> Self { Self { source_map, short_message, ui_testing: false, + external_macro_backtrace, } } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 424d7c0038..3f1b91256c 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -94,7 +94,6 @@ impl Diagnostic { match self.level { Level::Bug | Level::Fatal | - Level::PhaseFatal | Level::Error | Level::FailureNote => { true @@ -120,6 +119,9 @@ impl Diagnostic { } /// Adds a span/label to be included in the resulting snippet. + /// This label will be shown together with the original span/label used when creating the + /// diagnostic, *not* a span added by one of the `span_*` methods. + /// /// This is pushed onto the `MultiSpan` that was created when the /// diagnostic was first built. If you don't call this function at /// all, and you just supplied a `Span` to create the diagnostic, @@ -196,6 +198,7 @@ impl Diagnostic { self } + /// Prints the span with a note above it. pub fn span_note>(&mut self, sp: S, msg: &str) @@ -209,6 +212,7 @@ impl Diagnostic { self } + /// Prints the span with a warn above it. pub fn span_warn>(&mut self, sp: S, msg: &str) @@ -222,6 +226,7 @@ impl Diagnostic { self } + /// Prints the span with some help above it. pub fn span_help>(&mut self, sp: S, msg: &str) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 41d0638f7c..e85388bfea 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -18,8 +18,17 @@ use log::debug; /// extending `HandlerFlags`, accessed via `self.handler.flags`. #[must_use] #[derive(Clone)] -pub struct DiagnosticBuilder<'a> { - pub handler: &'a Handler, +pub struct DiagnosticBuilder<'a>(Box>); + +/// This is a large type, and often used as a return value, especially within +/// the frequently-used `PResult` type. In theory, return value optimization +/// (RVO) should avoid unnecessary copying. In practice, it does not (at the +/// time of writing). The split between `DiagnosticBuilder` and +/// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls. +#[must_use] +#[derive(Clone)] +struct DiagnosticBuilderInner<'a> { + handler: &'a Handler, diagnostic: Diagnostic, allow_suggestions: bool, } @@ -52,7 +61,7 @@ macro_rules! forward { ) => { $(#[$attrs])* pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.diagnostic.$n($($name),*); + self.0.diagnostic.$n($($name),*); self } }; @@ -69,7 +78,7 @@ macro_rules! forward { ) => { $(#[$attrs])* pub fn $n>(&mut self, $($name: $ty),*) -> &mut Self { - self.diagnostic.$n($($name),*); + self.0.diagnostic.$n($($name),*); self } }; @@ -79,24 +88,20 @@ impl<'a> Deref for DiagnosticBuilder<'a> { type Target = Diagnostic; fn deref(&self) -> &Diagnostic { - &self.diagnostic + &self.0.diagnostic } } impl<'a> DerefMut for DiagnosticBuilder<'a> { fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.diagnostic + &mut self.0.diagnostic } } impl<'a> DiagnosticBuilder<'a> { /// Emit the diagnostic. pub fn emit(&mut self) { - if self.cancelled() { - return; - } - - self.handler.emit_db(&self); + self.0.handler.emit_diagnostic(&self); self.cancel(); } @@ -115,8 +120,8 @@ impl<'a> DiagnosticBuilder<'a> { /// Buffers the diagnostic for later emission, unless handler /// has disabled such buffering. pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { - if self.handler.flags.dont_buffer_diagnostics || - self.handler.flags.treat_err_as_bug.is_some() + if self.0.handler.flags.dont_buffer_diagnostics || + self.0.handler.flags.treat_err_as_bug.is_some() { self.emit(); return; @@ -126,7 +131,7 @@ impl<'a> DiagnosticBuilder<'a> { // implements `Drop`. let diagnostic; unsafe { - diagnostic = std::ptr::read(&self.diagnostic); + diagnostic = std::ptr::read(&self.0.diagnostic); std::mem::forget(self); }; // Logging here is useful to help track down where in logs an error was @@ -144,7 +149,7 @@ impl<'a> DiagnosticBuilder<'a> { span: Option, ) -> &mut Self { let span = span.map(|s| s.into()).unwrap_or_else(|| MultiSpan::new()); - self.diagnostic.sub(level, message, span, None); + self.0.diagnostic.sub(level, message, span, None); self } @@ -160,7 +165,7 @@ impl<'a> DiagnosticBuilder<'a> { /// locally in whichever way makes the most sense. pub fn delay_as_bug(&mut self) { self.level = Level::Bug; - self.handler.delay_as_bug(self.diagnostic.clone()); + self.0.handler.delay_as_bug(self.0.diagnostic.clone()); self.cancel(); } @@ -171,7 +176,7 @@ impl<'a> DiagnosticBuilder<'a> { /// then the snippet will just include that `Span`, which is /// called the primary span. pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { - self.diagnostic.span_label(span, label); + self.0.diagnostic.span_label(span, label); self } @@ -208,10 +213,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.multipart_suggestion( + self.0.diagnostic.multipart_suggestion( msg, suggestion, applicability, @@ -225,10 +230,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.tool_only_multipart_suggestion( + self.0.diagnostic.tool_only_multipart_suggestion( msg, suggestion, applicability, @@ -236,7 +241,6 @@ impl<'a> DiagnosticBuilder<'a> { self } - pub fn span_suggestion( &mut self, sp: Span, @@ -244,10 +248,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion( + self.0.diagnostic.span_suggestion( sp, msg, suggestion, @@ -263,10 +267,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestions: impl Iterator, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestions( + self.0.diagnostic.span_suggestions( sp, msg, suggestions, @@ -282,10 +286,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion_short( + self.0.diagnostic.span_suggestion_short( sp, msg, suggestion, @@ -301,10 +305,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion_hidden( + self.0.diagnostic.span_suggestion_hidden( sp, msg, suggestion, @@ -320,10 +324,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.tool_only_span_suggestion( + self.0.diagnostic.tool_only_span_suggestion( sp, msg, suggestion, @@ -336,13 +340,13 @@ impl<'a> DiagnosticBuilder<'a> { forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self { - self.allow_suggestions = allow; + self.0.allow_suggestions = allow; self } /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. - pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { + crate fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new_with_code(handler, level, None, message) } @@ -359,19 +363,19 @@ impl<'a> DiagnosticBuilder<'a> { /// Creates a new `DiagnosticBuilder` with an already constructed /// diagnostic. - pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) + crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { - DiagnosticBuilder { + DiagnosticBuilder(Box::new(DiagnosticBuilderInner { handler, diagnostic, allow_suggestions: true, - } + })) } } impl<'a> Debug for DiagnosticBuilder<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.diagnostic.fmt(f) + self.0.diagnostic.fmt(f) } } @@ -381,7 +385,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> { fn drop(&mut self) { if !panicking() && !self.cancelled() { let mut db = DiagnosticBuilder::new( - self.handler, + self.0.handler, Level::Bug, "the following error was constructed but not emitted", ); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 361b5cd935..fc441320e0 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -12,7 +12,7 @@ use Destination::*; use syntax_pos::{SourceFile, Span, MultiSpan}; use crate::{ - Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, + Level, CodeSuggestion, Diagnostic, SubDiagnostic, SuggestionStyle, SourceMapperDyn, DiagnosticId, }; use crate::Level::Error; @@ -24,7 +24,7 @@ use rustc_data_structures::sync::Lrc; use std::borrow::Cow; use std::io::prelude::*; use std::io; -use std::cmp::{min, Reverse}; +use std::cmp::{min, max, Reverse}; use std::path::Path; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; @@ -51,9 +51,129 @@ impl HumanReadableErrorType { dst: Box, source_map: Option>, teach: bool, + terminal_width: Option, + external_macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); - EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors()) + let color = color_config.suggests_using_colors(); + EmitterWriter::new(dst, source_map, short, teach, color, terminal_width, + external_macro_backtrace) + } +} + +#[derive(Clone, Copy, Debug)] +struct Margin { + /// The available whitespace in the left that can be consumed when centering. + pub whitespace_left: usize, + /// The column of the beginning of left-most span. + pub span_left: usize, + /// The column of the end of right-most span. + pub span_right: usize, + /// The beginning of the line to be displayed. + pub computed_left: usize, + /// The end of the line to be displayed. + pub computed_right: usize, + /// The current width of the terminal. 140 by default and in tests. + pub column_width: usize, + /// The end column of a span label, including the span. Doesn't account for labels not in the + /// same line as the span. + pub label_right: usize, +} + +impl Margin { + fn new( + whitespace_left: usize, + span_left: usize, + span_right: usize, + label_right: usize, + column_width: usize, + max_line_len: usize, + ) -> Self { + // The 6 is padding to give a bit of room for `...` when displaying: + // ``` + // error: message + // --> file.rs:16:58 + // | + // 16 | ... fn foo(self) -> Self::Bar { + // | ^^^^^^^^^ + // ``` + + let mut m = Margin { + whitespace_left: if whitespace_left >= 6 { whitespace_left - 6 } else { 0 }, + span_left: if span_left >= 6 { span_left - 6 } else { 0 }, + span_right: span_right + 6, + computed_left: 0, + computed_right: 0, + column_width, + label_right: label_right + 6, + }; + m.compute(max_line_len); + m + } + + fn was_cut_left(&self) -> bool { + self.computed_left > 0 + } + + fn was_cut_right(&self, line_len: usize) -> bool { + let right = if self.computed_right == self.span_right || + self.computed_right == self.label_right + { + // Account for the "..." padding given above. Otherwise we end up with code lines that + // do fit but end in "..." as if they were trimmed. + self.computed_right - 6 + } else { + self.computed_right + }; + right < line_len && line_len > self.computed_left + self.column_width + } + + fn compute(&mut self, max_line_len: usize) { + // When there's a lot of whitespace (>20), we want to trim it as it is useless. + self.computed_left = if self.whitespace_left > 20 { + self.whitespace_left - 16 // We want some padding. + } else { + 0 + }; + // We want to show as much as possible, max_line_len is the right-most boundary for the + // relevant code. + self.computed_right = max(max_line_len, self.computed_left); + + if self.computed_right - self.computed_left > self.column_width { + // Trimming only whitespace isn't enough, let's get craftier. + if self.label_right - self.whitespace_left <= self.column_width { + // Attempt to fit the code window only trimming whitespace. + self.computed_left = self.whitespace_left; + self.computed_right = self.computed_left + self.column_width; + } else if self.label_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering only the spans and labels. + let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; + self.computed_left = self.span_left.saturating_sub(padding_left); + self.computed_right = self.computed_left + self.column_width; + } else if self.span_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering the spans and labels plus padding. + let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; + self.computed_left = self.span_left.saturating_sub(padding_left); + self.computed_right = self.computed_left + self.column_width; + } else { // Mostly give up but still don't show the full line. + self.computed_left = self.span_left; + self.computed_right = self.span_right; + } + } + } + + fn left(&self, line_len: usize) -> usize { + min(self.computed_left, line_len) + } + + fn right(&self, line_len: usize) -> usize { + if max(line_len, self.computed_left) - self.computed_left <= self.column_width { + line_len + } else if self.computed_right > line_len { + line_len + } else { + self.computed_right + } } } @@ -62,7 +182,7 @@ const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. pub trait Emitter { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>); + fn emit_diagnostic(&mut self, db: &Diagnostic); /// Emit a notification that an artifact has been output. /// This is currently only supported for the JSON format, @@ -73,16 +193,25 @@ pub trait Emitter { fn should_show_explain(&self) -> bool { true } -} -impl Emitter for EmitterWriter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + /// Formats the substitutions of the primary_span + /// + /// The are a lot of conditions to this method, but in short: + /// + /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, + /// we format the `help` suggestion depending on the content of the + /// substitutions. In that case, we return the modified span only. + /// + /// * If the current `Diagnostic` has multiple suggestions, + /// we return the original `primary_span` and the original suggestions. + fn primary_span_formatted<'a>( + &mut self, + db: &'a Diagnostic + ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = db.span.clone(); - let mut children = db.children.clone(); - let mut suggestions: &[_] = &[]; - if let Some((sugg, rest)) = db.suggestions.split_first() { if rest.is_empty() && + // ^ if there is only one suggestion // don't display multi-suggestions as labels sugg.substitutions.len() == 1 && // don't display multipart suggestions as labels @@ -98,26 +227,167 @@ impl Emitter for EmitterWriter { { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { - // This substitution is only removal or we explicitly don't want to show the - // code inline, don't show it + // This substitution is only removal OR we explicitly don't want to show the + // code inline (`hide_inline`). Therefore, we don't show the substitution. format!("help: {}", sugg.msg) } else { + // Show the default suggestion text with the substitution format!("help: {}: `{}`", sugg.msg, substitution) }; primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); + + // We return only the modified primary_span + (primary_span, &[]) } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - suggestions = &db.suggestions; + (primary_span, &db.suggestions) } + } else { + (primary_span, &db.suggestions) + } + } + + // This does a small "fix" for multispans by looking to see if it can find any that + // point directly at <*macros>. Since these are often difficult to read, this + // will change the span to point at the use site. + fn fix_multispans_in_std_macros(&self, + source_map: &Option>, + span: &mut MultiSpan, + children: &mut Vec, + level: &Level, + backtrace: bool) { + let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace); + for child in children.iter_mut() { + spans_updated |= self.fix_multispan_in_std_macros( + source_map, + &mut child.span, + backtrace + ); } + let msg = if level == &Error { + "this error originates in a macro outside of the current crate \ + (in Nightly builds, run with -Z external-macro-backtrace \ + for more info)".to_string() + } else { + "this warning originates in a macro outside of the current crate \ + (in Nightly builds, run with -Z external-macro-backtrace \ + for more info)".to_string() + }; - self.fix_multispans_in_std_macros(&mut primary_span, + if spans_updated { + children.push(SubDiagnostic { + level: Level::Note, + message: vec![ + (msg, + Style::NoStyle), + ], + span: MultiSpan::new(), + render_span: None, + }); + } + } + + // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of + // <*macros>. Since these locations are often difficult to read, we move these Spans from + // <*macros> to their corresponding use site. + fn fix_multispan_in_std_macros(&self, + source_map: &Option>, + span: &mut MultiSpan, + always_backtrace: bool) -> bool { + let mut spans_updated = false; + + if let Some(ref sm) = source_map { + let mut before_after: Vec<(Span, Span)> = vec![]; + let mut new_labels: Vec<(Span, String)> = vec![]; + + // First, find all the spans in <*macros> and point instead at their use site + for sp in span.primary_spans() { + if sp.is_dummy() { + continue; + } + let call_sp = sm.call_span_if_macro(*sp); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); + } + let backtrace_len = sp.macro_backtrace().len(); + for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { + // Only show macro locations that are local + // and display them like a span_note + if trace.def_site_span.is_dummy() { + continue; + } + if always_backtrace { + new_labels.push((trace.def_site_span, + format!("in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + String::new() + }))); + } + // Check to make sure we're not in any <*macros> + if !sm.span_to_filename(trace.def_site_span).is_macros() && + !trace.macro_decl_name.starts_with("desugaring of ") && + !trace.macro_decl_name.starts_with("#[") || + always_backtrace { + new_labels.push((trace.call_site, + format!("in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + String::new() + }))); + if !always_backtrace { + break; + } + } + } + } + for (label_span, label_text) in new_labels { + span.push_span_label(label_span, label_text); + } + for sp_label in span.span_labels() { + if sp_label.span.is_dummy() { + continue; + } + if sm.span_to_filename(sp_label.span.clone()).is_macros() && + !always_backtrace + { + let v = sp_label.span.macro_backtrace(); + if let Some(use_site) = v.last() { + before_after.push((sp_label.span.clone(), use_site.call_site.clone())); + } + } + } + // After we have them, make sure we replace these 'bad' def sites with their use sites + for (before, after) in before_after { + span.replace(before, after); + spans_updated = true; + } + } + + spans_updated + } +} + +impl Emitter for EmitterWriter { + fn emit_diagnostic(&mut self, db: &Diagnostic) { + let mut children = db.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&db); + + self.fix_multispans_in_std_macros(&self.sm, + &mut primary_span, &mut children, &db.level, - db.handler.flags.external_macro_backtrace); + self.external_macro_backtrace); self.emit_messages_default(&db.level, &db.styled_message(), @@ -180,6 +450,9 @@ pub struct EmitterWriter { short_message: bool, teach: bool, ui_testing: bool, + terminal_width: Option, + + external_macro_backtrace: bool, } #[derive(Debug)] @@ -190,11 +463,14 @@ pub struct FileWithAnnotatedLines { } impl EmitterWriter { - pub fn stderr(color_config: ColorConfig, - source_map: Option>, - short_message: bool, - teach: bool) - -> EmitterWriter { + pub fn stderr( + color_config: ColorConfig, + source_map: Option>, + short_message: bool, + teach: bool, + terminal_width: Option, + external_macro_backtrace: bool, + ) -> EmitterWriter { let dst = Destination::from_stderr(color_config); EmitterWriter { dst, @@ -202,6 +478,8 @@ impl EmitterWriter { short_message, teach, ui_testing: false, + terminal_width, + external_macro_backtrace, } } @@ -211,6 +489,8 @@ impl EmitterWriter { short_message: bool, teach: bool, colored: bool, + terminal_width: Option, + external_macro_backtrace: bool, ) -> EmitterWriter { EmitterWriter { dst: Raw(dst, colored), @@ -218,6 +498,8 @@ impl EmitterWriter { short_message, teach, ui_testing: false, + terminal_width, + external_macro_backtrace, } } @@ -234,12 +516,70 @@ impl EmitterWriter { } } - fn render_source_line(&self, - buffer: &mut StyledBuffer, - file: Lrc, - line: &Line, - width_offset: usize, - code_offset: usize) -> Vec<(usize, Style)> { + fn draw_line( + &self, + buffer: &mut StyledBuffer, + source_string: &str, + line_index: usize, + line_offset: usize, + width_offset: usize, + code_offset: usize, + margin: Margin, + ) { + let line_len = source_string.len(); + // Create the source line we will highlight. + let left = margin.left(line_len); + let right = margin.right(line_len); + // On long lines, we strip the source line, accounting for unicode. + let mut taken = 0; + let code: String = source_string.chars().skip(left).take_while(|ch| { + // Make sure that the trimming on the right will fall within the terminal width. + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. + // For now, just accept that sometimes the code line will be longer than desired. + let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + if taken + next > right - left { + return false; + } + taken += next; + true + }).collect(); + buffer.puts(line_offset, code_offset, &code, Style::Quotation); + if margin.was_cut_left() { + // We have stripped some code/whitespace from the beginning, make it clear. + buffer.puts(line_offset, code_offset, "...", Style::LineNumber); + } + if margin.was_cut_right(line_len) { + // We have stripped some code after the right-most span end, make it clear we did so. + buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber); + } + buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); + + draw_col_separator(buffer, line_offset, width_offset - 2); + } + + fn render_source_line( + &self, + buffer: &mut StyledBuffer, + file: Lrc, + line: &Line, + width_offset: usize, + code_offset: usize, + margin: Margin, + ) -> Vec<(usize, Style)> { + // Draw: + // + // LL | ... code ... + // | ^^-^ span label + // | | + // | secondary span label + // + // ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it + // | | | | + // | | | actual code found in your source code and the spans we use to mark it + // | | when there's too much wasted space to the left, trim it + // | vertical divider between the column number and the code + // column number + if line.line_index == 0 { return Vec::new(); } @@ -251,14 +591,21 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - // First create the source line we will highlight. - buffer.puts(line_offset, code_offset, &source_string, Style::Quotation); - buffer.puts(line_offset, - 0, - &self.maybe_anonymized(line.line_index), - Style::LineNumber); + let left = margin.left(source_string.len()); // Left trim + // Account for unicode characters of width !=0 that were removed. + let left = source_string.chars().take(left).fold(0, |acc, ch| { + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) + }); - draw_col_separator(buffer, line_offset, width_offset - 2); + self.draw_line( + buffer, + &source_string, + line.line_index, + line_offset, + width_offset, + code_offset, + margin, + ); // Special case when there's only one annotation involved, it is the start of a multiline // span and there's no text at the beginning of the code line. Instead of doing the whole @@ -279,18 +626,13 @@ impl EmitterWriter { if line.annotations.len() == 1 { if let Some(ref ann) = line.annotations.get(0) { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - if source_string.chars() - .take(ann.start_col) - .all(|c| c.is_whitespace()) { + if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { let style = if ann.is_primary { Style::UnderlinePrimary } else { Style::UnderlineSecondary }; - buffer.putc(line_offset, - width_offset + depth - 1, - '/', - style); + buffer.putc(line_offset, width_offset + depth - 1, '/', style); return vec![(depth, style)]; } } @@ -511,19 +853,23 @@ impl EmitterWriter { match annotation.annotation_type { AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => { - draw_range(buffer, - '_', - line_offset + pos, - width_offset + depth, - code_offset + annotation.start_col, - style); + draw_range( + buffer, + '_', + line_offset + pos, + width_offset + depth, + code_offset + annotation.start_col - left, + style, + ); } _ if self.teach => { - buffer.set_style_range(line_offset, - code_offset + annotation.start_col, - code_offset + annotation.end_col, - style, - annotation.is_primary); + buffer.set_style_range( + line_offset, + code_offset + annotation.start_col - left, + code_offset + annotation.end_col - left, + style, + annotation.is_primary, + ); } _ => {} } @@ -551,7 +897,7 @@ impl EmitterWriter { if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { buffer.putc(p, - code_offset + annotation.start_col, + code_offset + annotation.start_col - margin.computed_left, '|', style); } @@ -595,15 +941,20 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, annotation.end_col + 1) + (pos + 1, if annotation.end_col + 1 > left { + annotation.end_col + 1 - left + } else { + 0 + }) } else { - (pos + 2, annotation.start_col) + (pos + 2, if annotation.start_col > left { + annotation.start_col - left + } else { + 0 + }) }; if let Some(ref label) = annotation.label { - buffer.puts(line_offset + pos, - code_offset + col, - &label, - style); + buffer.puts(line_offset + pos, code_offset + col, &label, style); } } @@ -638,10 +989,16 @@ impl EmitterWriter { ('-', Style::UnderlineSecondary) }; for p in annotation.start_col..annotation.end_col { - buffer.putc(line_offset + 1, - code_offset + p, - underline, - style); + buffer.putc( + line_offset + 1, + if code_offset + p > left { + code_offset + p - left + } else { + 0 + }, + underline, + style, + ); } } annotations_position.iter().filter_map(|&(_, annotation)| { @@ -698,127 +1055,6 @@ impl EmitterWriter { max } - // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of - // <*macros>. Since these locations are often difficult to read, we move these Spans from - // <*macros> to their corresponding use site. - fn fix_multispan_in_std_macros(&mut self, - span: &mut MultiSpan, - always_backtrace: bool) -> bool { - let mut spans_updated = false; - - if let Some(ref sm) = self.sm { - let mut before_after: Vec<(Span, Span)> = vec![]; - let mut new_labels: Vec<(Span, String)> = vec![]; - - // First, find all the spans in <*macros> and point instead at their use site - for sp in span.primary_spans() { - if sp.is_dummy() { - continue; - } - let call_sp = sm.call_span_if_macro(*sp); - if call_sp != *sp && !always_backtrace { - before_after.push((*sp, call_sp)); - } - let backtrace_len = sp.macro_backtrace().len(); - for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { - // Only show macro locations that are local - // and display them like a span_note - if trace.def_site_span.is_dummy() { - continue; - } - if always_backtrace { - new_labels.push((trace.def_site_span, - format!("in this expansion of `{}`{}", - trace.macro_decl_name, - if backtrace_len > 2 { - // if backtrace_len == 1 it'll be pointed - // at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }))); - } - // Check to make sure we're not in any <*macros> - if !sm.span_to_filename(trace.def_site_span).is_macros() && - !trace.macro_decl_name.starts_with("desugaring of ") && - !trace.macro_decl_name.starts_with("#[") || - always_backtrace { - new_labels.push((trace.call_site, - format!("in this macro invocation{}", - if backtrace_len > 2 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }))); - if !always_backtrace { - break; - } - } - } - } - for (label_span, label_text) in new_labels { - span.push_span_label(label_span, label_text); - } - for sp_label in span.span_labels() { - if sp_label.span.is_dummy() { - continue; - } - if sm.span_to_filename(sp_label.span.clone()).is_macros() && - !always_backtrace - { - let v = sp_label.span.macro_backtrace(); - if let Some(use_site) = v.last() { - before_after.push((sp_label.span.clone(), use_site.call_site.clone())); - } - } - } - // After we have them, make sure we replace these 'bad' def sites with their use sites - for (before, after) in before_after { - span.replace(before, after); - spans_updated = true; - } - } - - spans_updated - } - - // This does a small "fix" for multispans by looking to see if it can find any that - // point directly at <*macros>. Since these are often difficult to read, this - // will change the span to point at the use site. - fn fix_multispans_in_std_macros(&mut self, - span: &mut MultiSpan, - children: &mut Vec, - level: &Level, - backtrace: bool) { - let mut spans_updated = self.fix_multispan_in_std_macros(span, backtrace); - for child in children.iter_mut() { - spans_updated |= self.fix_multispan_in_std_macros(&mut child.span, backtrace); - } - let msg = if level == &Error { - "this error originates in a macro outside of the current crate \ - (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() - } else { - "this warning originates in a macro outside of the current crate \ - (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() - }; - - if spans_updated { - children.push(SubDiagnostic { - level: Level::Note, - message: vec![ - (msg, - Style::NoStyle), - ], - span: MultiSpan::new(), - render_span: None, - }); - } - } - /// Adds a left margin to every line but the first, given a padding length and the label being /// displayed, keeping the provided highlighting. fn msg_to_buffer(&self, @@ -916,15 +1152,18 @@ impl EmitterWriter { buffer.prepend(0, " ", Style::NoStyle); } draw_note_separator(&mut buffer, 0, max_line_num_len + 1); - let level_str = level.to_string(); - if !level_str.is_empty() { - buffer.append(0, &level_str, Style::MainHeaderMsg); - buffer.append(0, ": ", Style::NoStyle); + if *level != Level::FailureNote { + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::MainHeaderMsg); + buffer.append(0, ": ", Style::NoStyle); + } } self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None); } else { let level_str = level.to_string(); - if !level_str.is_empty() { + // The failure note level itself does not provide any useful diagnostic information + if *level != Level::FailureNote && !level_str.is_empty() { buffer.append(0, &level_str, Style::Level(level.clone())); } // only render error codes, not lint codes @@ -933,7 +1172,7 @@ impl EmitterWriter { buffer.append(0, &code, Style::Level(level.clone())); buffer.append(0, "]", Style::Level(level.clone())); } - if !level_str.is_empty() { + if *level != Level::FailureNote && !level_str.is_empty() { buffer.append(0, ": ", header_style); } for &(ref text, _) in msg.iter() { @@ -979,22 +1218,30 @@ impl EmitterWriter { let buffer_msg_line_offset = buffer.num_lines(); buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber); - buffer.append(buffer_msg_line_offset, - &format!("{}:{}:{}", - loc.file.name, - sm.doctest_offset_line(&loc.file.name, loc.line), - loc.col.0 + 1), - Style::LineAndColumn); + buffer.append( + buffer_msg_line_offset, + &format!( + "{}:{}:{}", + loc.file.name, + sm.doctest_offset_line(&loc.file.name, loc.line), + loc.col.0 + 1, + ), + Style::LineAndColumn, + ); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle); } } else { - buffer.prepend(0, - &format!("{}:{}:{}: ", - loc.file.name, - sm.doctest_offset_line(&loc.file.name, loc.line), - loc.col.0 + 1), - Style::LineAndColumn); + buffer.prepend( + 0, + &format!( + "{}:{}:{}: ", + loc.file.name, + sm.doctest_offset_line(&loc.file.name, loc.line), + loc.col.0 + 1, + ), + Style::LineAndColumn, + ); } } else if !self.short_message { // remember where we are in the output buffer for easy reference @@ -1037,22 +1284,96 @@ impl EmitterWriter { // Contains the vertical lines' positions for active multiline annotations let mut multilines = FxHashMap::default(); + // Get the left-side margin to remove it + let mut whitespace_margin = std::usize::MAX; + for line_idx in 0..annotated_file.lines.len() { + let file = annotated_file.file.clone(); + let line = &annotated_file.lines[line_idx]; + if let Some(source_string) = file.get_line(line.line_index - 1) { + let leading_whitespace = source_string + .chars() + .take_while(|c| c.is_whitespace()) + .count(); + if source_string.chars().any(|c| !c.is_whitespace()) { + whitespace_margin = min( + whitespace_margin, + leading_whitespace, + ); + } + } + } + if whitespace_margin == std::usize::MAX { + whitespace_margin = 0; + } + + // Left-most column any visible span points at. + let mut span_left_margin = std::usize::MAX; + for line in &annotated_file.lines { + for ann in &line.annotations { + span_left_margin = min(span_left_margin, ann.start_col); + span_left_margin = min(span_left_margin, ann.end_col); + } + } + if span_left_margin == std::usize::MAX { + span_left_margin = 0; + } + + // Right-most column any visible span points at. + let mut span_right_margin = 0; + let mut label_right_margin = 0; + let mut max_line_len = 0; + for line in &annotated_file.lines { + max_line_len = max(max_line_len, annotated_file.file + .get_line(line.line_index - 1) + .map(|s| s.len()) + .unwrap_or(0)); + for ann in &line.annotations { + span_right_margin = max(span_right_margin, ann.start_col); + span_right_margin = max(span_right_margin, ann.end_col); + // FIXME: account for labels not in the same line + let label_right = ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0); + label_right_margin = max(label_right_margin, ann.end_col + label_right); + } + } + + let width_offset = 3 + max_line_num_len; + let code_offset = if annotated_file.multiline_depth == 0 { + width_offset + } else { + width_offset + annotated_file.multiline_depth + 1 + }; + + let column_width = if let Some(width) = self.terminal_width { + width.saturating_sub(code_offset) + } else if self.ui_testing { + 140 + } else { + term_size::dimensions() + .map(|(w, _)| w.saturating_sub(code_offset)) + .unwrap_or(std::usize::MAX) + }; + + let margin = Margin::new( + whitespace_margin, + span_left_margin, + span_right_margin, + label_right_margin, + column_width, + max_line_len, + ); + // Next, output the annotate source for this file for line_idx in 0..annotated_file.lines.len() { let previous_buffer_line = buffer.num_lines(); - let width_offset = 3 + max_line_num_len; - let code_offset = if annotated_file.multiline_depth == 0 { - width_offset - } else { - width_offset + annotated_file.multiline_depth + 1 - }; - - let depths = self.render_source_line(&mut buffer, - annotated_file.file.clone(), - &annotated_file.lines[line_idx], - width_offset, - code_offset); + let depths = self.render_source_line( + &mut buffer, + annotated_file.file.clone(), + &annotated_file.lines[line_idx], + width_offset, + code_offset, + margin, + ); let mut to_add = FxHashMap::default(); @@ -1099,25 +1420,24 @@ impl EmitterWriter { let last_buffer_line_num = buffer.num_lines(); - buffer.puts(last_buffer_line_num, - 0, - &self.maybe_anonymized(annotated_file.lines[line_idx + 1] - .line_index - 1), - Style::LineNumber); - draw_col_separator(&mut buffer, - last_buffer_line_num, - 1 + max_line_num_len); - buffer.puts(last_buffer_line_num, - code_offset, - &unannotated_line, - Style::Quotation); + self.draw_line( + &mut buffer, + &unannotated_line, + annotated_file.lines[line_idx + 1].line_index - 1, + last_buffer_line_num, + width_offset, + code_offset, + margin, + ); for (depth, style) in &multilines { - draw_multiline_line(&mut buffer, - last_buffer_line_num, - width_offset, - *depth, - *style); + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + *depth, + *style, + ); } } } @@ -1207,7 +1527,7 @@ impl EmitterWriter { // ...or trailing spaces. Account for substitutions containing unicode // characters. let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) }); let underline_start = (span_start_pos + start) as isize + offset; @@ -1230,7 +1550,7 @@ impl EmitterWriter { // length of the code after substitution let full_sub_len = part.snippet.chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) as isize + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) as isize }); // length of the code to be substituted diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3b6a6a824c..1fe5b71d7b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -16,7 +16,7 @@ use Level::*; use emitter::{Emitter, EmitterWriter}; use registry::Registry; -use rustc_data_structures::sync::{self, Lrc, Lock, AtomicUsize, AtomicBool, SeqCst}; +use rustc_data_structures::sync::{self, Lrc, Lock}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::StableHasher; @@ -43,8 +43,7 @@ use syntax_pos::{BytePos, SourceFile, FileName, MultiSpan, - Span, - NO_EXPANSION}; + Span}; /// Indicates the confidence in the correctness of a suggestion. /// @@ -189,7 +188,7 @@ impl CodeSuggestion { // Find the bounding span. let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap(); let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap(); - let bounding_span = Span::new(lo, hi, NO_EXPANSION); + let bounding_span = Span::with_root_ctxt(lo, hi); let lines = cm.span_to_lines(bounding_span).unwrap(); assert!(!lines.lines.is_empty()); @@ -299,30 +298,34 @@ pub use diagnostic_builder::DiagnosticBuilder; /// Certain errors (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. pub struct Handler { - pub flags: HandlerFlags, + flags: HandlerFlags, + inner: Lock, +} +struct HandlerInner { + flags: HandlerFlags, /// The number of errors that have been emitted, including duplicates. /// /// This is not necessarily the count that's reported to the user once /// compilation ends. - err_count: AtomicUsize, - deduplicated_err_count: AtomicUsize, - emitter: Lock>, - continue_after_error: AtomicBool, - delayed_span_bugs: Lock>, + err_count: usize, + deduplicated_err_count: usize, + emitter: Box, + continue_after_error: bool, + delayed_span_bugs: Vec, /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which /// would be uneccessary repetition. - taught_diagnostics: Lock>, + taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain - emitted_diagnostic_codes: Lock>, + emitted_diagnostic_codes: FxHashSet, /// This set contains a hash of every diagnostic that has been emitted by /// this handler. These hashes is used to avoid emitting the same error /// twice. - emitted_diagnostics: Lock>, + emitted_diagnostics: FxHashSet, } fn default_track_diagnostic(_: &Diagnostic) {} @@ -330,7 +333,7 @@ fn default_track_diagnostic(_: &Diagnostic) {} thread_local!(pub static TRACK_DIAGNOSTICS: Cell = Cell::new(default_track_diagnostic)); -#[derive(Default)] +#[derive(Copy, Clone, Default)] pub struct HandlerFlags { /// If false, warning-level lints are suppressed. /// (rustc: see `--allow warnings` and `--cap-lints`) @@ -349,13 +352,13 @@ pub struct HandlerFlags { pub external_macro_backtrace: bool, } -impl Drop for Handler { +impl Drop for HandlerInner { fn drop(&mut self) { - if !self.has_errors() { - let mut bugs = self.delayed_span_bugs.borrow_mut(); + if self.err_count == 0 { + let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new()); let has_bugs = !bugs.is_empty(); - for bug in bugs.drain(..) { - DiagnosticBuilder::new_diagnostic(self, bug).emit(); + for bug in bugs { + self.emit_diagnostic(&bug); } if has_bugs { panic!("no errors encountered even though `delay_span_bug` issued"); @@ -384,7 +387,8 @@ impl Handler { cm: Option>, flags: HandlerFlags) -> Handler { - let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false)); + let emitter = Box::new(EmitterWriter::stderr( + color_config, cm, false, false, None, flags.external_macro_backtrace)); Handler::with_emitter_and_flags(emitter, flags) } @@ -405,19 +409,28 @@ impl Handler { { Handler { flags, - err_count: AtomicUsize::new(0), - deduplicated_err_count: AtomicUsize::new(0), - emitter: Lock::new(e), - continue_after_error: AtomicBool::new(true), - delayed_span_bugs: Lock::new(Vec::new()), - taught_diagnostics: Default::default(), - emitted_diagnostic_codes: Default::default(), - emitted_diagnostics: Default::default(), + inner: Lock::new(HandlerInner { + flags, + err_count: 0, + deduplicated_err_count: 0, + emitter: e, + continue_after_error: true, + delayed_span_bugs: Vec::new(), + taught_diagnostics: Default::default(), + emitted_diagnostic_codes: Default::default(), + emitted_diagnostics: Default::default(), + }), } } pub fn set_continue_after_error(&self, continue_after_error: bool) { - self.continue_after_error.store(continue_after_error, SeqCst); + self.inner.borrow_mut().continue_after_error = continue_after_error; + } + + // This is here to not allow mutation of flags; + // as of this writing it's only used in tests in librustc. + pub fn can_emit_warnings(&self) -> bool { + self.flags.can_emit_warnings } /// Resets the diagnostic error count as well as the cached emitted diagnostics. @@ -425,11 +438,13 @@ impl Handler { /// NOTE: *do not* call this function from rustc. It is only meant to be called from external /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as /// the overall count of emitted error diagnostics. + // FIXME: this does not clear inner entirely pub fn reset_err_count(&self) { + let mut inner = self.inner.borrow_mut(); // actually frees the underlying memory (which `clear` would not do) - *self.emitted_diagnostics.borrow_mut() = Default::default(); - self.deduplicated_err_count.store(0, SeqCst); - self.err_count.store(0, SeqCst); + inner.emitted_diagnostics = Default::default(); + inner.deduplicated_err_count = 0; + inner.err_count = 0; } pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> { @@ -520,30 +535,9 @@ impl Handler { DiagnosticBuilder::new(self, Level::Fatal, msg) } - pub fn cancel(&self, err: &mut DiagnosticBuilder<'_>) { - err.cancel(); - } - - fn panic_if_treat_err_as_bug(&self) { - if self.treat_err_as_bug() { - let s = match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) { - (0, _) => return, - (1, 1) => "aborting due to `-Z treat-err-as-bug=1`".to_string(), - (1, _) => return, - (count, as_bug) => { - format!( - "aborting after {} errors due to `-Z treat-err-as-bug={}`", - count, - as_bug, - ) - } - }; - panic!(s); - } - } - pub fn span_fatal>(&self, sp: S, msg: &str) -> FatalError { - self.emit(&sp.into(), msg, Fatal); + self.emit_diagnostic(Diagnostic::new(Fatal, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); FatalError } pub fn span_fatal_with_code>(&self, @@ -551,11 +545,13 @@ impl Handler { msg: &str, code: DiagnosticId) -> FatalError { - self.emit_with_code(&sp.into(), msg, code, Fatal); + self.emit_diagnostic(Diagnostic::new_with_code(Fatal, Some(code), msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); FatalError } pub fn span_err>(&self, sp: S, msg: &str) { - self.emit(&sp.into(), msg, Error); + self.emit_diagnostic(Diagnostic::new(Error, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn mut_span_err>(&self, sp: S, @@ -566,38 +562,30 @@ impl Handler { result } pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_with_code(&sp.into(), msg, code, Error); + self.emit_diagnostic(Diagnostic::new_with_code(Error, Some(code), msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn span_warn>(&self, sp: S, msg: &str) { - self.emit(&sp.into(), msg, Warning); + self.emit_diagnostic(Diagnostic::new(Warning, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn span_warn_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_with_code(&sp.into(), msg, code, Warning); + self.emit_diagnostic(Diagnostic::new_with_code(Warning, Some(code), msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn span_bug>(&self, sp: S, msg: &str) -> ! { - self.emit(&sp.into(), msg, Bug); - panic!(ExplicitBug); + self.inner.borrow_mut().span_bug(sp, msg) } pub fn delay_span_bug>(&self, sp: S, msg: &str) { - if self.treat_err_as_bug() { - // FIXME: don't abort here if report_delayed_bugs is off - self.span_bug(sp, msg); - } - let mut diagnostic = Diagnostic::new(Level::Bug, msg); - diagnostic.set_span(sp.into()); - self.delay_as_bug(diagnostic); - } - fn delay_as_bug(&self, diagnostic: Diagnostic) { - if self.flags.report_delayed_bugs { - DiagnosticBuilder::new_diagnostic(self, diagnostic.clone()).emit(); - } - self.delayed_span_bugs.borrow_mut().push(diagnostic); + self.inner.borrow_mut().delay_span_bug(sp, msg) } pub fn span_bug_no_panic>(&self, sp: S, msg: &str) { - self.emit(&sp.into(), msg, Bug); + self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn span_note_without_error>(&self, sp: S, msg: &str) { - self.emit(&sp.into(), msg, Note); + self.emit_diagnostic(Diagnostic::new(Note, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); } pub fn span_note_diag(&self, sp: Span, @@ -607,53 +595,29 @@ impl Handler { db.set_span(sp); db } - pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { - self.span_bug(sp, &format!("unimplemented {}", msg)); - } pub fn failure(&self, msg: &str) { - DiagnosticBuilder::new(self, FailureNote, msg).emit() + self.inner.borrow_mut().failure(msg); } pub fn fatal(&self, msg: &str) -> FatalError { - if self.treat_err_as_bug() { - self.bug(msg); - } - DiagnosticBuilder::new(self, Fatal, msg).emit(); - FatalError + self.inner.borrow_mut().fatal(msg) } pub fn err(&self, msg: &str) { - if self.treat_err_as_bug() { - self.bug(msg); - } - let mut db = DiagnosticBuilder::new(self, Error, msg); - db.emit(); + self.inner.borrow_mut().err(msg); } pub fn warn(&self, msg: &str) { let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } - fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.map(|c| self.err_count() >= c).unwrap_or(false) - } pub fn note_without_error(&self, msg: &str) { let mut db = DiagnosticBuilder::new(self, Note, msg); db.emit(); } pub fn bug(&self, msg: &str) -> ! { - let mut db = DiagnosticBuilder::new(self, Bug, msg); - db.emit(); - panic!(ExplicitBug); - } - pub fn unimpl(&self, msg: &str) -> ! { - self.bug(&format!("unimplemented {}", msg)); - } - - fn bump_err_count(&self) { - self.err_count.fetch_add(1, SeqCst); - self.panic_if_treat_err_as_bug(); + self.inner.borrow_mut().bug(msg) } pub fn err_count(&self) -> usize { - self.err_count.load(SeqCst) + self.inner.borrow().err_count } pub fn has_errors(&self) -> bool { @@ -661,7 +625,99 @@ impl Handler { } pub fn print_error_count(&self, registry: &Registry) { - let s = match self.deduplicated_err_count.load(SeqCst) { + self.inner.borrow_mut().print_error_count(registry) + } + + pub fn abort_if_errors(&self) { + self.inner.borrow().abort_if_errors() + } + + pub fn abort_if_errors_and_should_abort(&self) { + self.inner.borrow().abort_if_errors_and_should_abort() + } + + pub fn must_teach(&self, code: &DiagnosticId) -> bool { + self.inner.borrow_mut().must_teach(code) + } + + pub fn force_print_diagnostic(&self, db: Diagnostic) { + self.inner.borrow_mut().force_print_diagnostic(db) + } + + pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) { + self.inner.borrow_mut().emit_diagnostic(diagnostic) + } + + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { + self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) + } + + pub fn delay_as_bug(&self, diagnostic: Diagnostic) { + self.inner.borrow_mut().delay_as_bug(diagnostic) + } +} + +impl HandlerInner { + /// `true` if we haven't taught a diagnostic with this code already. + /// The caller must then teach the user about such a diagnostic. + /// + /// Used to suppress emitting the same error multiple times with extended explanation when + /// calling `-Zteach`. + fn must_teach(&mut self, code: &DiagnosticId) -> bool { + self.taught_diagnostics.insert(code.clone()) + } + + fn force_print_diagnostic(&mut self, db: Diagnostic) { + self.emitter.emit_diagnostic(&db); + } + + fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) { + if diagnostic.cancelled() { + return; + } + + if diagnostic.level == Warning && !self.flags.can_emit_warnings { + return; + } + + TRACK_DIAGNOSTICS.with(|track_diagnostics| { + track_diagnostics.get()(diagnostic); + }); + + if let Some(ref code) = diagnostic.code { + self.emitted_diagnostic_codes.insert(code.clone()); + } + + let diagnostic_hash = { + use std::hash::Hash; + let mut hasher = StableHasher::new(); + diagnostic.hash(&mut hasher); + hasher.finish() + }; + + // Only emit the diagnostic if we haven't already emitted an equivalent + // one: + if self.emitted_diagnostics.insert(diagnostic_hash) { + self.emitter.emit_diagnostic(diagnostic); + if diagnostic.is_error() { + self.deduplicated_err_count += 1; + } + } + if diagnostic.is_error() { + self.bump_err_count(); + } + } + + fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { + self.emitter.emit_artifact_notification(path, artifact_type); + } + + fn treat_err_as_bug(&self) -> bool { + self.flags.treat_err_as_bug.map(|c| self.err_count >= c).unwrap_or(false) + } + + fn print_error_count(&mut self, registry: &Registry) { + let s = match self.deduplicated_err_count { 0 => return, 1 => "aborting due to previous error".to_string(), count => format!("aborting due to {} previous errors", count) @@ -672,12 +728,11 @@ impl Handler { let _ = self.fatal(&s); - let can_show_explain = self.emitter.borrow().should_show_explain(); - let are_there_diagnostics = !self.emitted_diagnostic_codes.borrow().is_empty(); + let can_show_explain = self.emitter.should_show_explain(); + let are_there_diagnostics = !self.emitted_diagnostic_codes.is_empty(); if can_show_explain && are_there_diagnostics { let mut error_codes = self .emitted_diagnostic_codes - .borrow() .iter() .filter_map(|x| match &x { DiagnosticId::Error(s) if registry.find_description(s).is_some() => { @@ -705,81 +760,86 @@ impl Handler { } } - pub fn abort_if_errors(&self) { - if self.has_errors() { + fn abort_if_errors_and_should_abort(&self) { + if self.err_count > 0 && !self.continue_after_error { FatalError.raise(); } } - pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) { - if lvl == Warning && !self.flags.can_emit_warnings { - return; - } - let mut db = DiagnosticBuilder::new(self, lvl, msg); - db.set_span(msp.clone()); - db.emit(); - if !self.continue_after_error.load(SeqCst) { - self.abort_if_errors(); - } - } - pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl: Level) { - if lvl == Warning && !self.flags.can_emit_warnings { - return; - } - let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg); - db.set_span(msp.clone()); - db.emit(); - if !self.continue_after_error.load(SeqCst) { - self.abort_if_errors(); + + fn abort_if_errors(&self) { + if self.err_count > 0 { + FatalError.raise(); } } - /// `true` if we haven't taught a diagnostic with this code already. - /// The caller must then teach the user about such a diagnostic. - /// - /// Used to suppress emitting the same error multiple times with extended explanation when - /// calling `-Zteach`. - pub fn must_teach(&self, code: &DiagnosticId) -> bool { - self.taught_diagnostics.borrow_mut().insert(code.clone()) + fn span_bug>(&mut self, sp: S, msg: &str) -> ! { + self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); + self.abort_if_errors_and_should_abort(); + panic!(ExplicitBug); } - pub fn force_print_db(&self, mut db: DiagnosticBuilder<'_>) { - self.emitter.borrow_mut().emit_diagnostic(&db); - db.cancel(); + fn delay_span_bug>(&mut self, sp: S, msg: &str) { + if self.treat_err_as_bug() { + // FIXME: don't abort here if report_delayed_bugs is off + self.span_bug(sp, msg); + } + let mut diagnostic = Diagnostic::new(Level::Bug, msg); + diagnostic.set_span(sp.into()); + self.delay_as_bug(diagnostic) } - fn emit_db(&self, db: &DiagnosticBuilder<'_>) { - let diagnostic = &**db; + fn failure(&mut self, msg: &str) { + self.emit_diagnostic(&Diagnostic::new(FailureNote, msg)); + } - TRACK_DIAGNOSTICS.with(|track_diagnostics| { - track_diagnostics.get()(diagnostic); - }); + fn fatal(&mut self, msg: &str) -> FatalError { + if self.treat_err_as_bug() { + self.bug(msg); + } + self.emit_diagnostic(&Diagnostic::new(Fatal, msg)); + FatalError + } - if let Some(ref code) = diagnostic.code { - self.emitted_diagnostic_codes.borrow_mut().insert(code.clone()); + fn err(&mut self, msg: &str) { + if self.treat_err_as_bug() { + self.bug(msg); } + self.emit_diagnostic(&Diagnostic::new(Error, msg)); + } - let diagnostic_hash = { - use std::hash::Hash; - let mut hasher = StableHasher::new(); - diagnostic.hash(&mut hasher); - hasher.finish() - }; + fn bug(&mut self, msg: &str) -> ! { + self.emit_diagnostic(&Diagnostic::new(Bug, msg)); + panic!(ExplicitBug); + } - // Only emit the diagnostic if we haven't already emitted an equivalent - // one: - if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) { - self.emitter.borrow_mut().emit_diagnostic(db); - if db.is_error() { - self.deduplicated_err_count.fetch_add(1, SeqCst); - } - } - if db.is_error() { - self.bump_err_count(); + fn delay_as_bug(&mut self, diagnostic: Diagnostic) { + if self.flags.report_delayed_bugs { + self.emit_diagnostic(&diagnostic); } + self.delayed_span_bugs.push(diagnostic); } - pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.emitter.borrow_mut().emit_artifact_notification(path, artifact_type); + fn bump_err_count(&mut self) { + self.err_count += 1; + self.panic_if_treat_err_as_bug(); + } + + fn panic_if_treat_err_as_bug(&self) { + if self.treat_err_as_bug() { + let s = match (self.err_count, self.flags.treat_err_as_bug.unwrap_or(0)) { + (0, _) => return, + (1, 1) => "aborting due to `-Z treat-err-as-bug=1`".to_string(), + (1, _) => return, + (count, as_bug) => { + format!( + "aborting after {} errors due to `-Z treat-err-as-bug={}`", + count, + as_bug, + ) + } + }; + panic!(s); + } } } @@ -787,9 +847,6 @@ impl Handler { pub enum Level { Bug, Fatal, - // An error which while not immediately fatal, should stop the compiler - // progressing beyond the current phase. - PhaseFatal, Error, Warning, Note, @@ -808,7 +865,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | Fatal | PhaseFatal | Error => { + Bug | Fatal | Error => { spec.set_fg(Some(Color::Red)) .set_intense(true); } @@ -833,11 +890,11 @@ impl Level { pub fn to_str(self) -> &'static str { match self { Bug => "error: internal compiler error", - Fatal | PhaseFatal | Error => "error", + Fatal | Error => "error", Warning => "warning", Note => "note", Help => "help", - FailureNote => "", + FailureNote => "failure-note", Cancelled => panic!("Shouldn't call on cancelled error"), } } @@ -849,3 +906,10 @@ impl Level { } } } + +#[macro_export] +macro_rules! pluralise { + ($x:expr) => { + if $x != 1 { "s" } else { "" } + }; +} diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index a931ad3b66..659c4c89fe 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -12,7 +12,7 @@ doctest = false [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -rand = "0.6" +rand = "0.7" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 046fdc7227..e08eeaf857 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -27,7 +27,7 @@ use rustc::mir::mono::CodegenUnitNameBuilder; use rustc::ty::TyCtxt; use std::collections::BTreeSet; use syntax::ast; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::{InternedString, Symbol, sym}; use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED, ATTR_EXPECTED_CGU_REUSE}; @@ -45,8 +45,8 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { .collect_and_partition_mono_items(LOCAL_CRATE) .1 .iter() - .map(|cgu| format!("{}", cgu.name())) - .collect::>(); + .map(|cgu| *cgu.name()) + .collect::>(); let ams = AssertModuleSource { tcx, @@ -61,7 +61,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { struct AssertModuleSource<'tcx> { tcx: TyCtxt<'tcx>, - available_cgus: BTreeSet, + available_cgus: BTreeSet, } impl AssertModuleSource<'tcx> { @@ -127,7 +127,7 @@ impl AssertModuleSource<'tcx> { debug!("mapping '{}' to cgu name '{}'", self.field(attr, MODULE), cgu_name); - if !self.available_cgus.contains(&cgu_name.as_str()[..]) { + if !self.available_cgus.contains(&cgu_name) { self.tcx.sess.span_err(attr.span, &format!("no module named `{}` (mangled: {}). \ Available modules: {}", @@ -135,7 +135,7 @@ impl AssertModuleSource<'tcx> { cgu_name, self.available_cgus .iter() - .cloned() + .map(|cgu| cgu.as_str().to_string()) .collect::>() .join(", "))); } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index e569a9bc7d..837aa9360c 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -24,6 +24,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; use rustc::ty::TyCtxt; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; use syntax::ast::{self, Attribute, NestedMetaItem}; use syntax::symbol::{Symbol, sym}; @@ -71,6 +72,7 @@ const BASE_IMPL: &[&str] = &[ /// code, i.e., functions+methods const BASE_MIR: &[&str] = &[ label_strs::optimized_mir, + label_strs::promoted_mir, label_strs::mir_built, ]; @@ -472,11 +474,10 @@ impl DirtyCleanVisitor<'tcx> { fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) == prev_fingerprint { + if current_fingerprint == prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, @@ -484,14 +485,28 @@ impl DirtyCleanVisitor<'tcx> { } } + fn get_fingerprint(&self, dep_node: &DepNode) -> Option { + if self.tcx.dep_graph.dep_node_exists(dep_node) { + let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node); + Some(self.tcx.dep_graph.fingerprint_of(dep_node_index)) + } else { + None + } + } + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) != prev_fingerprint { + // if the node wasn't previously evaluated and now is (or vice versa), + // then the node isn't actually clean or dirty. + if (current_fingerprint == None) ^ (prev_fingerprint == None) { + return; + } + + if current_fingerprint != prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 4937801d31..f6293107a9 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -30,7 +30,8 @@ rustc_passes = { path = "../librustc_passes" } rustc_typeck = { path = "../librustc_typeck" } rustc_lint = { path = "../librustc_lint" } rustc_errors = { path = "../librustc_errors" } -rustc_plugin = { path = "../librustc_plugin" } +rustc_plugin = { path = "../librustc_plugin", package = "rustc_plugin_impl" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } tempfile = "3.0.5" +once_cell = "1" diff --git a/src/librustc_interface/build.rs b/src/librustc_interface/build.rs new file mode 100644 index 0000000000..79a343e0fe --- /dev/null +++ b/src/librustc_interface/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=RUSTC_INSTALL_BINDIR"); +} diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8b0b5a5b7a..e8e8da6733 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -34,14 +34,13 @@ use rustc_privacy; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_traits; use rustc_typeck as typeck; -use syntax::{self, ast, diagnostics, visit}; +use syntax::{self, ast, visit}; use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; use syntax::symbol::Symbol; -use syntax::feature_gate::AttributeType; use syntax_pos::FileName; use syntax_ext; @@ -219,7 +218,6 @@ impl BoxedResolver { pub struct PluginInfo { syntax_exts: Vec, - attributes: Vec<(Symbol, AttributeType)>, } pub fn register_plugins<'a>( @@ -230,10 +228,12 @@ pub fn register_plugins<'a>( crate_name: &str, ) -> Result<(ast::Crate, PluginInfo)> { krate = time(sess, "attributes injection", || { - syntax::attr::inject(krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr) + syntax_ext::cmdline_attrs::inject( + krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr + ) }); - let (mut krate, features) = syntax::config::features( + let (krate, features) = syntax::config::features( krate, &sess.parse_sess, sess.edition(), @@ -268,16 +268,6 @@ pub fn register_plugins<'a>( middle::recursion_limit::update_limits(sess, &krate); }); - krate = time(sess, "crate injection", || { - let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s); - let (krate, name) = - syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition()); - if let Some(name) = name { - sess.parse_sess.injected_crate_name.set(name); - } - krate - }); - let registrars = time(sess, "plugin loading", || { plugin::load::load_plugins( sess, @@ -291,21 +281,6 @@ pub fn register_plugins<'a>( let mut registry = Registry::new(sess, krate.span); time(sess, "plugin registration", || { - if sess.features_untracked().rustc_diagnostic_macros { - registry.register_macro( - "__diagnostic_used", - diagnostics::plugin::expand_diagnostic_used, - ); - registry.register_macro( - "__register_diagnostic", - diagnostics::plugin::expand_register_diagnostic, - ); - registry.register_macro( - "__build_diagnostic_array", - diagnostics::plugin::expand_build_diagnostic_array, - ); - } - for registrar in registrars { registry.args_hidden = Some(registrar.args); (registrar.fun)(&mut registry); @@ -335,12 +310,9 @@ pub fn register_plugins<'a>( } *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; - *sess.plugin_attributes.borrow_mut() = attributes.clone(); + *sess.plugin_attributes.borrow_mut() = attributes; - Ok((krate, PluginInfo { - syntax_exts, - attributes, - })) + Ok((krate, PluginInfo { syntax_exts })) } fn configure_and_expand_inner<'a>( @@ -352,7 +324,6 @@ fn configure_and_expand_inner<'a>( crate_loader: &'a mut CrateLoader<'a>, plugin_info: PluginInfo, ) -> Result<(ast::Crate, Resolver<'a>)> { - let attributes = plugin_info.attributes; time(sess, "pre ast expansion lint checks", || { lint::check_ast_crate( sess, @@ -370,6 +341,21 @@ fn configure_and_expand_inner<'a>( &resolver_arenas, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); + + krate = time(sess, "crate injection", || { + let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); + let (krate, name) = syntax_ext::standard_library_imports::inject( + krate, + &mut resolver, + &sess.parse_sess, + alt_std_name, + ); + if let Some(name) = name { + sess.parse_sess.injected_crate_name.set(name); + } + krate + }); + syntax_ext::plugin_macro_defs::inject( &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() ); @@ -473,14 +459,25 @@ fn configure_and_expand_inner<'a>( ast_validation::check_crate(sess, &krate) }); - // If we're in rustdoc we're always compiling as an rlib, but that'll trip a - // bunch of checks in the `modify` function below. For now just skip this - // step entirely if we're rustdoc as it's not too useful anyway. - if !sess.opts.actually_rustdoc { + + let crate_types = sess.crate_types.borrow(); + let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); + + // For backwards compatibility, we don't try to run proc macro injection + // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being + // specified. This should only affect users who manually invoke 'rustdoc', as + // 'cargo doc' will automatically pass the proper '--crate-type' flags. + // However, we do emit a warning, to let such users know that they should + // start passing '--crate-type proc-macro' + if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { + let mut msg = sess.diagnostic().struct_warn(&"Trying to document proc macro crate \ + without passing '--crate-type proc-macro to rustdoc"); + + msg.warn("The generated documentation may be incorrect"); + msg.emit() + } else { krate = time(sess, "maybe creating a macro crate", || { - let crate_types = sess.crate_types.borrow(); let num_crate_types = crate_types.len(); - let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); let is_test_crate = sess.opts.test; syntax_ext::proc_macro_harness::inject( &sess.parse_sess, @@ -519,7 +516,6 @@ fn configure_and_expand_inner<'a>( &krate, &sess.parse_sess, &sess.features_untracked(), - &attributes, sess.opts.unstable_features, ); }); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index f007a0cf2a..b81f814de0 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -43,17 +43,17 @@ use std::{thread, panic}; pub fn diagnostics_registry() -> Registry { let mut all_errors = Vec::new(); - all_errors.extend_from_slice(&rustc::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_typeck::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_resolve::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_privacy::error_codes::DIAGNOSTICS); // FIXME: need to figure out a way to get these back in here // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics()); - all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_mir::DIAGNOSTICS); - all_errors.extend_from_slice(&syntax::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_metadata::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_passes::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_plugin::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_mir::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&syntax::error_codes::DIAGNOSTICS); Registry::new(&all_errors) } @@ -289,20 +289,39 @@ pub fn get_codegen_backend(sess: &Session) -> Box { backend } -pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box { - // For now we only allow this function to be called once as it'll dlopen a - // few things, which seems to work best if we only do that once. In - // general this assertion never trips due to the once guard in `get_codegen_backend`, - // but there's a few manual calls to this function in this file we protect - // against. - static LOADED: AtomicBool = AtomicBool::new(false); - assert!(!LOADED.fetch_or(true, Ordering::SeqCst), - "cannot load the default codegen backend twice"); +// This is used for rustdoc, but it uses similar machinery to codegen backend +// loading, so we leave the code here. It is potentially useful for other tools +// that want to invoke the rustc binary while linking to rustc as well. +pub fn rustc_path<'a>() -> Option<&'a Path> { + static RUSTC_PATH: once_cell::sync::OnceCell> = + once_cell::sync::OnceCell::new(); + const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR"); + + RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_ref().map(|v| &**v) +} + +fn get_rustc_path_inner(bin_path: &str) -> Option { + sysroot_candidates().iter() + .filter_map(|sysroot| { + let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") { + "rustc.exe" + } else { + "rustc" + }); + if candidate.exists() { + Some(candidate) + } else { + None + } + }) + .next() +} + +fn sysroot_candidates() -> Vec { let target = session::config::host_triple(); let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()]; - let path = current_dll_path() - .and_then(|s| s.canonicalize().ok()); + let path = current_dll_path().and_then(|s| s.canonicalize().ok()); if let Some(dll) = path { // use `parent` twice to chop off the file name and then also the // directory containing the dll which should be either `lib` or `bin`. @@ -327,69 +346,7 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box>() - .join("\n* "); - let err = format!("failed to find a `codegen-backends` folder \ - in the sysroot candidates:\n* {}", candidates); - early_error(ErrorOutputType::default(), &err); - }); - info!("probing {} for a codegen backend", sysroot.display()); - - let d = sysroot.read_dir().unwrap_or_else(|e| { - let err = format!("failed to load default codegen backend, couldn't \ - read `{}`: {}", sysroot.display(), e); - early_error(ErrorOutputType::default(), &err); - }); - - let mut file: Option = None; - - let expected_name = format!("rustc_codegen_llvm-{}", backend_name); - for entry in d.filter_map(|e| e.ok()) { - let path = entry.path(); - let filename = match path.file_name().and_then(|s| s.to_str()) { - Some(s) => s, - None => continue, - }; - if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) { - continue - } - let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()]; - if name != expected_name { - continue - } - if let Some(ref prev) = file { - let err = format!("duplicate codegen backends found\n\ - first: {}\n\ - second: {}\n\ - ", prev.display(), path.display()); - early_error(ErrorOutputType::default(), &err); - } - file = Some(path.clone()); - } - - match file { - Some(ref s) => return load_backend_from_dylib(s), - None => { - let err = format!("failed to load default codegen backend for `{}`, \ - no appropriate codegen dylib found in `{}`", - backend_name, sysroot.display()); - early_error(ErrorOutputType::default(), &err); - } - } + return sysroot_candidates; #[cfg(unix)] fn current_dll_path() -> Option { @@ -459,6 +416,85 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box fn() -> Box { + // For now we only allow this function to be called once as it'll dlopen a + // few things, which seems to work best if we only do that once. In + // general this assertion never trips due to the once guard in `get_codegen_backend`, + // but there's a few manual calls to this function in this file we protect + // against. + static LOADED: AtomicBool = AtomicBool::new(false); + assert!(!LOADED.fetch_or(true, Ordering::SeqCst), + "cannot load the default codegen backend twice"); + + let target = session::config::host_triple(); + let sysroot_candidates = sysroot_candidates(); + + let sysroot = sysroot_candidates.iter() + .map(|sysroot| { + let libdir = filesearch::relative_target_lib_path(&sysroot, &target); + sysroot.join(libdir).with_file_name( + option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends")) + }) + .filter(|f| { + info!("codegen backend candidate: {}", f.display()); + f.exists() + }) + .next(); + let sysroot = sysroot.unwrap_or_else(|| { + let candidates = sysroot_candidates.iter() + .map(|p| p.display().to_string()) + .collect::>() + .join("\n* "); + let err = format!("failed to find a `codegen-backends` folder \ + in the sysroot candidates:\n* {}", candidates); + early_error(ErrorOutputType::default(), &err); + }); + info!("probing {} for a codegen backend", sysroot.display()); + + let d = sysroot.read_dir().unwrap_or_else(|e| { + let err = format!("failed to load default codegen backend, couldn't \ + read `{}`: {}", sysroot.display(), e); + early_error(ErrorOutputType::default(), &err); + }); + + let mut file: Option = None; + + let expected_name = format!("rustc_codegen_llvm-{}", backend_name); + for entry in d.filter_map(|e| e.ok()) { + let path = entry.path(); + let filename = match path.file_name().and_then(|s| s.to_str()) { + Some(s) => s, + None => continue, + }; + if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) { + continue + } + let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()]; + if name != expected_name { + continue + } + if let Some(ref prev) = file { + let err = format!("duplicate codegen backends found\n\ + first: {}\n\ + second: {}\n\ + ", prev.display(), path.display()); + early_error(ErrorOutputType::default(), &err); + } + file = Some(path.clone()); + } + + match file { + Some(ref s) => return load_backend_from_dylib(s), + None => { + let err = format!("failed to load default codegen backend for `{}`, \ + no appropriate codegen dylib found in `{}`", + backend_name, sysroot.display()); + early_error(ErrorOutputType::default(), &err); + } + } + +} + pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator { use std::hash::Hasher; diff --git a/src/librustc_lexer/Cargo.toml b/src/librustc_lexer/Cargo.toml index 0dbcda618e..950771f0a6 100644 --- a/src/librustc_lexer/Cargo.toml +++ b/src/librustc_lexer/Cargo.toml @@ -2,14 +2,20 @@ authors = ["The Rust Project Developers"] name = "rustc_lexer" version = "0.1.0" +license = "MIT OR Apache-2.0" edition = "2018" -# Note that this crate purposefully does not depend on other rustc crates -[dependencies] -unicode-xid = { version = "0.1.0", optional = true } +repository = "https://github.com/rust-lang/rust/" +description = """ +Rust lexer used by rustc. No stability guarantees are provided. +""" # Note: do not remove this blank `[lib]` section. # This will be used when publishing this crate as `rustc-ap-rustc_lexer`. [lib] doctest = false name = "rustc_lexer" + +# Note that this crate purposefully does not depend on other rustc crates +[dependencies] +unicode-xid = "0.2.0" diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index c02abe6b89..08608cfe98 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -1,6 +1,5 @@ -// We want to be able to build this crate with a stable compiler, so feature -// flags should be optional. -#![cfg_attr(not(feature = "unicode-xid"), feature(unicode_internals))] +// We want to be able to build this crate with a stable compiler, so no +// `#![feature]` attributes should be added. mod cursor; pub mod unescape; @@ -23,9 +22,6 @@ pub enum TokenKind { Lifetime { starts_with_number: bool }, Semi, Comma, - DotDotDot, - DotDotEq, - DotDot, Dot, OpenParen, CloseParen, @@ -37,41 +33,19 @@ pub enum TokenKind { Pound, Tilde, Question, - ColonColon, Colon, Dollar, - EqEq, Eq, - FatArrow, - Ne, Not, - Le, - LArrow, Lt, - ShlEq, - Shl, - Ge, Gt, - ShrEq, - Shr, - RArrow, Minus, - MinusEq, And, - AndAnd, - AndEq, Or, - OrOr, - OrEq, - PlusEq, Plus, - StarEq, Star, - SlashEq, Slash, - CaretEq, Caret, - PercentEq, Percent, Unknown, } @@ -128,6 +102,62 @@ pub fn tokenize(mut input: &str) -> impl Iterator + '_ { }) } +// See [UAX #31](http://unicode.org/reports/tr31) for definitions of these +// classes. + +/// True if `c` is considered a whitespace according to Rust language definition. +pub fn is_whitespace(c: char) -> bool { + // This is Pattern_White_Space. + // + // Note that this set is stable (ie, it doesn't change with different + // Unicode versions), so it's ok to just hard-code the values. + + match c { + // Usual ASCII suspects + | '\u{0009}' // \t + | '\u{000A}' // \n + | '\u{000B}' // vertical tab + | '\u{000C}' // form feed + | '\u{000D}' // \r + | '\u{0020}' // space + + // NEXT LINE from latin1 + | '\u{0085}' + + // Bidi markers + | '\u{200E}' // LEFT-TO-RIGHT MARK + | '\u{200F}' // RIGHT-TO-LEFT MARK + + // Dedicated whitespace characters from Unicode + | '\u{2028}' // LINE SEPARATOR + | '\u{2029}' // PARAGRAPH SEPARATOR + => true, + _ => false, + } +} + +/// True if `c` is valid as a first character of an identifier. +pub fn is_id_start(c: char) -> bool { + // This is XID_Start OR '_' (which formally is not a XID_Start). + // We also add fast-path for ascii idents + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || c == '_' + || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) +} + +/// True if `c` is valid as a non-first character of an identifier. +pub fn is_id_continue(c: char) -> bool { + // This is exactly XID_Continue. + // We also add fast-path for ascii idents + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || ('0' <= c && c <= '9') + || c == '_' + || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) +} + + impl Cursor<'_> { fn advance_token(&mut self) -> Token { let first_char = self.bump().unwrap(); @@ -135,17 +165,11 @@ impl Cursor<'_> { '/' => match self.nth_char(0) { '/' => self.line_comment(), '*' => self.block_comment(), - _ => { - if self.eat_assign() { - SlashEq - } else { - Slash - } - } + _ => Slash, }, - c if character_properties::is_whitespace(c) => self.whitespace(), + c if is_whitespace(c) => self.whitespace(), 'r' => match (self.nth_char(0), self.nth_char(1)) { - ('#', c1) if character_properties::is_id_start(c1) => self.raw_ident(), + ('#', c1) if is_id_start(c1) => self.raw_ident(), ('#', _) | ('"', _) => { let (n_hashes, started, terminated) = self.raw_double_quoted_string(); let suffix_start = self.len_consumed(); @@ -190,7 +214,7 @@ impl Cursor<'_> { } _ => self.ident(), }, - c if character_properties::is_id_start(c) => self.ident(), + c if is_id_start(c) => self.ident(), c @ '0'..='9' => { let literal_kind = self.number(c); let suffix_start = self.len_consumed(); @@ -199,22 +223,7 @@ impl Cursor<'_> { } ';' => Semi, ',' => Comma, - '.' => { - if self.nth_char(0) == '.' { - self.bump(); - if self.nth_char(0) == '.' { - self.bump(); - DotDotDot - } else if self.nth_char(0) == '=' { - self.bump(); - DotDotEq - } else { - DotDot - } - } else { - Dot - } - } + '.' => Dot, '(' => OpenParen, ')' => CloseParen, '{' => OpenBrace, @@ -225,112 +234,19 @@ impl Cursor<'_> { '#' => Pound, '~' => Tilde, '?' => Question, - ':' => { - if self.nth_char(0) == ':' { - self.bump(); - ColonColon - } else { - Colon - } - } + ':' => Colon, '$' => Dollar, - '=' => { - if self.nth_char(0) == '=' { - self.bump(); - EqEq - } else if self.nth_char(0) == '>' { - self.bump(); - FatArrow - } else { - Eq - } - } - '!' => { - if self.nth_char(0) == '=' { - self.bump(); - Ne - } else { - Not - } - } - '<' => match self.nth_char(0) { - '=' => { - self.bump(); - Le - } - '<' => { - self.bump(); - if self.eat_assign() { ShlEq } else { Shl } - } - '-' => { - self.bump(); - LArrow - } - _ => Lt, - }, - '>' => match self.nth_char(0) { - '=' => { - self.bump(); - Ge - } - '>' => { - self.bump(); - if self.eat_assign() { ShrEq } else { Shr } - } - _ => Gt, - }, - '-' => { - if self.nth_char(0) == '>' { - self.bump(); - RArrow - } else { - if self.eat_assign() { MinusEq } else { Minus } - } - } - '&' => { - if self.nth_char(0) == '&' { - self.bump(); - AndAnd - } else { - if self.eat_assign() { AndEq } else { And } - } - } - '|' => { - if self.nth_char(0) == '|' { - self.bump(); - OrOr - } else { - if self.eat_assign() { OrEq } else { Or } - } - } - '+' => { - if self.eat_assign() { - PlusEq - } else { - Plus - } - } - '*' => { - if self.eat_assign() { - StarEq - } else { - Star - } - } - '^' => { - if self.eat_assign() { - CaretEq - } else { - Caret - } - } - '%' => { - if self.eat_assign() { - PercentEq - } else { - Percent - } - } + '=' => Eq, + '!' => Not, + '<' => Lt, + '>' => Gt, + '-' => Minus, + '&' => And, + '|' => Or, + '+' => Plus, + '*' => Star, + '^' => Caret, + '%' => Percent, '\'' => self.lifetime_or_char(), '"' => { let terminated = self.double_quoted_string(); @@ -387,8 +303,8 @@ impl Cursor<'_> { } fn whitespace(&mut self) -> TokenKind { - debug_assert!(character_properties::is_whitespace(self.prev())); - while character_properties::is_whitespace(self.nth_char(0)) { + debug_assert!(is_whitespace(self.prev())); + while is_whitespace(self.nth_char(0)) { self.bump(); } Whitespace @@ -398,19 +314,19 @@ impl Cursor<'_> { debug_assert!( self.prev() == 'r' && self.nth_char(0) == '#' - && character_properties::is_id_start(self.nth_char(1)) + && is_id_start(self.nth_char(1)) ); self.bump(); self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } RawIdent } fn ident(&mut self) -> TokenKind { - debug_assert!(character_properties::is_id_start(self.prev())); - while character_properties::is_id_continue(self.nth_char(0)) { + debug_assert!(is_id_start(self.prev())); + while is_id_continue(self.nth_char(0)) { self.bump(); } Ident @@ -455,7 +371,7 @@ impl Cursor<'_> { // integer literal followed by field/method access or a range pattern // (`0..2` and `12.foo()`) '.' if self.nth_char(1) != '.' - && !character_properties::is_id_start(self.nth_char(1)) => + && !is_id_start(self.nth_char(1)) => { // might have stuff after the ., and if it does, it needs to start // with a number @@ -485,7 +401,7 @@ impl Cursor<'_> { fn lifetime_or_char(&mut self) -> TokenKind { debug_assert!(self.prev() == '\''); let mut starts_with_number = false; - if (character_properties::is_id_start(self.nth_char(0)) + if (is_id_start(self.nth_char(0)) || self.nth_char(0).is_digit(10) && { starts_with_number = true; true @@ -493,7 +409,7 @@ impl Cursor<'_> { && self.nth_char(1) != '\'' { self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } @@ -636,75 +552,13 @@ impl Cursor<'_> { } fn eat_literal_suffix(&mut self) { - if !character_properties::is_id_start(self.nth_char(0)) { + if !is_id_start(self.nth_char(0)) { return; } self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } } - - fn eat_assign(&mut self) -> bool { - if self.nth_char(0) == '=' { - self.bump(); - true - } else { - false - } - } -} - -pub mod character_properties { - // this is Pattern_White_Space - #[cfg(feature = "unicode-xid")] - pub fn is_whitespace(c: char) -> bool { - match c { - '\u{0009}' | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0020}' - | '\u{0085}' | '\u{200E}' | '\u{200F}' | '\u{2028}' | '\u{2029}' => true, - _ => false, - } - } - - #[cfg(not(feature = "unicode-xid"))] - pub fn is_whitespace(c: char) -> bool { - core::unicode::property::Pattern_White_Space(c) - } - - // this is XID_Start OR '_' (which formally is not a XID_Start) - #[cfg(feature = "unicode-xid")] - pub fn is_id_start(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) - } - - #[cfg(not(feature = "unicode-xid"))] - pub fn is_id_start(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || (c > '\x7f' && c.is_xid_start()) - } - - // this is XID_Continue - #[cfg(feature = "unicode-xid")] - pub fn is_id_continue(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') - || c == '_' - || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) - } - - #[cfg(not(feature = "unicode-xid"))] - pub fn is_id_continue(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') - || c == '_' - || (c > '\x7f' && c.is_xid_continue()) - } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index bb2a5cab7d..cf19a9eb14 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -42,7 +42,7 @@ use syntax::source_map::Spanned; use syntax::edition::Edition; use syntax::feature_gate::{self, AttributeGate, AttributeType}; use syntax::feature_gate::{Stability, deprecated_attributes}; -use syntax_pos::{BytePos, Span, SyntaxContext}; +use syntax_pos::{BytePos, Span}; use syntax::symbol::{Symbol, kw, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; @@ -78,7 +78,7 @@ impl EarlyLintPass for WhileTrue { if let ast::ExprKind::While(cond, ..) = &e.node { if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).node { if let ast::LitKind::Bool(true) = lit.node { - if lit.span.ctxt() == SyntaxContext::empty() { + if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; let condition_span = cx.sess.source_map().def_span(e.span); cx.struct_span_lint(WHILE_TRUE, condition_span, msg) @@ -164,18 +164,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { .expect("struct pattern type is not an ADT") .variant_of_res(cx.tables.qpath_res(qpath, pat.hir_id)); for fieldpat in field_pats { - if fieldpat.node.is_shorthand { + if fieldpat.is_shorthand { continue; } - if fieldpat.span.ctxt().outer_expn_info().is_some() { + if fieldpat.span.from_expansion() { // Don't lint if this is a macro expansion: macro authors // shouldn't have to worry about this kind of style issue // (Issue #49588) continue; } - if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node { + if let PatKind::Binding(_, _, ident, None) = fieldpat.pat.node { if cx.tcx.find_field_index(ident, &variant) == - Some(cx.tcx.field_index(fieldpat.node.hir_id, cx.tables)) { + Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) { let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, &format!("the `{}:` in this pattern is redundant", ident)); @@ -482,10 +482,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } } - fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) { + fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant) { self.check_missing_docs_attrs(cx, - Some(v.node.id), - &v.node.attrs, + Some(v.id), + &v.attrs, v.span, "a variant"); } @@ -570,7 +570,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { _ => return, } - let debug = match cx.tcx.lang_items().debug_trait() { + let debug = match cx.tcx.get_diagnostic_item(sym::debug_trait) { Some(debug) => debug, None => return, }; @@ -669,6 +669,22 @@ impl DeprecatedAttr { } } +fn lint_deprecated_attr( + cx: &EarlyContext<'_>, + attr: &ast::Attribute, + msg: &str, + suggestion: Option<&str>, +) { + cx.struct_span_lint(DEPRECATED, attr.span, &msg) + .span_suggestion_short( + attr.span, + suggestion.unwrap_or("remove this attribute"), + String::new(), + Applicability::MachineApplicable + ) + .emit(); +} + impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { for &&(n, _, _, ref g) in &self.depr_attrs { @@ -679,18 +695,15 @@ impl EarlyLintPass for DeprecatedAttr { _) = g { let msg = format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link); - let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg); - err.span_suggestion_short( - attr.span, - suggestion.unwrap_or("remove this attribute"), - String::new(), - Applicability::MachineApplicable - ); - err.emit(); + lint_deprecated_attr(cx, attr, &msg, suggestion); } return; } } + if attr.check_name(sym::no_start) || attr.check_name(sym::crate_id) { + let msg = format!("use of deprecated attribute `{}`: no longer used.", attr.path); + lint_deprecated_attr(cx, attr, &msg, None); + } } } @@ -772,7 +785,7 @@ impl EarlyLintPass for UnusedDocComment { } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - let arm_span = arm.pats[0].span.with_hi(arm.body.span.hi()); + let arm_span = arm.pat.span.with_hi(arm.body.span.hi()); self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs); } @@ -1012,7 +1025,7 @@ impl UnreachablePub { let mut applicability = Applicability::MachineApplicable; match vis.node { hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => { - if span.ctxt().outer_expn_info().is_some() { + if span.from_expansion() { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.sess.source_map().def_span(span); @@ -1493,7 +1506,7 @@ impl EarlyLintPass for KeywordIdents { self.check_tokens(cx, mac_def.stream()); } fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { - self.check_tokens(cx, mac.node.tts.clone().into()); + self.check_tokens(cx, mac.tts.clone().into()); } fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) { self.check_ident_token(cx, UnderMacro(false), ident); @@ -1876,16 +1889,70 @@ declare_lint_pass!(InvalidValue => [INVALID_VALUE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) { - const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; - const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + #[derive(Debug, Copy, Clone, PartialEq)] + enum InitKind { Zeroed, Uninit }; /// Information about why a type cannot be initialized this way. /// Contains an error message and optionally a span to point at. type InitError = (String, Option); + /// Test if this constant is all-0. + fn is_zero(expr: &hir::Expr) -> bool { + use hir::ExprKind::*; + use syntax::ast::LitKind::*; + match &expr.node { + Lit(lit) => + if let Int(i, _) = lit.node { + i == 0 + } else { + false + }, + Tup(tup) => + tup.iter().all(is_zero), + _ => + false + } + } + + /// Determine if this expression is a "dangerous initialization". + fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { + const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; + const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + // `transmute` is inside an anonymous module (the `extern` block?); + // `Invalid` represents the empty string and matches that. + const TRANSMUTE_PATH: &[Symbol] = + &[sym::core, sym::intrinsics, kw::Invalid, sym::transmute]; + + if let hir::ExprKind::Call(ref path_expr, ref args) = expr.node { + if let hir::ExprKind::Path(ref qpath) = path_expr.node { + let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + + if cx.match_def_path(def_id, ZEROED_PATH) { + return Some(InitKind::Zeroed); + } + if cx.match_def_path(def_id, UININIT_PATH) { + return Some(InitKind::Uninit); + } + if cx.match_def_path(def_id, TRANSMUTE_PATH) { + if is_zero(&args[0]) { + return Some(InitKind::Zeroed); + } + } + // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and + // `MaybeUninit::uninit().assume_init()`. + } + } + + None + } + /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. - fn ty_find_init_error<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + fn ty_find_init_error<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + init: InitKind, + ) -> Option { use rustc::ty::TyKind::*; match ty.sty { // Primitive types that don't like 0 as a value. @@ -1893,8 +1960,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), - // Recurse for some compound types. + // Primitive types with other constraints. + Bool if init == InitKind::Uninit => + Some((format!("Booleans must be `true` or `false`"), None)), + Char if init == InitKind::Uninit => + Some((format!("Characters must be a valid unicode codepoint"), None)), + // Recurse and checks for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { + // First check f this ADT has a layout attribute (like `NonNull` and friends). + use std::ops::Bound; + match tcx.layout_scalar_valid_range(adt_def.did) { + // We exploit here that `layout_scalar_valid_range` will never + // return `Bound::Excluded`. (And we have tests checking that we + // handle the attribute correctly.) + (Bound::Included(lo), _) if lo > 0 => + return Some((format!("{} must be non-null", ty), None)), + (Bound::Included(_), _) | (_, Bound::Included(_)) + if init == InitKind::Uninit => + return Some(( + format!("{} must be initialized inside its custom valid range", ty), + None, + )), + _ => {} + } + // Now, recurse. match adt_def.variants.len() { 0 => Some((format!("0-variant enums have no valid value"), None)), 1 => { @@ -1905,6 +1994,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { ty_find_init_error( tcx, field.ty(tcx, substs), + init, ).map(|(mut msg, span)| if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. @@ -1918,57 +2008,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { }) }) } + // Multi-variant enums are tricky: if all but one variant are + // uninhabited, we might actually do layout like for a single-variant + // enum, and then even leaving them uninitialized could be okay. _ => None, // Conservative fallback for multi-variant enum. } } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field)) + ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } - // FIXME: Would be nice to also warn for `NonNull`/`NonZero*`. - // FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`, - // `char`, and any multivariant enum. // Conservative fallback. _ => None, } } - if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node { - if let hir::ExprKind::Path(ref qpath) = path_expr.node { - if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if cx.match_def_path(def_id, &ZEROED_PATH) || - cx.match_def_path(def_id, &UININIT_PATH) - { - // This conjures an instance of a type out of nothing, - // using zeroed or uninitialized memory. - // We are extremely conservative with what we warn about. - let conjured_ty = cx.tables.expr_ty(expr); - if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { - let mut err = cx.struct_span_lint( - INVALID_VALUE, - expr.span, - &format!( - "the type `{}` does not permit {}", - conjured_ty, - if cx.match_def_path(def_id, &ZEROED_PATH) { - "zero-initialization" - } else { - "being left uninitialized" - } - ), - ); - err.span_label(expr.span, - "this code causes undefined behavior when executed"); - err.span_label(expr.span, "help: use `MaybeUninit` instead"); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - } - } + if let Some(init) = is_dangerous_init(cx, expr) { + // This conjures an instance of a type out of nothing, + // using zeroed or uninitialized memory. + // We are extremely conservative with what we warn about. + let conjured_ty = cx.tables.expr_ty(expr); + if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { + let mut err = cx.struct_span_lint( + INVALID_VALUE, + expr.span, + &format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + ), + ); + err.span_label(expr.span, + "this code causes undefined behavior when executed"); + err.span_label(expr.span, "help: use `MaybeUninit` instead"); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); } + err.emit(); } } } diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs index d7c39b780b..ea2e1d9ecc 100644 --- a/src/librustc_lint/error_codes.rs +++ b/src/librustc_lint/error_codes.rs @@ -1,5 +1,4 @@ -use syntax::register_diagnostics; - -register_diagnostics! { +syntax::register_diagnostics! { +; E0721, // `await` keyword } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 5648f9d0fd..0e054013cd 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -3,7 +3,7 @@ //! This currently only contains the definitions and implementations //! of most of the lints that `rustc` supports directly, it does not //! contain the infrastructure for defining/registering lints. That is -//! available in `rustc::lint` and `rustc_plugin` respectively. +//! available in `rustc::lint` and `rustc_driver::plugin` respectively. //! //! ## Note //! @@ -15,7 +15,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] @@ -24,6 +23,7 @@ extern crate rustc; mod error_codes; mod nonstandard_style; +mod redundant_semicolon; pub mod builtin; mod types; mod unused; @@ -55,6 +55,7 @@ use session::Session; use lint::LintId; use lint::FutureIncompatibleInfo; +use redundant_semicolon::*; use nonstandard_style::*; use builtin::*; use types::*; @@ -98,6 +99,7 @@ macro_rules! early_lint_passes { WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, + RedundantSemicolon: RedundantSemicolon, ]); ) } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 8f7fe6680c..bb6119d0ff 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -146,8 +146,8 @@ impl EarlyLintPass for NonCamelCaseTypes { } } - fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant, _: &ast::Generics) { - self.check_case(cx, "variant", &v.node.ident); + fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) { + self.check_case(cx, "variant", &v.ident); } fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) { @@ -350,9 +350,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { &mut self, cx: &LateContext<'_, '_>, s: &hir::VariantData, - _: ast::Name, - _: &hir::Generics, - _: hir::HirId, ) { for sf in s.fields() { self.check_snake_case(cx, "structure field", &sf.ident); diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs new file mode 100644 index 0000000000..7c9df3578b --- /dev/null +++ b/src/librustc_lint/redundant_semicolon.rs @@ -0,0 +1,52 @@ +use crate::lint::{EarlyLintPass, LintPass, EarlyContext, LintArray, LintContext}; +use syntax::ast::{Stmt, StmtKind, ExprKind}; +use syntax::errors::Applicability; + +declare_lint! { + pub REDUNDANT_SEMICOLON, + Warn, + "detects unnecessary trailing semicolons" +} + +declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]); + +impl EarlyLintPass for RedundantSemicolon { + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { + if let StmtKind::Semi(expr) = &stmt.node { + if let ExprKind::Tup(ref v) = &expr.node { + if v.is_empty() { + // Strings of excess semicolons are encoded as empty tuple expressions + // during the parsing stage, so we check for empty tuple expressions + // which span only semicolons + if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) { + if source_str.chars().all(|c| c == ';') { + let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1; + let msg = if multiple { + "unnecessary trailing semicolons" + } else { + "unnecessary trailing semicolon" + }; + let mut err = cx.struct_span_lint( + REDUNDANT_SEMICOLON, + stmt.span, + &msg + ); + let suggest_msg = if multiple { + "remove these semicolons" + } else { + "remove this semicolon" + }; + err.span_suggestion( + stmt.span, + &suggest_msg, + String::new(), + Applicability::MaybeIncorrect + ); + err.emit(); + } + } + } + } + } + } +} diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e86230437f..40261f6d13 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -624,7 +624,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { AdtKind::Struct => { if !def.repr.c() && !def.repr.transparent() { return FfiUnsafe { - ty: ty, + ty, reason: "this struct has unspecified layout", help: Some("consider adding a `#[repr(C)]` or \ `#[repr(transparent)]` attribute to this struct"), @@ -633,7 +633,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if def.non_enum_variant().fields.is_empty() { return FfiUnsafe { - ty: ty, + ty, reason: "this struct has no fields", help: Some("consider adding a member to this struct"), }; @@ -669,7 +669,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { AdtKind::Union => { if !def.repr.c() && !def.repr.transparent() { return FfiUnsafe { - ty: ty, + ty, reason: "this union has unspecified layout", help: Some("consider adding a `#[repr(C)]` or \ `#[repr(transparent)]` attribute to this union"), @@ -678,7 +678,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if def.non_enum_variant().fields.is_empty() { return FfiUnsafe { - ty: ty, + ty, reason: "this union has no fields", help: Some("consider adding a field to this union"), }; @@ -721,7 +721,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Special-case types like `Option`. if !is_repr_nullable_ptr(cx, ty, def, substs) { return FfiUnsafe { - ty: ty, + ty, reason: "enum has no representation hint", help: Some("consider adding a `#[repr(C)]`, \ `#[repr(transparent)]`, or integer `#[repr(...)]` \ @@ -750,7 +750,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } FfiPhantom(..) => { return FfiUnsafe { - ty: ty, + ty, reason: "this enum contains a PhantomData field", help: None, }; @@ -764,13 +764,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } ty::Char => FfiUnsafe { - ty: ty, + ty, reason: "the `char` type has no C equivalent", help: Some("consider using `u32` or `libc::wchar_t` instead"), }, ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe { - ty: ty, + ty, reason: "128-bit integers don't currently have a known stable ABI", help: None, }, @@ -779,25 +779,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe, ty::Slice(_) => FfiUnsafe { - ty: ty, + ty, reason: "slices have no C equivalent", help: Some("consider using a raw pointer instead"), }, ty::Dynamic(..) => FfiUnsafe { - ty: ty, + ty, reason: "trait objects have no C equivalent", help: None, }, ty::Str => FfiUnsafe { - ty: ty, + ty, reason: "string slices have no C equivalent", help: Some("consider using `*const u8` and a length instead"), }, ty::Tuple(..) => FfiUnsafe { - ty: ty, + ty, reason: "tuples have unspecified layout", help: Some("consider using a struct instead"), }, @@ -811,7 +811,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match sig.abi() { Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { return FfiUnsafe { - ty: ty, + ty, reason: "this function pointer has Rust-specific calling convention", help: Some("consider using an `extern fn(...) -> ...` \ function pointer instead"), @@ -855,11 +855,76 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | - ty::FnDef(..) => bug!("Unexpected type in foreign function"), + ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty), + } + } + + fn emit_ffi_unsafe_type_lint( + &mut self, + ty: Ty<'tcx>, + sp: Span, + note: &str, + help: Option<&str>, + ) { + let mut diag = self.cx.struct_span_lint( + IMPROPER_CTYPES, + sp, + &format!("`extern` block uses type `{}`, which is not FFI-safe", ty), + ); + diag.span_label(sp, "not FFI-safe"); + if let Some(help) = help { + diag.help(help); + } + diag.note(note); + if let ty::Adt(def, _) = ty.sty { + if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { + diag.span_note(sp, "type defined here"); + } + } + diag.emit(); + } + + fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { + use crate::rustc::ty::TypeFoldable; + + struct ProhibitOpaqueTypes<'tcx> { + ty: Option>, + }; + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + if let ty::Opaque(..) = ty.sty { + self.ty = Some(ty); + true + } else { + ty.super_visit_with(self) + } + } + } + + let mut visitor = ProhibitOpaqueTypes { ty: None }; + ty.visit_with(&mut visitor); + if let Some(ty) = visitor.ty { + self.emit_ffi_unsafe_type_lint( + ty, + sp, + "opaque types have no C equivalent", + None, + ); + true + } else { + false } } fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { + // We have to check for opaque types before `normalize_erasing_regions`, + // which will replace opaque types with their underlying concrete type. + if self.check_for_opaque_ty(sp, ty) { + // We've already emitted an error due to an opaque type. + return; + } + // it is only OK to use this function because extern fns cannot have // any generic types right now: let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); @@ -867,24 +932,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { - self.cx.span_lint(IMPROPER_CTYPES, - sp, - &format!("`extern` block uses type `{}` which is not FFI-safe: \ - composed only of PhantomData", ty)); + self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None); } - FfiResult::FfiUnsafe { ty: unsafe_ty, reason, help } => { - let msg = format!("`extern` block uses type `{}` which is not FFI-safe: {}", - unsafe_ty, reason); - let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg); - if let Some(s) = help { - diag.help(s); - } - if let ty::Adt(def, _) = unsafe_ty.sty { - if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { - diag.span_note(sp, "type defined here"); - } - } - diag.emit(); + FfiResult::FfiUnsafe { ty, reason, help } => { + self.emit_ffi_unsafe_type_lint(ty, sp, reason, help); } } } @@ -924,7 +975,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) { let mut vis = ImproperCTypesVisitor { cx }; let abi = cx.tcx.hir().get_foreign_abi(it.hir_id); - if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic { + if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi { + // Don't worry about types in internal ABIs. + } else { match it.node { hir::ForeignItemKind::Fn(ref decl, _, _) => { vis.check_foreign_fn(it.hir_id, decl); @@ -976,7 +1029,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let bytes = variant_layout.size.bytes().saturating_sub(discr_size); debug!("- variant `{}` is {} bytes large", - variant.node.ident, + variant.ident, bytes); bytes }) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 6a3dfdbe31..2d4af2f606 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -9,7 +9,7 @@ use lint::{LintPass, EarlyLintPass, LateLintPass}; use syntax::ast; use syntax::attr; -use syntax::errors::Applicability; +use syntax::errors::{Applicability, pluralise}; use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use syntax::print::pprust; use syntax::symbol::{kw, sym}; @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } let ty = cx.tables.expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false); + let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); let mut fn_warned = false; let mut op_warned = false; @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { span: Span, descr_pre: &str, descr_post: &str, - plural: bool, + plural_len: usize, ) -> bool { if ty.is_unit() || cx.tcx.is_ty_uninhabited_from( cx.tcx.hir().get_module_parent(expr.hir_id), ty) @@ -143,13 +143,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { return true; } - let plural_suffix = if plural { "s" } else { "" }; + let plural_suffix = pluralise!(plural_len); match ty.sty { ty::Adt(..) if ty.is_box() => { let boxed_ty = ty.boxed_ty(); let descr_pre = &format!("{}boxed ", descr_pre); - check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural) + check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len) } ty::Adt(def, _) => { check_must_use_def(cx, def.did, span, descr_pre, descr_post) @@ -202,7 +202,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = *spans.get(i).unwrap_or(&span); - if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) { + if check_must_use_ty( + cx, + ty, + expr, + span, + descr_pre, + descr_post, + plural_len + ) { has_emitted = true; } } @@ -216,7 +224,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_pre, plural_suffix, ); - check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true) + check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1) } // Otherwise, we don't lint, to avoid false positives. _ => false, @@ -370,7 +378,8 @@ impl UnusedParens { right_pos: Option) { match value.node { ast::ExprKind::Paren(ref inner) => { - if !Self::is_expr_parens_necessary(inner, followed_by_block) { + if !Self::is_expr_parens_necessary(inner, followed_by_block) && + value.attrs.is_empty() { let expr_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet @@ -398,18 +407,37 @@ impl UnusedParens { } } - fn check_unused_parens_pat(&self, - cx: &EarlyContext<'_>, - value: &ast::Pat, - msg: &str) { - if let ast::PatKind::Paren(_) = value.node { + fn check_unused_parens_pat( + &self, + cx: &EarlyContext<'_>, + value: &ast::Pat, + avoid_or: bool, + avoid_mut: bool, + ) { + use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable}; + + if let PatKind::Paren(inner) = &value.node { + match inner.node { + // The lint visitor will visit each subpattern of `p`. We do not want to lint + // any range pattern no matter where it occurs in the pattern. For something like + // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume + // that if there are unnecessary parens they serve a purpose of readability. + PatKind::Range(..) => return, + // Avoid `p0 | .. | pn` if we should. + PatKind::Or(..) if avoid_or => return, + // Avoid `mut x` and `mut x @ p` if we should: + PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return, + // Otherwise proceed with linting. + _ => {} + } + let pattern_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet } else { pprust::pat_to_string(value) }; - Self::remove_outer_parens(cx, value.span, &pattern_text, msg, (false, false)); + Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false)); } } @@ -474,6 +502,11 @@ impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { use syntax::ast::ExprKind::*; let (value, msg, followed_by_block, left_pos, right_pos) = match e.node { + Let(ref pat, ..) => { + self.check_unused_parens_pat(cx, pat, false, false); + return; + } + If(ref cond, ref block, ..) => { let left = e.span.lo() + syntax_pos::BytePos(2); let right = block.span.lo(); @@ -486,7 +519,8 @@ impl EarlyLintPass for UnusedParens { (cond, "`while` condition", true, Some(left), Some(right)) }, - ForLoop(_, ref cond, ref block, ..) => { + ForLoop(ref pat, ref cond, ref block, ..) => { + self.check_unused_parens_pat(cx, pat, false, false); (cond, "`for` head expression", true, None, Some(block.span.lo())) } @@ -517,9 +551,8 @@ impl EarlyLintPass for UnusedParens { // trigger in situations that macro authors shouldn't have to care about, e.g., // when a parenthesized token tree matched in one macro expansion is matched as // an expression in another and used as a fn/method argument (Issue #47775) - if e.span.ctxt().outer_expn_info() - .map_or(false, |info| info.call_site.ctxt().outer_expn_info().is_some()) { - return; + if e.span.ctxt().outer_expn_data().call_site.from_expansion() { + return; } let msg = format!("{} argument", call_kind); for arg in args_to_check { @@ -532,26 +565,44 @@ impl EarlyLintPass for UnusedParens { } fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { - use ast::PatKind::{Paren, Range}; - // The lint visitor will visit each subpattern of `p`. We do not want to lint any range - // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there - // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessary parens they serve a purpose of readability. - if let Paren(ref pat) = p.node { - match pat.node { - Range(..) => {} - _ => self.check_unused_parens_pat(cx, &p, "pattern") - } + use ast::{PatKind::*, Mutability}; + match &p.node { + // Do not lint on `(..)` as that will result in the other arms being useless. + Paren(_) + // The other cases do not contain sub-patterns. + | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return, + // These are list-like patterns; parens can always be removed. + TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { + self.check_unused_parens_pat(cx, p, false, false); + }, + Struct(_, fps, _) => for f in fps { + self.check_unused_parens_pat(cx, &f.pat, false, false); + }, + // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. + Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false), + // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. + // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. + Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable), } } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let ast::StmtKind::Local(ref local) = s.node { + self.check_unused_parens_pat(cx, &local.pat, false, false); + if let Some(ref value) = local.init { self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None); } } } + + fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) { + self.check_unused_parens_pat(cx, ¶m.pat, true, false); + } + + fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { + self.check_unused_parens_pat(cx, &arm.pat, false, false); + } } declare_lint! { @@ -576,24 +627,19 @@ impl UnusedImportBraces { } // Trigger the lint if the nested item is a non-self single item - let node_ident; - match items[0].0.kind { + let node_name = match items[0].0.kind { ast::UseTreeKind::Simple(rename, ..) => { let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; if orig_ident.name == kw::SelfLower { return; } - node_ident = rename.unwrap_or(orig_ident); + rename.unwrap_or(orig_ident).name } - ast::UseTreeKind::Glob => { - node_ident = ast::Ident::from_str("*"); - } - ast::UseTreeKind::Nested(_) => { - return; - } - } + ast::UseTreeKind::Glob => Symbol::intern("*"), + ast::UseTreeKind::Nested(_) => return, + }; - let msg = format!("braces around {} is unnecessary", node_ident.name); + let msg = format!("braces around {} is unnecessary", node_name); cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg); } } diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 16cdbb7dd4..62a3757757 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -54,7 +54,7 @@ fn main() { // LLVM are compiled the same way, but for us that's typically the case. // // We *want* detect this cross compiling situation by asking llvm-config - // what it's host-target is. If that's not the TARGET, then we're cross + // what its host-target is. If that's not the TARGET, then we're cross // compiling. Unfortunately `llvm-config` seems either be buggy, or we're // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This @@ -62,7 +62,7 @@ fn main() { // havoc ensues. // // In any case, if we're cross compiling, this generally just means that we - // can't trust all the output of llvm-config becaues it might be targeted + // can't trust all the output of llvm-config because it might be targeted // for the host rather than the target. As a result a bunch of blocks below // are gated on `if !is_crossed` let target = env::var("TARGET").expect("TARGET was not set"); @@ -151,6 +151,10 @@ fn main() { cfg.define("LLVM_RUSTLLVM", None); } + if env::var_os("LLVM_NDEBUG").is_some() { + cfg.define("NDEBUG", None); + } + build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm")); cfg.file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") @@ -162,7 +166,7 @@ fn main() { let (llvm_kind, llvm_link_arg) = detect_llvm_link(); - // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then + // Link in all LLVM libraries, if we're using the "wrong" llvm-config then // we don't pick up system libs because unfortunately they're for the host // of llvm-config, not the target that we're attempting to link. let mut cmd = Command::new(&llvm_config); @@ -250,8 +254,11 @@ fn main() { let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX"); let stdcppname = if target.contains("openbsd") { - // llvm-config on OpenBSD doesn't mention stdlib=libc++ - "c++" + if target.contains("sparc64") { + "estdc++" + } else { + "c++" + } } else if target.contains("freebsd") { "c++" } else if target.contains("darwin") { diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index b8c7b7c2d5..73720d8c2d 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -4,6 +4,10 @@ use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { + println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); + if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { + return; + } if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { build_helper::restore_library_path(); diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index 85e2247ebd..3d3a020ef0 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -1,5 +1,5 @@ #![feature(proc_macro_hygiene)] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #![recursion_limit="128"] diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index d5f1e71518..af41b6a4c8 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -2,8 +2,7 @@ use crate::cstore::{self, CStore, CrateSource, MetadataBlob}; use crate::locator::{self, CratePaths}; -use crate::decoder::proc_macro_def_path_table; -use crate::schema::CrateRoot; +use crate::schema::{CrateRoot}; use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use rustc::hir::def_id::CrateNum; @@ -26,11 +25,11 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; use syntax::ext::allocator::{global_allocator_spans, AllocatorKind}; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::symbol::{Symbol, sym}; use syntax::{span_err, span_fatal}; use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; +use proc_macro::bridge::client::ProcMacro; pub struct Library { pub dylib: Option<(PathBuf, PathKind)>, @@ -230,24 +229,13 @@ impl<'a> CrateLoader<'a> { let dependencies: Vec = cnum_map.iter().cloned().collect(); - let proc_macros = crate_root.proc_macro_decls_static.map(|_| { + let raw_proc_macros = crate_root.proc_macro_data.map(|_| { if self.sess.opts.debugging_opts.dual_proc_macros { - let host_lib = host_lib.unwrap(); - self.load_derive_macros( - &host_lib.metadata.get_root(), - host_lib.dylib.map(|p| p.0), - span - ) + let host_lib = host_lib.as_ref().unwrap(); + self.dlsym_proc_macros(host_lib.dylib.as_ref().map(|p| p.0.clone()), + &host_lib.metadata.get_root(), span) } else { - self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) - } - }); - - let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { - if let Some(proc_macros) = &proc_macros { - proc_macro_def_path_table(&crate_root, proc_macros) - } else { - crate_root.def_path_table.decode((&metadata, self.sess)) + self.dlsym_proc_macros(dylib.clone().map(|p| p.0), &crate_root, span) } }); @@ -260,13 +248,16 @@ impl<'a> CrateLoader<'a> { .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) .collect(); + let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { + crate_root.def_path_table.decode((&metadata, self.sess)) + }); + let cmeta = cstore::CrateMetadata { name: crate_root.name, imported_name: ident, extern_crate: Lock::new(None), def_path_table: Lrc::new(def_path_table), trait_impls, - proc_macros, root: crate_root, blob: metadata, cnum_map, @@ -280,7 +271,10 @@ impl<'a> CrateLoader<'a> { rlib, rmeta, }, - private_dep + private_dep, + span, + host_lib, + raw_proc_macros }; let cmeta = Lrc::new(cmeta); @@ -389,7 +383,7 @@ impl<'a> CrateLoader<'a> { match result { (LoadResult::Previous(cnum), None) => { let data = self.cstore.get_crate_data(cnum); - if data.root.proc_macro_decls_static.is_some() { + if data.root.proc_macro_data.is_some() { dep_kind = DepKind::UnexportedMacrosOnly; } data.dep_kind.with_lock(|data_dep_kind| { @@ -482,7 +476,7 @@ impl<'a> CrateLoader<'a> { dep_kind: DepKind) -> cstore::CrateNumMap { debug!("resolving deps of external crate"); - if crate_root.proc_macro_decls_static.is_some() { + if crate_root.proc_macro_data.is_some() { return cstore::CrateNumMap::new(); } @@ -574,19 +568,13 @@ impl<'a> CrateLoader<'a> { } } - /// Loads custom derive macros. - /// - /// Note that this is intentionally similar to how we load plugins today, - /// but also intentionally separate. Plugins are likely always going to be - /// implemented as dynamic libraries, but we have a possible future where - /// custom derive (and other macro-1.1 style features) are implemented via - /// executables and custom IPC. - fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option, span: Span) - -> Vec<(ast::Name, Lrc)> { - use std::{env, mem}; + fn dlsym_proc_macros(&self, + dylib: Option, + root: &CrateRoot<'_>, + span: Span + ) -> &'static [ProcMacro] { + use std::env; use crate::dynamic_lib::DynamicLibrary; - use proc_macro::bridge::client::ProcMacro; - use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive}; let path = match dylib { Some(dylib) => dylib, @@ -608,38 +596,11 @@ impl<'a> CrateLoader<'a> { *(sym as *const &[ProcMacro]) }; - let extensions = decls.iter().map(|&decl| { - let (name, kind, helper_attrs) = match decl { - ProcMacro::CustomDerive { trait_name, attributes, client } => { - let helper_attrs = - attributes.iter().cloned().map(Symbol::intern).collect::>(); - ( - trait_name, - SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { - client, attrs: helper_attrs.clone() - })), - helper_attrs, - ) - } - ProcMacro::Attr { name, client } => ( - name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() - ), - ProcMacro::Bang { name, client } => ( - name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() - ) - }; - - (Symbol::intern(name), Lrc::new(SyntaxExtension { - helper_attrs, - ..SyntaxExtension::default(kind, root.edition) - })) - }).collect(); - // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. - mem::forget(lib); + std::mem::forget(lib); - extensions + decls } /// Look for a plugin registrar. Returns library path, crate diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 5d8fabc7e6..5bf4067431 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -28,6 +28,9 @@ pub use crate::cstore_impl::{provide, provide_extern}; pub type CrateNumMap = IndexVec; pub use rustc_data_structures::sync::MetadataRef; +use crate::creader::Library; +use syntax_pos::Span; +use proc_macro::bridge::client::ProcMacro; pub struct MetadataBlob(pub MetadataRef); @@ -65,28 +68,31 @@ pub struct CrateMetadata { pub alloc_decoding_state: AllocDecodingState, // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this - // lifetime is only used behind `Lazy` / `LazySeq`, and therefore - // acts like an universal (`for<'tcx>`), that is paired up with - // whichever `TyCtxt` is being used to decode those values. + // lifetime is only used behind `Lazy`, and therefore acts like an + // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` + // is being used to decode those values. pub root: schema::CrateRoot<'static>, - /// For each public item in this crate, we encode a key. When the + /// For each definition in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. pub def_path_table: Lrc, - pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq>, + pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, pub dep_kind: Lock, pub source: CrateSource, - pub proc_macros: Option)>>, - /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint - pub private_dep: bool + pub private_dep: bool, + + pub host_lib: Option, + pub span: Span, + + pub raw_proc_macros: Option<&'static [ProcMacro]>, } pub struct CStore { @@ -98,7 +104,7 @@ pub struct CStore { pub enum LoadedMacro { MacroDef(ast::Item), - ProcMacro(Lrc), + ProcMacro(SyntaxExtension), } impl CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ee1175e798..55cf3965aa 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -30,12 +30,10 @@ use syntax::ast; use syntax::attr; use syntax::source_map; use syntax::edition::Edition; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use syntax::ext::proc_macro::BangProcMacro; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; -use syntax::symbol::{Symbol, sym}; -use syntax_pos::{Span, NO_EXPANSION, FileName}; +use syntax::symbol::Symbol; +use syntax_pos::{Span, FileName}; use rustc_data_structures::bit_set::BitSet; macro_rules! provide { @@ -127,21 +125,15 @@ provide! { <'tcx> tcx, def_id, other, cdata, bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); }) } - optimized_mir => { - let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) - }); - - let mir = tcx.arena.alloc(mir); - - mir - } + optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } + promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } + asyncness => { cdata.asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } @@ -157,7 +149,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, // a `fn` when encoding, so the dep-tracking wouldn't work. // This is only used by rustdoc anyway, which shouldn't have // incremental recompilation ever enabled. - fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } + fn_arg_names => { cdata.get_fn_param_names(def_id.index) } rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } trait_of_item => { cdata.get_trait_of_item(def_id.index) } @@ -235,6 +227,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } defined_lib_features => { cdata.get_lib_features(tcx) } defined_lang_items => { cdata.get_lang_items(tcx) } + diagnostic_items => { cdata.get_diagnostic_items(tcx) } missing_lang_items => { cdata.get_missing_lang_items(tcx) } missing_extern_crate_item => { @@ -426,24 +419,17 @@ impl cstore::CStore { pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); - if let Some(ref proc_macros) = data.proc_macros { - return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); - } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { - let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })); - let ext = SyntaxExtension { - allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()), - ..SyntaxExtension::default(kind, data.root.edition) - }; - return LoadedMacro::ProcMacro(Lrc::new(ext)); + if data.is_proc_macro_crate() { + return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); } let def = data.get_macro(id.index); - let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name); + let macro_full_name = data.def_path(id.index) + .to_string_friendly(|_| data.imported_name); let source_name = FileName::Macros(macro_full_name); let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body); - let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION); + let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos); let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None); emit_unclosed_delims(&mut errors, &sess.diagnostic()); @@ -459,7 +445,8 @@ impl cstore::CStore { .insert(local_span, (name.to_string(), data.get_span(id.index, sess))); LoadedMacro::MacroDef(ast::Item { - ident: ast::Ident::from_str(&name.as_str()), + // FIXME: cross-crate hygiene + ident: ast::Ident::with_dummy_span(name.as_symbol()), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 935187dd06..247748eb3e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -3,22 +3,23 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; +use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::mir::interpret::AllocDecodingSession; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::mir::Body; +use rustc::mir::{Body, Promoted}; use rustc::util::captures::Captures; use std::io; @@ -30,10 +31,11 @@ use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; use syntax::symbol::{Symbol, sym}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; -use syntax::ext::hygiene::ExpnId; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; +use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; +use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}}; use log::debug; +use proc_macro::bridge::client::ProcMacro; +use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; pub struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, @@ -134,14 +136,14 @@ impl<'a, 'tcx, T: Decodable> Lazy { } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> LazySeq { +impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { pub fn decode>( self, meta: M, - ) -> impl Iterator + Captures<'a> + Captures<'tcx> + 'x { + ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); - (0..self.len).map(move |_| T::decode(&mut dcx).unwrap()) + (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } } @@ -154,10 +156,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.cdata.expect("missing CrateMetadata in DecodeContext") } - fn read_lazy_distance(&mut self, min_size: usize) -> Result::Error> { + fn read_lazy_with_meta( + &mut self, + meta: T::Meta, + ) -> Result, ::Error> { + let min_size = T::min_size(meta); let distance = self.read_usize()?; let position = match self.lazy_state { - LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"), + LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { assert!(distance + min_size <= start); start - distance - min_size @@ -165,7 +171,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { LazyState::Previous(last_min_end) => last_min_end + distance, }; self.lazy_state = LazyState::Previous(position + min_size); - Ok(position) + Ok(Lazy::from_position_and_meta(position, meta)) } } @@ -230,19 +236,18 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(Lazy::with_position(self.read_lazy_distance(Lazy::::min_size())?)) + self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result, Self::Error> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; - let position = if len == 0 { - 0 + if len == 0 { + Ok(Lazy::empty()) } else { - self.read_lazy_distance(LazySeq::::min_size(len))? - }; - Ok(LazySeq::with_position_and_length(position, len)) + self.read_lazy_with_meta(len) + } } } @@ -344,7 +349,15 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { let hi = (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::with_root_ctxt(lo, hi)) + } +} + +impl SpecializedDecoder for DecodeContext<'_, '_> { + fn specialized_decode(&mut self) -> Result { + // FIXME(jseyfried): intercrate hygiene + + Ok(Ident::with_dummy_span(Symbol::decode(self)?)) } } @@ -370,7 +383,7 @@ impl<'tcx> MetadataBlob { } pub fn get_rustc_version(&self) -> String { - Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) } pub fn get_root(&self) -> CrateRoot<'tcx> { @@ -379,7 +392,7 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::with_position(pos).decode(self) + Lazy::>::from_position(pos).decode(self) } pub fn list_crate_metadata(&self, @@ -434,46 +447,24 @@ impl<'tcx> EntryKind<'tcx> { } } -/// Creates the "fake" DefPathTable for a given proc macro crate. -/// -/// The DefPathTable is as follows: -/// -/// CRATE_ROOT (DefIndex 0:0) -/// |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N) -/// |- proc macro #0 (DefIndex 1:N) -/// |- proc macro #1 (DefIndex 1:N+1) -/// \- ... -crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>, - proc_macros: &[(ast::Name, Lrc)]) - -> DefPathTable -{ - let mut definitions = Definitions::default(); - - let name = crate_root.name.as_str(); - let disambiguator = crate_root.disambiguator; - debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator); - let crate_root = definitions.create_root_def(&name, disambiguator); - for (index, (name, _)) in proc_macros.iter().enumerate() { - let def_index = definitions.create_def_with_parent( - crate_root, - ast::DUMMY_NODE_ID, - DefPathData::MacroNs(name.as_interned_str()), - ExpnId::root(), - DUMMY_SP); - debug!("definition for {:?} is {:?}", name, def_index); - assert_eq!(def_index, DefIndex::from_proc_macro_index(index)); - } - - definitions.def_path_table().clone() -} - impl<'a, 'tcx> CrateMetadata { + pub fn is_proc_macro_crate(&self) -> bool { + self.root.proc_macro_decls_static.is_some() + } + fn is_proc_macro(&self, id: DefIndex) -> bool { - self.proc_macros.is_some() && id != CRATE_DEF_INDEX + self.is_proc_macro_crate() && + self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() + } + + fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { + match self.is_proc_macro(id) { + true => None, + false => Some(self.entry(id)), + } } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - assert!(!self.is_proc_macro(item_id)); self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } @@ -496,13 +487,28 @@ impl<'a, 'tcx> CrateMetadata { } } + fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { + // DefIndex's in root.proc_macro_data have a one-to-one correspondence + // with items in 'raw_proc_macros'. + // NOTE: If you update the order of macros in 'proc_macro_data' for any reason, + // you must also update src/libsyntax_ext/proc_macro_harness.rs + // Failing to do so will result in incorrect data being associated + // with proc macros when deserialized. + let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap(); + &self.raw_proc_macros.unwrap()[pos] + } + pub fn item_name(&self, item_index: DefIndex) -> Symbol { - self.def_key(item_index) - .disambiguated_data - .data - .get_opt_name() - .expect("no name in item_name") - .as_symbol() + if !self.is_proc_macro(item_index) { + self.def_key(item_index) + .disambiguated_data + .data + .get_opt_name() + .expect("no name in item_name") + .as_symbol() + } else { + Symbol::intern(self.raw_proc_macro(item_index).name()) + } } pub fn def_kind(&self, index: DefIndex) -> Option { @@ -510,16 +516,48 @@ impl<'a, 'tcx> CrateMetadata { self.entry(index).kind.def_kind() } else { Some(DefKind::Macro( - self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind() + macro_kind(self.raw_proc_macro(index)) )) } } pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { - match self.is_proc_macro(index) { - true => DUMMY_SP, - false => self.entry(index).span.decode((self, sess)), - } + self.entry(index).span.decode((self, sess)) + } + + crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { + let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { + ProcMacro::CustomDerive { trait_name, attributes, client } => { + let helper_attrs = + attributes.iter().cloned().map(Symbol::intern).collect::>(); + ( + trait_name, + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })), + helper_attrs, + ) + } + ProcMacro::Attr { name, client } => ( + name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() + ), + ProcMacro::Bang { name, client } => ( + name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() + ) + }; + let edition = if sess.opts.debugging_opts.dual_proc_macros { + self.host_lib.as_ref().unwrap().metadata.get_root().edition + } else { + self.root.edition + }; + + SyntaxExtension::new( + &sess.parse_sess, + kind, + self.get_span(id, sess), + helper_attrs, + edition, + Symbol::intern(name), + &self.get_attributes(&self.entry(id), sess), + ) } pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { @@ -569,7 +607,7 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef::new( tcx, - Ident::with_empty_ctxt(self.item_name(index)), + Ident::with_dummy_span(self.item_name(index)), variant_did, ctor_did, data.discr, @@ -577,7 +615,7 @@ impl<'a, 'tcx> CrateMetadata { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - ident: Ident::with_empty_ctxt(self.item_name(index)), + ident: Ident::with_dummy_span(self.item_name(index)), vis: f.visibility.decode(self) } }).collect(), @@ -662,10 +700,8 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_deprecation(&self, id: DefIndex) -> Option { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).deprecation.map(|depr| depr.decode(self)), - } + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) } pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { @@ -715,7 +751,7 @@ impl<'a, 'tcx> CrateMetadata { /// Iterates over the language items in the given crate. pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not export any lang-items to the target. &[] } else { @@ -726,22 +762,39 @@ impl<'a, 'tcx> CrateMetadata { } } + /// Iterates over the diagnostic items in the given crate. + pub fn get_diagnostic_items( + &self, + tcx: TyCtxt<'tcx>, + ) -> &'tcx FxHashMap { + tcx.arena.alloc(if self.is_proc_macro_crate() { + // Proc macro crates do not export any diagnostic-items to the target. + Default::default() + } else { + self.root + .diagnostic_items + .decode(self) + .map(|(name, def_index)| (name, self.local_def_id(def_index))) + .collect() + }) + } + /// Iterates over each child of the given item. pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { - if let Some(ref proc_macros) = self.proc_macros { + if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) { /* If we are loading as a proc macro, we want to return the view of this crate - * as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table` - * for the DefPathTable we are corresponding to. + * as a proc macro crate. */ if id == CRATE_DEF_INDEX { - for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { + for def_index in proc_macros_ids { + let raw_macro = self.raw_proc_macro(def_index); let res = Res::Def( - DefKind::Macro(ext.macro_kind()), - self.local_def_id(DefIndex::from_proc_macro_index(id)), + DefKind::Macro(macro_kind(raw_macro)), + self.local_def_id(def_index), ); - let ident = Ident::with_empty_ctxt(name); + let ident = Ident::from_str(raw_macro.name()); callback(def::Export { ident: ident, res: res, @@ -783,7 +836,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(kind) = self.def_kind(child_index) { callback(def::Export { res: Res::Def(kind, self.local_def_id(child_index)), - ident: Ident::with_empty_ctxt(self.item_name(child_index)), + ident: Ident::with_dummy_span(self.item_name(child_index)), vis: self.get_visibility(child_index), span: self.entry(child_index).span.decode((self, sess)), }); @@ -875,11 +928,24 @@ impl<'a, 'tcx> CrateMetadata { self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } - pub fn maybe_get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option> { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), - } + pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id)) + }) + } + + pub fn get_promoted_mir( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> IndexVec> { + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.promoted_mir.map(|promoted| promoted.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { @@ -952,11 +1018,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { - if self.is_proc_macro(node_id) { - return Lrc::new([]); - } + pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { // The attributes for a tuple struct/variant are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition @@ -1014,7 +1077,7 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, filter: Option, ) -> &'tcx [DefId] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // proc-macro crates export no trait impls. return &[] } @@ -1058,7 +1121,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_native_libraries(&self, sess: &Session) -> Vec { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* native libraries. vec![] } else { @@ -1067,7 +1130,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* foreign modules. &[] } else { @@ -1090,7 +1153,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not depend on any target weak lang-items. &[] } else { @@ -1100,21 +1163,21 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { - let arg_names = match self.entry(id).kind { + pub fn get_fn_param_names(&self, id: DefIndex) -> Vec { + let param_names = match self.entry(id).kind { EntryKind::Fn(data) | - EntryKind::ForeignFn(data) => data.decode(self).arg_names, - EntryKind::Method(data) => data.decode(self).fn_data.arg_names, - _ => LazySeq::empty(), + EntryKind::ForeignFn(data) => data.decode(self).param_names, + EntryKind::Method(data) => data.decode(self).fn_data.param_names, + _ => Lazy::empty(), }; - arg_names.decode(self).collect() + param_names.decode(self).collect() } pub fn exported_symbols( &self, tcx: TyCtxt<'tcx>, ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // If this crate is a custom derive crate, then we're not even going to // link those in so we skip those crates. vec![] @@ -1149,6 +1212,15 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } + pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync { + match self.entry(id).kind { + EntryKind::Fn(data) => data.decode(self).asyncness, + EntryKind::Method(data) => data.decode(self).fn_data.asyncness, + EntryKind::ForeignFn(data) => data.decode(self).asyncness, + _ => bug!("asyncness: expect functions entry."), + } + } + pub fn is_foreign_item(&self, id: DefIndex) -> bool { match self.entry(id).kind { EntryKind::ForeignImmStatic | @@ -1183,13 +1255,18 @@ impl<'a, 'tcx> CrateMetadata { #[inline] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.def_path_table.def_key(index) + let mut key = self.def_path_table.def_key(index); + if self.is_proc_macro(index) { + let name = self.raw_proc_macro(index).name(); + key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name)); + } + key } // Returns the path leading to the thing with this `id`. pub fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); - DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent)) + DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } #[inline] @@ -1302,3 +1379,13 @@ impl<'a, 'tcx> CrateMetadata { self.source_map_import_info.borrow() } } + +// Cannot be implemented on 'ProcMacro', as libproc_macro +// does not depend on libsyntax +fn macro_kind(raw: &ProcMacro) -> MacroKind { + match raw { + ProcMacro::CustomDerive { .. } => MacroKind::Derive, + ProcMacro::Attr { .. } => MacroKind::Attr, + ProcMacro::Bang { .. } => MacroKind::Bang + } +} diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d73a4966bc..1e7c0829a2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,6 +8,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, use rustc::hir::GenericParamKind; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::middle::dependency_format::Linkage; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, metadata_symbol_name}; @@ -30,8 +31,9 @@ use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; +use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::source_map::Spanned; -use syntax::symbol::{kw, sym}; +use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax_pos::{self, FileName, SourceFile, Span}; use log::{debug, trace}; @@ -97,17 +99,17 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { - self.emit_lazy_distance(lazy.position, Lazy::::min_size()) + self.emit_lazy_distance(*lazy) } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { - fn specialized_encode(&mut self, seq: &LazySeq) -> Result<(), Self::Error> { - self.emit_usize(seq.len)?; - if seq.len == 0 { +impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { + fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta)?; + if lazy.meta == 0 { return Ok(()); } - self.emit_lazy_distance(seq.position, LazySeq::::min_size(seq.len)) + self.emit_lazy_distance(*lazy) } } @@ -173,6 +175,13 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } +impl SpecializedEncoder for EncodeContext<'tcx> { + fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> { + // FIXME(jseyfried): intercrate hygiene + ident.name.encode(self) + } +} + impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> { @@ -231,21 +240,38 @@ impl<'tcx> TyEncoder for EncodeContext<'tcx> { } } -impl<'tcx> EncodeContext<'tcx> { - fn emit_node R, R>(&mut self, f: F) -> R { - assert_eq!(self.lazy_state, LazyState::NoNode); - let pos = self.position(); - self.lazy_state = LazyState::NodeStart(pos); - let r = f(self, pos); - self.lazy_state = LazyState::NoNode; - r +/// Helper trait to allow overloading `EncodeContext::lazy` for iterators. +trait EncodeContentsForLazy { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> T::Meta; +} + +impl EncodeContentsForLazy for &T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) { + self.encode(ecx).unwrap() } +} + +impl EncodeContentsForLazy for T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) { + self.encode(ecx).unwrap() + } +} - fn emit_lazy_distance(&mut self, - position: usize, - min_size: usize) - -> Result<(), ::Error> { - let min_end = position + min_size; +impl EncodeContentsForLazy<[T]> for I + where I: IntoIterator, + I::Item: EncodeContentsForLazy, +{ + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize { + self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count() + } +} + +impl<'tcx> EncodeContext<'tcx> { + fn emit_lazy_distance( + &mut self, + lazy: Lazy, + ) -> Result<(), ::Error> { + let min_end = lazy.position + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { @@ -254,48 +280,31 @@ impl<'tcx> EncodeContext<'tcx> { } LazyState::Previous(last_min_end) => { assert!( - last_min_end <= position, + last_min_end <= lazy.position, "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - position - last_min_end + lazy.position - last_min_end } }; self.lazy_state = LazyState::Previous(min_end); self.emit_usize(distance) } - pub fn lazy(&mut self, value: &T) -> Lazy { - self.emit_node(|ecx, pos| { - value.encode(ecx).unwrap(); - - assert!(pos + Lazy::::min_size() <= ecx.position()); - Lazy::with_position(pos) - }) - } - - pub fn lazy_seq(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + fn lazy( + &mut self, + value: impl EncodeContentsForLazy, + ) -> Lazy { + let pos = self.position(); - assert!(pos + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) - } + assert_eq!(self.lazy_state, LazyState::NoNode); + self.lazy_state = LazyState::NodeStart(pos); + let meta = value.encode_contents_for_lazy(self); + self.lazy_state = LazyState::NoNode; - pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: 'b + Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + assert!(pos + ::min_size(meta) <= self.position()); - assert!(pos + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) + Lazy::from_position_and_meta(pos, meta) } /// Emit the data for a `DefId` to the metadata. The function to @@ -312,7 +321,7 @@ impl<'tcx> EncodeContext<'tcx> { assert!(id.is_local()); let entry = op(self, data); - let entry = self.lazy(&entry); + let entry = self.lazy(entry); self.entries_index.record(id, entry); } @@ -333,7 +342,7 @@ impl<'tcx> EncodeContext<'tcx> { self.lazy(definitions.def_path_table()) } - fn encode_source_map(&mut self) -> LazySeq { + fn encode_source_map(&mut self) -> Lazy<[syntax_pos::SourceFile]> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -372,10 +381,12 @@ impl<'tcx> EncodeContext<'tcx> { }) .collect::>(); - self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) + self.lazy(adapted.iter().map(|rc| &**rc)) } fn encode_crate_root(&mut self) -> Lazy> { + let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + let mut i = self.position(); let crate_deps = self.encode_crate_deps(); @@ -393,6 +404,11 @@ impl<'tcx> EncodeContext<'tcx> { let lang_items_missing = self.encode_lang_items_missing(); let lang_item_bytes = self.position() - i; + // Encode the diagnostic items. + i = self.position(); + let diagnostic_items = self.encode_diagnostic_items(); + let diagnostic_item_bytes = self.position() - i; + // Encode the native libraries used i = self.position(); let native_libraries = self.encode_native_libraries(); @@ -453,20 +469,26 @@ impl<'tcx> EncodeContext<'tcx> { } n = new_n; } - self.lazy_seq(interpret_alloc_index) + self.lazy(interpret_alloc_index) }; + i = self.position(); let entries_index = self.entries_index.write_index(&mut self.opaque); let entries_index_bytes = self.position() - i; + // Encode the proc macro data + i = self.position(); + let proc_macro_data = self.encode_proc_macros(); + let proc_macro_data_bytes = self.position() - i; + + let attrs = tcx.hir().krate_attrs(); - let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); let has_global_allocator = *tcx.sess.has_global_allocator.get(); let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); - let root = self.lazy(&CrateRoot { + let root = self.lazy(CrateRoot { name: tcx.crate_name(LOCAL_CRATE), extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), @@ -484,6 +506,7 @@ impl<'tcx> EncodeContext<'tcx> { } else { None }, + proc_macro_data, proc_macro_stability: if is_proc_macro { tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone()) } else { @@ -502,6 +525,7 @@ impl<'tcx> EncodeContext<'tcx> { dylib_dependency_formats, lib_features, lang_items, + diagnostic_items, lang_items_missing, native_libraries, foreign_modules, @@ -527,11 +551,13 @@ impl<'tcx> EncodeContext<'tcx> { println!(" dep bytes: {}", dep_bytes); println!(" lib feature bytes: {}", lib_feature_bytes); println!(" lang item bytes: {}", lang_item_bytes); + println!(" diagnostic item bytes: {}", diagnostic_item_bytes); println!(" native bytes: {}", native_lib_bytes); println!(" source_map bytes: {}", source_map_bytes); println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); + println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); println!(" entries index bytes: {}", entries_index_bytes); println!(" zero bytes: {}", zero_bytes); @@ -543,17 +569,17 @@ impl<'tcx> EncodeContext<'tcx> { } impl EncodeContext<'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { + fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { debug!("EncodeContext::encode_variances_of({:?})", def_id); let tcx = self.tcx; - self.lazy_seq_ref(&tcx.variances_of(def_id)[..]) + self.lazy(&tcx.variances_of(def_id)[..]) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; let ty = tcx.type_of(def_id); debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(&ty) + self.lazy(ty) } fn encode_enum_variant_info( @@ -582,11 +608,11 @@ impl EncodeContext<'tcx> { let enum_vis = &tcx.hir().expect_item(enum_id).vis; Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy_seq(variant.fields.iter().map(|f| { + children: self.lazy(variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })), @@ -594,17 +620,18 @@ impl EncodeContext<'tcx> { deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -623,7 +650,7 @@ impl EncodeContext<'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -639,26 +666,27 @@ impl EncodeContext<'tcx> { } Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -672,30 +700,31 @@ impl EncodeContext<'tcx> { let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(exports) => self.lazy_seq_ref(exports), - _ => LazySeq::empty(), + Some(exports) => self.lazy(exports), + _ => Lazy::empty(), }, }; Entry { - kind: EntryKind::Mod(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Mod(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(attrs), - children: self.lazy_seq(md.item_ids.iter().map(|item_id| { + children: self.lazy(md.item_ids.iter().map(|item_id| { tcx.hir().local_def_id(item_id.id).index })), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, - mir: None + mir: None, + promoted_mir: None, } } @@ -715,21 +744,22 @@ impl EncodeContext<'tcx> { Entry { kind: EntryKind::Field, - visibility: self.lazy(&field.vis), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(field.vis), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -744,7 +774,7 @@ impl EncodeContext<'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -770,26 +800,27 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, adt_def_id); Entry { - kind: EntryKind::Struct(self.lazy(&data), repr_options), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Struct(self.lazy(data), repr_options), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -802,13 +833,13 @@ impl EncodeContext<'tcx> { fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_of(def_id)) + self.lazy(&*tcx.predicates_of(def_id)) } fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_defined_on(def_id)) + self.lazy(&*tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { @@ -839,29 +870,30 @@ impl EncodeContext<'tcx> { let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); - let rendered_const = self.lazy(&RenderedConst(rendered)); + let rendered_const = self.lazy(RenderedConst(rendered)); EntryKind::AssocConst(container, const_qualif, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { - let arg_names = match *m { + let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.node { + let param_names = match *m { hir::TraitMethod::Required(ref names) => { - self.encode_fn_arg_names(names) + self.encode_fn_param_names(names) } hir::TraitMethod::Provided(body) => { - self.encode_fn_arg_names_for_body(body) + self.encode_fn_param_names_for_body(body) } }; FnData { + asyncness: method_sig.header.asyncness, constness: hir::Constness::NotConst, - arg_names, + param_names, sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -873,10 +905,10 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&trait_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(trait_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -894,17 +926,18 @@ impl EncodeContext<'tcx> { } ty::AssocKind::OpaqueTy => unreachable!(), }, - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if trait_item.kind == ty::AssocKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -950,14 +983,15 @@ impl EncodeContext<'tcx> { ty::AssocKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { + asyncness: sig.header.asyncness, constness: sig.header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), + param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: impl_item.method_has_self_argument, @@ -985,33 +1019,34 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&impl_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(impl_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if impl_item.kind == ty::AssocKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } - fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) - -> LazySeq { + fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) + -> Lazy<[ast::Name]> { self.tcx.dep_graph.with_ignore(|| { let body = self.tcx.hir().body(body_id); - self.lazy_seq(body.arguments.iter().map(|arg| { + self.lazy(body.params.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, _ => kw::Invalid, @@ -1020,28 +1055,41 @@ impl EncodeContext<'tcx> { }) } - fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> LazySeq { - self.lazy_seq(param_names.iter().map(|ident| ident.name)) + fn encode_fn_param_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> { + self.lazy(param_names.iter().map(|ident| ident.name)) } fn encode_optimized_mir(&mut self, def_id: DefId) -> Option>> { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(&mir)) + Some(self.lazy(mir)) + } else { + None + } + } + + fn encode_promoted_mir( + &mut self, + def_id: DefId, + ) -> Option>>> { + debug!("EncodeContext::encode_promoted_mir({:?})", def_id); + if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { + let promoted = self.tcx.promoted_mir(def_id); + Some(self.lazy(promoted)) } else { None } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { + fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { - LazySeq::empty() + Lazy::empty() } else { - self.lazy_seq(implementations.iter().map(|&def_id| { + self.lazy(implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) @@ -1055,7 +1103,7 @@ impl EncodeContext<'tcx> { fn encode_deprecation(&mut self, def_id: DefId) -> Option> { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) + self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { @@ -1082,12 +1130,13 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Fn(_, header, .., body) => { let data = FnData { + asyncness: header.asyncness, constness: header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + param_names: self.encode_fn_param_names_for_body(body), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::Fn(self.lazy(&data)) + EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); @@ -1108,7 +1157,7 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, def_id); - EntryKind::Struct(self.lazy(&VariantData { + EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, @@ -1119,7 +1168,7 @@ impl EncodeContext<'tcx> { let variant = tcx.adt_def(def_id).non_enum_variant(); let repr_options = get_repr_options(tcx, def_id); - EntryKind::Union(self.lazy(&VariantData { + EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, @@ -1156,10 +1205,10 @@ impl EncodeContext<'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), + trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; - EntryKind::Impl(self.lazy(&data)) + EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { let trait_def = tcx.trait_def(def_id); @@ -1168,37 +1217,51 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::Trait(self.lazy(&data)) + EntryKind::Trait(self.lazy(data)) } hir::ItemKind::TraitAlias(..) => { let data = TraitAliasData { - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::TraitAlias(self.lazy(&data)) + EntryKind::TraitAlias(self.lazy(data)) } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }; + let mir = match item.node { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, + hir::ItemKind::Fn(_, header, ..) => { + let generics = tcx.generics_of(def_id); + let needs_inline = + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + needs_inline || header.constness == hir::Constness::Const || always_encode_mir + } + _ => false, + }; + Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(&item.span), + visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), + span: self.lazy(item.span), attributes: self.encode_attributes(&item.attrs), children: match item.node { hir::ItemKind::ForeignMod(ref fm) => { - self.lazy_seq(fm.items + self.lazy(fm.items .iter() .map(|foreign_item| tcx.hir().local_def_id( foreign_item.hir_id).index)) } hir::ItemKind::Enum(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.variants.iter().map(|v| { + self.lazy(def.variants.iter().map(|v| { assert!(v.def_id.is_local()); v.def_id.index })) @@ -1206,19 +1269,19 @@ impl EncodeContext<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| { + self.lazy(def.non_enum_variant().fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })) } hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => { - self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { + self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) } - _ => LazySeq::empty(), + _ => Lazy::empty(), }, stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -1241,7 +1304,7 @@ impl EncodeContext<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: match item.node { hir::ItemKind::Static(..) | @@ -1283,29 +1346,8 @@ impl EncodeContext<'tcx> { _ => None, // not *wrong* for other kinds of items, but not needed }, - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) - } - hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), - hir::ItemKind::Fn(_, header, ..) => { - let generics = tcx.generics_of(def_id); - let needs_inline = - (generics.requires_monomorphization(tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - if needs_inline - || header.constness == hir::Constness::Const - || always_encode_mir - { - self.encode_optimized_mir(def_id) - } else { - None - } - } - _ => None, - }, + mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } @@ -1314,24 +1356,25 @@ impl EncodeContext<'tcx> { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); Entry { - kind: EntryKind::MacroDef(self.lazy(&MacroDef { - body: pprust::tokens_to_string(macro_def.body.clone()), + kind: EntryKind::MacroDef(self.lazy(MacroDef { + body: pprust::tts_to_string(macro_def.body.clone()), legacy: macro_def.legacy, })), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(¯o_def.span), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(macro_def.span), attributes: self.encode_attributes(¯o_def.attrs), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), - children: LazySeq::empty(), + children: Lazy::empty(), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1344,20 +1387,21 @@ impl EncodeContext<'tcx> { let tcx = self.tcx; Entry { kind: entry_kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1389,13 +1433,13 @@ impl EncodeContext<'tcx> { let data = GeneratorData { layout: layout.clone(), }; - EntryKind::Generator(self.lazy(&data)) + EntryKind::Generator(self.lazy(data)) } ty::Closure(def_id, substs) => { let sig = substs.closure_sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(&sig) }; - EntryKind::Closure(self.lazy(&data)) + let data = ClosureData { sig: self.lazy(sig) }; + EntryKind::Closure(self.lazy(data)) } _ => bug!("closure that is neither generator nor closure") @@ -1403,21 +1447,22 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: LazySeq::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: None, predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1431,39 +1476,56 @@ impl EncodeContext<'tcx> { Entry { kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { - self.lazy_seq_ref(attrs) + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { + self.lazy(attrs) } - fn encode_native_libraries(&mut self) -> LazySeq { + fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); - self.lazy_seq(used_libraries.iter().cloned()) + self.lazy(used_libraries.iter().cloned()) } - fn encode_foreign_modules(&mut self) -> LazySeq { + fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); - self.lazy_seq(foreign_modules.iter().cloned()) + self.lazy(foreign_modules.iter().cloned()) + } + + fn encode_proc_macros(&mut self) -> Option> { + let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + if is_proc_macro { + let tcx = self.tcx; + Some(self.lazy(tcx.hir().krate().items.values().filter_map(|item| { + if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) { + Some(item.hir_id.owner) + } else { + None + } + }))) + } else { + None + } } - fn encode_crate_deps(&mut self) -> LazySeq { + fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { let crates = self.tcx.crates(); let mut deps = crates @@ -1494,20 +1556,26 @@ impl EncodeContext<'tcx> { // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) + self.lazy(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option)> { + fn encode_lib_features(&mut self) -> Lazy<[(ast::Name, Option)]> { let tcx = self.tcx; let lib_features = tcx.lib_features(); - self.lazy_seq(lib_features.to_vec()) + self.lazy(lib_features.to_vec()) + } + + fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> { + let tcx = self.tcx; + let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE); + self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index))) } - fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> { + fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { let tcx = self.tcx; let lang_items = tcx.lang_items(); let lang_items = lang_items.items().iter(); - self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { + self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { if let Some(def_id) = opt_def_id { if def_id.is_local() { return Some((def_id.index, i)); @@ -1517,13 +1585,13 @@ impl EncodeContext<'tcx> { })) } - fn encode_lang_items_missing(&mut self) -> LazySeq { + fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> { let tcx = self.tcx; - self.lazy_seq_ref(&tcx.lang_items().missing) + self.lazy(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) -> LazySeq { + fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { @@ -1549,12 +1617,12 @@ impl EncodeContext<'tcx> { TraitImpls { trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_seq_ref(&impls), + impls: self.lazy(&impls), } }) .collect(); - self.lazy_seq_ref(&all_impls) + self.lazy(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1565,12 +1633,12 @@ impl EncodeContext<'tcx> { // definition (as that's not defined in this crate). fn encode_exported_symbols(&mut self, exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)]) - -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> { + -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> { // The metadata symbol name is special. It should not show up in // downstream crates. let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); - self.lazy_seq(exported_symbols + self.lazy(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1583,10 +1651,10 @@ impl EncodeContext<'tcx> { .cloned()) } - fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { + fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option]> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { - self.lazy_seq(arr.iter().map(|slot| { + self.lazy(arr.iter().map(|slot| { match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, @@ -1596,7 +1664,7 @@ impl EncodeContext<'tcx> { } })) } - None => LazySeq::empty(), + None => Lazy::empty(), } } @@ -1610,11 +1678,12 @@ impl EncodeContext<'tcx> { let kind = match nitem.node { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { + asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(names), - sig: self.lazy(&tcx.fn_sig(def_id)), + param_names: self.encode_fn_param_names(names), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::ForeignFn(self.lazy(&data)) + EntryKind::ForeignFn(self.lazy(data)) } hir::ForeignItemKind::Static(_, hir::MutMutable) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, hir::MutImmutable) => EntryKind::ForeignImmStatic, @@ -1623,24 +1692,25 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(&nitem.span), + visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), + span: self.lazy(nitem.span), attributes: self.encode_attributes(&nitem.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: match nitem.node { hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, mir: None, + promoted_mir: None, } } } @@ -1676,7 +1746,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { id: hir::HirId) { intravisit::walk_variant(self, v, g, id); - if let Some(ref discr) = v.node.disr_expr { + if let Some(ref discr) = v.disr_expr { let def_id = self.tcx.hir().local_def_id(discr.hir_id); self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } diff --git a/src/librustc_metadata/error_codes.rs b/src/librustc_metadata/error_codes.rs index 0708a6243b..cd8e95e6c3 100644 --- a/src/librustc_metadata/error_codes.rs +++ b/src/librustc_metadata/error_codes.rs @@ -1,6 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { +syntax::register_diagnostics! { E0454: r##" A link name was given with an empty name. Erroneous code example: @@ -84,10 +82,7 @@ You need to link your code to the relevant crate in order to be able to use it (through Cargo or the `-L` option of rustc example). Plugins are crates as well, and you link to them the same way. "##, - -} - -register_diagnostics! { +; E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0514, // metadata version mismatch @@ -97,5 +92,6 @@ register_diagnostics! { E0464, // multiple matching crates for `..` E0465, // multiple .. candidates for `..` found E0519, // local crate and dependency have same (crate-name, disambiguator) - E0523, // two dependencies have same (crate-name, disambiguator) but different SVH + // two dependencies have same (crate-name, disambiguator) but different SVH + E0523, } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index dd2f59922e..6f248f22cf 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -108,18 +108,18 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { + pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); // First we write the length of the lower range ... buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes()); // ... then the values. buf.emit_raw_bytes(&self.positions); - LazySeq::with_position_and_length(pos as usize, self.positions.len() / 4 + 1) + Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1) } } -impl LazySeq> { +impl Lazy<[Index<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] @@ -127,7 +127,7 @@ impl LazySeq> { let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, - self.len); + self.meta); let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); if position == u32::MAX { @@ -135,7 +135,7 @@ impl LazySeq> { None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::with_position(position as usize)) + Some(Lazy::from_position(position as usize)) } } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index c96d02d9b3..e6104e629e 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -8,7 +8,6 @@ #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] -#![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(specialization)] @@ -23,7 +22,7 @@ extern crate rustc; #[macro_use] extern crate rustc_data_structures; -mod error_codes; +pub mod error_codes; mod index; mod encoder; @@ -68,5 +67,3 @@ pub fn validate_crate_name( sess.unwrap().abort_if_errors(); } } - -__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 3832c8ee22..ceba7cf0fe 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -716,7 +716,9 @@ impl<'a> Context<'a> { let root = metadata.get_root(); if let Some(is_proc_macro) = self.is_proc_macro { - if root.proc_macro_decls_static.is_some() != is_proc_macro { + if root.proc_macro_data.is_some() != is_proc_macro { + info!("Rejecting via proc macro: expected {} got {}", + is_proc_macro, root.proc_macro_data.is_some()); return None; } } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 66971bb6f8..ada1a8c615 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -8,7 +8,7 @@ use rustc_target::spec::abi::Abi; use syntax::attr; use syntax::source_map::Span; use syntax::feature_gate::{self, GateIssue}; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::{kw, sym, Symbol}; use syntax::{span_err, struct_span_err}; pub fn collect(tcx: TyCtxt<'_>) -> Vec { @@ -132,7 +132,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { impl Collector<'tcx> { fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { - if lib.name.as_ref().map(|s| s.as_str().is_empty()).unwrap_or(false) { + if lib.name.as_ref().map(|&s| s == kw::Invalid).unwrap_or(false) { match span { Some(span) => { struct_span_err!(self.tcx.sess, span, E0454, @@ -159,7 +159,7 @@ impl Collector<'tcx> { sym::link_cfg, span.unwrap(), GateIssue::Language, - "is feature gated"); + "is unstable"); } if lib.kind == cstore::NativeStaticNobundle && !self.tcx.features().static_nobundle { @@ -167,7 +167,7 @@ impl Collector<'tcx> { sym::static_nobundle, span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, - "kind=\"static-nobundle\" is feature gated"); + "kind=\"static-nobundle\" is unstable"); } self.libs.push(lib); } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index c0ac691593..92534ab056 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -11,6 +11,7 @@ use rustc::session::CrateDisambiguator; use rustc::session::config::SymbolManglingVersion; use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::svh::Svh; use syntax::{ast, attr}; @@ -41,6 +42,33 @@ pub const METADATA_VERSION: u8 = 4; pub const METADATA_HEADER: &[u8; 12] = &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; +/// Additional metadata for a `Lazy` where `T` may not be `Sized`, +/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values). +pub trait LazyMeta { + type Meta: Copy + 'static; + + /// Returns the minimum encoded size. + // FIXME(eddyb) Give better estimates for certain types. + fn min_size(meta: Self::Meta) -> usize; +} + +impl LazyMeta for T { + type Meta = (); + + fn min_size(_: ()) -> usize { + assert_ne!(std::mem::size_of::(), 0); + 1 + } +} + +impl LazyMeta for [T] { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * T::min_size(()) + } +} + /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. /// @@ -56,40 +84,8 @@ pub const METADATA_HEADER: &[u8; 12] = /// Distances start at 1, as 0-byte nodes are invalid. /// Also invalid are nodes being referred in a different /// order than they were encoded in. -#[must_use] -pub struct Lazy { - pub position: usize, - _marker: PhantomData, -} - -impl Lazy { - pub fn with_position(position: usize) -> Lazy { - Lazy { - position, - _marker: PhantomData, - } - } - - /// Returns the minimum encoded size of a value of type `T`. - // FIXME(eddyb) Give better estimates for certain types. - pub fn min_size() -> usize { - 1 - } -} - -impl Copy for Lazy {} -impl Clone for Lazy { - fn clone(&self) -> Self { - *self - } -} - -impl rustc_serialize::UseSpecializedEncodable for Lazy {} -impl rustc_serialize::UseSpecializedDecodable for Lazy {} - -/// A sequence of type T referred to by its absolute position -/// in the metadata and length, and which can be decoded lazily. -/// The sequence is a single node for the purposes of `Lazy`. +/// +/// # Sequences (`Lazy<[T]>`) /// /// Unlike `Lazy>`, the length is encoded next to the /// position, not at the position, which means that the length @@ -100,54 +96,62 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy {} /// the minimal distance the length of the sequence, i.e. /// it's assumed there's no 0-byte element in the sequence. #[must_use] -pub struct LazySeq { - pub len: usize, +// FIXME(#59875) the `Meta` parameter only exists to dodge +// invariance wrt `T` (coming from the `meta: T::Meta` field). +pub struct Lazy::Meta> + where T: ?Sized + LazyMeta, + Meta: 'static + Copy, +{ pub position: usize, + pub meta: Meta, _marker: PhantomData, } -impl LazySeq { - pub fn empty() -> LazySeq { - LazySeq::with_position_and_length(0, 0) - } - - pub fn with_position_and_length(position: usize, len: usize) -> LazySeq { - LazySeq { - len, +impl Lazy { + pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + Lazy { position, + meta, _marker: PhantomData, } } +} - /// Returns the minimum encoded size of `length` values of type `T`. - pub fn min_size(length: usize) -> usize { - length +impl Lazy { + pub fn from_position(position: usize) -> Lazy { + Lazy::from_position_and_meta(position, ()) } } -impl Copy for LazySeq {} -impl Clone for LazySeq { +impl Lazy<[T]> { + pub fn empty() -> Lazy<[T]> { + Lazy::from_position_and_meta(0, 0) + } +} + +impl Copy for Lazy {} +impl Clone for Lazy { fn clone(&self) -> Self { *self } } -impl rustc_serialize::UseSpecializedEncodable for LazySeq {} -impl rustc_serialize::UseSpecializedDecodable for LazySeq {} +impl rustc_serialize::UseSpecializedEncodable for Lazy {} +impl rustc_serialize::UseSpecializedDecodable for Lazy {} -/// Encoding / decoding state for `Lazy` and `LazySeq`. +/// Encoding / decoding state for `Lazy`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { /// Outside of a metadata node. NoNode, - /// Inside a metadata node, and before any `Lazy` or `LazySeq`. + /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. NodeStart(usize), - /// Inside a metadata node, with a previous `Lazy` or `LazySeq`. + /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that - /// previous `Lazy` / `LazySeq` would end (see their comments). + /// previous `Lazy` would end (see their comments). Previous(usize), } @@ -167,20 +171,25 @@ pub struct CrateRoot<'tcx> { pub proc_macro_decls_static: Option, pub proc_macro_stability: Option, - pub crate_deps: LazySeq, - pub dylib_dependency_formats: LazySeq>, - pub lib_features: LazySeq<(Symbol, Option)>, - pub lang_items: LazySeq<(DefIndex, usize)>, - pub lang_items_missing: LazySeq, - pub native_libraries: LazySeq, - pub foreign_modules: LazySeq, - pub source_map: LazySeq, + pub crate_deps: Lazy<[CrateDep]>, + pub dylib_dependency_formats: Lazy<[Option]>, + pub lib_features: Lazy<[(Symbol, Option)]>, + pub lang_items: Lazy<[(DefIndex, usize)]>, + pub lang_items_missing: Lazy<[lang_items::LangItem]>, + pub diagnostic_items: Lazy<[(Symbol, DefIndex)]>, + pub native_libraries: Lazy<[NativeLibrary]>, + pub foreign_modules: Lazy<[ForeignModule]>, + pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, - pub impls: LazySeq, - pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, - pub interpret_alloc_index: LazySeq, + pub impls: Lazy<[TraitImpls]>, + pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub interpret_alloc_index: Lazy<[u32]>, + + pub entries_index: Lazy<[index::Index<'tcx>]>, - pub entries_index: LazySeq>, + /// The DefIndex's of any proc macros delcared by + /// this crate + pub proc_macro_data: Option>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -203,7 +212,7 @@ pub struct CrateDep { #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), - pub impls: LazySeq, + pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -211,19 +220,20 @@ pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: Lazy, pub span: Lazy, - pub attributes: LazySeq, - pub children: LazySeq, + pub attributes: Lazy<[ast::Attribute]>, + pub children: Lazy<[DefIndex]>, pub stability: Option>, pub deprecation: Option>, pub ty: Option>>, - pub inherent_impls: LazySeq, - pub variances: LazySeq, + pub inherent_impls: Lazy<[DefIndex]>, + pub variances: Lazy<[ty::Variance]>, pub generics: Option>, pub predicates: Option>>, pub predicates_defined_on: Option>>, pub mir: Option>>, + pub promoted_mir: Option>>>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] @@ -274,7 +284,7 @@ pub struct RenderedConst(pub String); #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { - pub reexports: LazySeq>, + pub reexports: Lazy<[def::Export]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -285,8 +295,9 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { + pub asyncness: hir::IsAsync, pub constness: hir::Constness, - pub arg_names: LazySeq, + pub param_names: Lazy<[ast::Name]>, pub sig: Lazy>, } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 21008c7372..0691390bea 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,14 +15,15 @@ either = "1.5.0" dot = { path = "../libgraphviz", package = "graphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } +rustc_lexer = { path = "../librustc_lexer" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -byteorder = { version = "1.1", features = ["i128"] } +byteorder = { version = "1.3" } rustc_apfloat = { path = "../librustc_apfloat" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index c9e6e7f70a..db19cbc317 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -317,7 +317,7 @@ impl<'a, 'tcx> GatherBorrows<'a, 'tcx> { // so extract `temp`. let temp = if let &mir::Place { base: mir::PlaceBase::Local(temp), - projection: None, + projection: box [], } = assigned_place { temp } else { diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 4217a29bc6..599a0ad0d0 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -2,8 +2,8 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, - LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection, PlaceRef, - ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm, + LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, + Statement, StatementKind, TerminatorKind, VarBindingForm, }; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashSet; @@ -98,7 +98,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self.describe_place_with_options(moved_place, IncludingDowncast(true)) .unwrap_or_else(|| "_".to_owned()), ); - err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + err.span_label(span, format!("use of possibly-uninitialized {}", item_msg)); use_spans.var_span_label( &mut err, @@ -180,7 +180,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() { - if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + let sess = self.infcx.tcx.sess; + if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { err.span_suggestion( move_span, "consider borrowing to avoid moving into the for loop", @@ -244,7 +245,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let span = if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = place { let decl = &self.body.local_decls[*local]; Some(decl.source_info.span) @@ -614,17 +615,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { projection, } = first_borrowed_place; - let mut current = projection; + let mut cursor = &**projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; - while let Some(box Projection { base: base_proj, elem }) = current { match elem { - ProjectionElem::Field(field, _) if union_ty(base, base_proj).is_some() => { + ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => { return Some((PlaceRef { base: base, - projection: base_proj, + projection: proj_base, }, field)); }, - _ => current = base_proj, + _ => {}, } } None @@ -637,9 +639,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { projection, } = second_borrowed_place; - let mut current = projection; + let mut cursor = &**projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; - while let Some(box Projection { base: proj_base, elem }) = current { if let ProjectionElem::Field(field, _) = elem { if let Some(union_ty) = union_ty(base, proj_base) { if field != target_field @@ -660,8 +663,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } - - current = proj_base; } None }) @@ -707,7 +708,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.var_or_use(); - assert!(root_place.projection.is_none()); + assert!(root_place.projection.is_empty()); let proper_span = match root_place.base { PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span, _ => drop_span, @@ -716,7 +717,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if self.access_place_error_reported .contains(&(Place { base: root_place.base.clone(), - projection: root_place.projection.clone(), + projection: root_place.projection.to_vec().into_boxed_slice(), }, borrow_span)) { debug!( @@ -729,7 +730,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.access_place_error_reported .insert((Place { base: root_place.base.clone(), - projection: root_place.projection.clone(), + projection: root_place.projection.to_vec().into_boxed_slice(), }, borrow_span)); if let StorageDeadOrDrop::Destructor(dropped_ty) = @@ -1107,7 +1108,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let local_kind = match borrow.borrowed_place { Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } => { match self.body.local_kind(local) { LocalKind::ReturnPointer @@ -1136,7 +1137,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .unwrap(); let local = if let PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } = root_place { local } else { @@ -1190,7 +1191,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) { - Ok(string) => format!("move {}", string), + Ok(mut string) => { + if string.starts_with("async ") { + string.insert_str(6, "move "); + } else if string.starts_with("async|") { + string.insert_str(5, " move"); + } else { + string.insert_str(0, "move "); + }; + string + }, Err(_) => "move || ".to_string() }; @@ -1437,7 +1447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { let (from_arg, local_decl) = if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = *err_place { if let LocalKind::Arg = self.body.local_kind(local) { (true, Some(&self.body.local_decls[local])) @@ -1510,20 +1520,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> { let tcx = self.infcx.tcx; match place.projection { - None => { + [] => { StorageDeadOrDrop::LocalStorageDead } - Some(box Projection { ref base, ref elem }) => { + [proj_base @ .., elem] => { + // FIXME(spastorino) make this iterate let base_access = self.classify_drop_access_kind(PlaceRef { base: place.base, - projection: base, + projection: proj_base, }); match elem { ProjectionElem::Deref => match base_access { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(&place.base, base, self.body, tcx).ty.is_box(), + Place::ty_from(&place.base, proj_base, self.body, tcx).ty.is_box(), "Drop of value behind a reference or raw pointer" ); StorageDeadOrDrop::BoxedStorageDead @@ -1531,7 +1542,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::Destructor(_) => base_access, }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = Place::ty_from(&place.base, base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; match base_ty.sty { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor @@ -1589,7 +1600,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "annotate_argument_and_return_for_borrow: location={:?}", location ); - if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..}) + if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..}) = &self.body[location.block].statements.get(location.statement_index) { debug!( @@ -1600,7 +1611,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut target = *match reservation { Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } if self.body.local_kind(*local) == LocalKind::Temp => local, _ => return None, }; @@ -1614,11 +1625,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { target, stmt ); if let StatementKind::Assign( - Place { - base: PlaceBase::Local(assigned_to), - projection: None, - }, - box rvalue + box( + Place { + base: PlaceBase::Local(assigned_to), + projection: box [], + }, + rvalue + ) ) = &stmt.kind { debug!( "annotate_argument_and_return_for_borrow: assigned_to={:?} \ @@ -1744,7 +1757,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let TerminatorKind::Call { destination: Some((Place { base: PlaceBase::Local(assigned_to), - projection: None, + projection: box [], }, _)), args, .. diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 99899aa390..5bccd2835c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -41,7 +41,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut target = place.local_or_deref_local(); for stmt in &self.body[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); - if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind { + if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); match from { Operand::Copy(ref place) | @@ -152,35 +152,36 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } => { self.append_local_to_string(*local, buf)?; } PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), - projection: None, + projection: [], } => { buf.push_str("promoted"); } PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), - projection: None, + projection: [], } => { buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string()); } PlaceRef { base, - projection: Some(ref proj), + projection: [proj_base @ .., elem], } => { - match proj.elem { + match elem { ProjectionElem::Deref => { let upvar_field_projection = self.is_upvar_field_projection(place); @@ -198,20 +199,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, &including_downcast, )?; } else { - match (&proj.base, base) { - (None, PlaceBase::Local(local)) => { + match (proj_base, base) { + ([], PlaceBase::Local(local)) => { if self.body.local_decls[*local].is_ref_for_guard() { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -223,7 +224,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -237,7 +238,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -252,7 +253,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -274,12 +275,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { let field_name = self.describe_field(PlaceRef { base, - projection: &proj.base, - }, field); + projection: proj_base, + }, *field); self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -294,14 +295,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, &including_downcast, )?; buf.push_str("["); - if self.append_local_to_string(index, buf).is_err() { + if self.append_local_to_string(*index, buf).is_err() { buf.push_str("_"); } buf.push_str("]"); @@ -314,7 +315,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.append_place_to_string( PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, buf, autoderef, @@ -335,7 +336,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let local = &self.body.local_decls[local_index]; match local.name { Some(name) if !local.from_compiler_desugaring() => { - buf.push_str(name.as_str().get()); + buf.push_str(&name.as_str()); Ok(()) } _ => Err(()), @@ -348,28 +349,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } => { let local = &self.body.local_decls[*local]; self.describe_field_from_ty(&local.ty, field, None) } PlaceRef { base: PlaceBase::Static(static_), - projection: None, + projection: [], } => self.describe_field_from_ty(&static_.ty, field, None), PlaceRef { base, - projection: Some(proj), - } => match proj.elem { - ProjectionElem::Deref => self.describe_field(PlaceRef { - base, - projection: &proj.base, - }, field), + projection: [proj_base @ .., elem], + } => match elem { + ProjectionElem::Deref => { + self.describe_field(PlaceRef { + base, + projection: proj_base, + }, field) + } ProjectionElem::Downcast(_, variant_index) => { let base_ty = Place::ty_from(place.base, place.projection, self.body, self.infcx.tcx).ty; - self.describe_field_from_ty(&base_ty, field, Some(variant_index)) + self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } ProjectionElem::Field(_, field_type) => { self.describe_field_from_ty(&field_type, field, None) @@ -379,7 +382,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ProjectionElem::Subslice { .. } => { self.describe_field(PlaceRef { base, - projection: &proj.base, + projection: proj_base, }, field) } }, @@ -440,10 +443,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub fn is_place_thread_local(&self, place_ref: PlaceRef<'cx, 'tcx>) -> bool { if let PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), - projection: None, + projection: [], } = place_ref { let attrs = self.infcx.tcx.get_attrs(*def_id); let is_thread_local = attrs.iter().any(|attr| attr.check_name(sym::thread_local)); @@ -788,8 +792,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); if let StatementKind::Assign( - _, - box Rvalue::Aggregate(ref kind, ref places) + box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { let (def_id, is_generator) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), @@ -826,10 +829,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .get(location.statement_index) { Some(&Statement { - kind: StatementKind::Assign(Place { + kind: StatementKind::Assign(box(Place { base: PlaceBase::Local(local), - projection: None, - }, _), + projection: box [], + }, _)), .. }) => local, _ => return OtherUse(use_span), @@ -842,7 +845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { for stmt in &self.body[location.block].statements[location.statement_index + 1..] { if let StatementKind::Assign( - _, box Rvalue::Aggregate(ref kind, ref places) + box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { let (def_id, is_generator) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index bb217a1f96..1f17ab69f6 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -12,7 +12,7 @@ use crate::borrow_check::location::LocationIndex; use polonius_engine::Output; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::HasMoveData; +use crate::dataflow::move_paths::{HasMoveData, MovePathIndex}; use crate::dataflow::Borrows; use crate::dataflow::EverInitializedPlaces; use crate::dataflow::MaybeUninitializedPlaces; @@ -21,9 +21,8 @@ use either::Either; use std::fmt; use std::rc::Rc; -crate type PoloniusOutput = Output; +crate type PoloniusOutput = Output; -// (forced to be `pub` due to its use as an associated type below.) crate struct Flows<'b, 'tcx> { borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>, pub uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index de27aec2b2..32c6dd67a4 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -10,10 +10,10 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::middle::borrowck::SignalledError; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ - ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceRef, - Static, StaticKind + ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceElem, + PlaceRef, Static, StaticKind }; -use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; @@ -22,6 +22,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::indexed_vec::IndexVec; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -86,12 +87,13 @@ pub fn provide(providers: &mut Providers<'_>) { } fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { - let input_body = tcx.mir_validated(def_id); + let (input_body, promoted) = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); - do_mir_borrowck(&infcx, input_body, def_id) + let promoted: &IndexVec<_, _> = &promoted.borrow(); + do_mir_borrowck(&infcx, input_body, promoted, def_id) }); debug!("mir_borrowck done"); @@ -101,6 +103,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, + input_promoted: &IndexVec>, def_id: DefId, ) -> BorrowCheckResult<'tcx> { debug!("do_mir_borrowck(def_id = {:?})", def_id); @@ -147,7 +150,9 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body); + let mut promoted: IndexVec> = input_promoted.clone(); + let free_regions = + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = &body; // no further changes let location_table = &LocationTable::new(body); @@ -159,8 +164,8 @@ fn do_mir_borrowck<'a, 'tcx>( }; let mdpe = MoveDataParamEnv { - move_data: move_data, - param_env: param_env, + move_data, + param_env, }; let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); @@ -184,6 +189,7 @@ fn do_mir_borrowck<'a, 'tcx>( def_id, free_regions, body, + &promoted, &upvars, location_table, param_env, @@ -253,7 +259,10 @@ fn do_mir_borrowck<'a, 'tcx>( move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), errors_buffer, - disable_error_downgrading: false, + // Only downgrade errors on Rust 2015 and refuse to do so on Rust 2018. + // FIXME(Centril): In Rust 1.40.0, refuse doing so on 2015 as well and + // proceed to throwing out the migration infrastructure. + disable_error_downgrading: body.span.rust_2018(), nonlexical_regioncx: regioncx, used_mut: Default::default(), used_mut_upvars: SmallVec::new(), @@ -393,7 +402,7 @@ fn do_mir_borrowck<'a, 'tcx>( } for diag in mbcx.errors_buffer.drain(..) { - DiagnosticBuilder::new_diagnostic(mbcx.infcx.tcx.sess.diagnostic(), diag).emit(); + mbcx.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag); } } @@ -537,7 +546,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx self.check_activations(location, span, flow_state); match stmt.kind { - StatementKind::Assign(ref lhs, ref rhs) => { + StatementKind::Assign(box(ref lhs, ref rhs)) => { self.consume_rvalue( location, (rhs, span), @@ -552,7 +561,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx flow_state, ); } - StatementKind::FakeRead(_, ref place) => { + StatementKind::FakeRead(_, box ref place) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. @@ -896,7 +905,7 @@ enum InitializationRequiringAction { struct RootPlace<'d, 'tcx> { place_base: &'d PlaceBase<'tcx>, - place_projection: &'d Option>>, + place_projection: &'d [PlaceElem<'tcx>], is_local_mutation_allowed: LocalMutationIsAllowed, } @@ -1182,7 +1191,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // before (at this point in the flow). if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = place_span.0 { if let Mutability::Not = self.body.local_decls[*local].mutability { // check for reassignments to immutable local variables @@ -1322,7 +1331,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) { let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| { - if place.projection.is_some() { + if !place.projection.is_empty() { if let Some(field) = this.is_upvar_field_projection(place.as_ref()) { this.used_mut_upvars.push(field); } @@ -1337,11 +1346,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match *operand { Operand::Move(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) | Operand::Copy(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) if self.body.local_decls[local].is_user_variable.is_none() => { if self.body.local_decls[local].ty.is_mutable_ptr() { // The variable will be marked as mutable by the borrow. @@ -1378,7 +1387,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); - if let StatementKind::Assign(_, box Rvalue::Ref(_, _, ref source)) = stmt.kind { + if let StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref source))) = stmt.kind { propagate_closure_used_mut_place(self, source); } else { bug!("closures should only capture user variables \ @@ -1459,16 +1468,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // // FIXME: allow thread-locals to borrow other thread locals? - assert!(root_place.projection.is_none()); + assert!(root_place.projection.is_empty()); let (might_be_alive, will_be_dropped) = match root_place.base { PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }) => { (true, false) } PlaceBase::Static(box Static { - kind: StaticKind::Static(_), + kind: StaticKind::Static, .. }) => { // Thread-locals might be dropped after the function exits, but @@ -1747,13 +1756,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { flow_state: &Flows<'cx, 'tcx>, ) { debug!("check_if_assigned_path_is_moved place: {:?}", place); - // recur down place; dispatch to external checks when necessary - let mut place_projection = &place.projection; // None case => assigning to `x` does not require `x` be initialized. - while let Some(proj) = place_projection { - let Projection { ref base, ref elem } = **proj; - match *elem { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + + match elem { ProjectionElem::Index(_/*operand*/) | ProjectionElem::ConstantIndex { .. } | // assigning to P[i] requires P to be valid. @@ -1769,7 +1778,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location, InitializationRequiringAction::Use, (PlaceRef { base: &place.base, - projection: base, + projection: proj_base, }, span), flow_state); // (base initialized; no need to // recur further) @@ -1786,14 +1795,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // assigning to `P.f` requires `P` itself // be already initialized let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&place.base, base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; match base_ty.sty { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( location, InitializationRequiringAction::Assignment, (PlaceRef { base: &place.base, - projection: base, + projection: proj_base, }, span), flow_state); // (base initialized; no need to @@ -1806,7 +1815,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Adt(..) | ty::Tuple(..) => { check_parent_of_field(self, location, PlaceRef { base: &place.base, - projection: base, + projection: proj_base, }, span, flow_state); if let PlaceBase::Local(local) = place.base { @@ -1826,8 +1835,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } - - place_projection = base; } fn check_parent_of_field<'cx, 'tcx>( @@ -2075,7 +2082,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match root_place { RootPlace { place_base: PlaceBase::Local(local), - place_projection: None, + place_projection: [], is_local_mutation_allowed, } => { // If the local may have been initialized, and it is now currently being @@ -2094,7 +2101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } => {} RootPlace { place_base, - place_projection: place_projection @ Some(_), + place_projection: place_projection @ [.., _], is_local_mutation_allowed: _, } => { if let Some(field) = self.is_upvar_field_projection(PlaceRef { @@ -2106,7 +2113,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } RootPlace { place_base: PlaceBase::Static(..), - place_projection: None, + place_projection: [], is_local_mutation_allowed: _, } => {} } @@ -2122,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } => { let local = &self.body.local_decls[*local]; match local.mutability { @@ -2150,10 +2157,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), - projection: None, + projection: [], } => Ok(RootPlace { place_base: place.base, @@ -2162,10 +2169,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), - projection: None, + projection: [], } => { if !self.infcx.tcx.is_mutable_static(*def_id) { Err(place) @@ -2179,12 +2187,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } PlaceRef { base: _, - projection: Some(proj), + projection: [proj_base @ .., elem], } => { - match proj.elem { + match elem { ProjectionElem::Deref => { let base_ty = - Place::ty_from(place.base, &proj.base, self.body, self.infcx.tcx).ty; + Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty; // Check the kind of deref to decide match base_ty.sty { @@ -2206,7 +2214,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.is_mutable(PlaceRef { base: place.base, - projection: &proj.base, + projection: proj_base, }, mode) } } @@ -2230,7 +2238,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ if base_ty.is_box() => { self.is_mutable(PlaceRef { base: place.base, - projection: &proj.base, + projection: proj_base, }, is_local_mutation_allowed) } // Deref should only be for reference, pointers or boxes @@ -2287,7 +2295,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // ``` let _ = self.is_mutable(PlaceRef { base: place.base, - projection: &proj.base, + projection: proj_base, }, is_local_mutation_allowed)?; Ok(RootPlace { place_base: place.base, @@ -2299,7 +2307,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { self.is_mutable(PlaceRef { base: place.base, - projection: &proj.base, + projection: proj_base, }, is_local_mutation_allowed) } } @@ -2316,21 +2324,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut place_projection = place_ref.projection; let mut by_ref = false; - if let Some(box Projection { - base, - elem: ProjectionElem::Deref, - }) = place_projection { - place_projection = &base; + if let [proj_base @ .., ProjectionElem::Deref] = place_projection { + place_projection = proj_base; by_ref = true; } match place_projection { - Some(box Projection { - base, - elem: ProjectionElem::Field(field, _ty), - }) => { + [base @ .., ProjectionElem::Field(field, _ty)] => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(place_ref.base, &base, self.body, tcx).ty; + let base_ty = Place::ty_from(place_ref.base, base, self.body, tcx).ty; if (base_ty.is_closure() || base_ty.is_generator()) && (!by_ref || self.upvars[field.index()].by_ref) { diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 738a091b0d..aa732b0092 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -1,5 +1,3 @@ -use core::unicode::property::Pattern_White_Space; - use rustc::mir::*; use rustc::ty; use rustc_errors::{DiagnosticBuilder,Applicability}; @@ -91,11 +89,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // If that ever stops being the case, then the ever initialized // flow could be used. if let Some(StatementKind::Assign( - Place { - base: PlaceBase::Local(local), - projection: None, - }, - box Rvalue::Use(Operand::Move(move_from)), + box( + Place { + base: PlaceBase::Local(local), + projection: box [], + }, + Rvalue::Use(Operand::Move(move_from)) + ) )) = self.body.basic_blocks()[location.block] .statements .get(location.statement_index) @@ -276,16 +276,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { place: &Place<'tcx>, span: Span ) -> DiagnosticBuilder<'a> { - let description = if place.projection.is_none() { + let description = if place.projection.is_empty() { format!("static item `{}`", self.describe_place(place.as_ref()).unwrap()) } else { - let mut base_static = &place.projection; - while let Some(box Projection { base: Some(ref proj), .. }) = base_static { - base_static = &proj.base; - } let base_static = PlaceRef { base: &place.base, - projection: base_static, + projection: &place.projection[..1], }; format!( @@ -311,17 +307,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); - let deref_base = match deref_target_place.projection { - Some(box Projection { ref base, elem: ProjectionElem::Deref }) => PlaceRef { - base: &deref_target_place.base, - projection: base, - }, + let deref_base = match &deref_target_place.projection { + box [proj_base @ .., ProjectionElem::Deref] => { + PlaceRef { + base: &deref_target_place.base, + projection: proj_base, + } + } _ => bug!("deref_target_place is not a deref projection"), }; if let PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } = deref_base { let decl = &self.body.local_decls[*local]; if decl.is_ref_for_guard() { @@ -415,20 +413,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { "{:?}", move_place.ty(self.body, self.infcx.tcx).ty, ); - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); - let is_option = move_ty.starts_with("std::option::Option"); - let is_result = move_ty.starts_with("std::result::Result"); - if is_option || is_result { - err.span_suggestion( - span, - &format!("consider borrowing the `{}`'s content", if is_option { - "Option" - } else { - "Result" - }), - format!("{}.as_ref()", snippet), - Applicability::MaybeIncorrect, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + let is_option = move_ty.starts_with("std::option::Option"); + let is_result = move_ty.starts_with("std::result::Result"); + if is_option || is_result { + err.span_suggestion( + span, + &format!("consider borrowing the `{}`'s content", if is_option { + "Option" + } else { + "Result" + }), + format!("{}.as_ref()", snippet), + Applicability::MaybeIncorrect, + ); + } } err } @@ -439,19 +438,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'a>, span: Span, ) { - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { - err.span_suggestion( - span, - "consider borrowing here", - format!("&{}", snippet), - Applicability::Unspecified, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "consider borrowing here", + format!("&{}", snippet), + Applicability::Unspecified, + ); + } if binds_to.is_empty() { let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; @@ -517,27 +517,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. })) ) = bind_to.is_user_variable { - let pat_snippet = self.infcx.tcx.sess.source_map() - .span_to_snippet(pat_span) - .unwrap(); - if pat_snippet.starts_with('&') { - let pat_snippet = pat_snippet[1..].trim_start(); - let suggestion; - let to_remove; - if pat_snippet.starts_with("mut") - && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) - { - suggestion = pat_snippet["mut".len()..].trim_start(); - to_remove = "&mut"; - } else { - suggestion = pat_snippet; - to_remove = "&"; + if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) + { + if pat_snippet.starts_with('&') { + let pat_snippet = pat_snippet[1..].trim_start(); + let suggestion; + let to_remove; + if pat_snippet.starts_with("mut") + && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace) + { + suggestion = pat_snippet["mut".len()..].trim_start(); + to_remove = "&mut"; + } else { + suggestion = pat_snippet; + to_remove = "&"; + } + suggestions.push(( + pat_span, + to_remove, + suggestion.to_owned(), + )); } - suggestions.push(( - pat_span, - to_remove, - suggestion.to_owned(), - )); } } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 937c6383be..14b76d97b3 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -1,9 +1,8 @@ -use core::unicode::property::Pattern_White_Space; use rustc::hir; use rustc::hir::Node; use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body}; use rustc::mir::{ - Mutability, Place, PlaceRef, PlaceBase, Projection, ProjectionElem, Static, StaticKind + Mutability, Place, PlaceRef, PlaceBase, ProjectionElem, Static, StaticKind }; use rustc::ty::{self, Ty, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; @@ -48,12 +47,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match the_place_err { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } => { item_msg = format!("`{}`", access_place_desc.unwrap()); if let Place { base: PlaceBase::Local(_), - projection: None, + projection: box [], } = access_place { reason = ", as it is not declared as mutable".to_string(); } else { @@ -66,14 +65,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: _, - projection: - Some(box Projection { - base, - elem: ProjectionElem::Field(upvar_index, _), - }), + projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&the_place_err.base, &base, self.body, self.infcx.tcx).ty + Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty )); item_msg = format!("`{}`", access_place_desc.unwrap()); @@ -87,14 +82,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: _, - projection: - Some(box Projection { - base, - elem: ProjectionElem::Deref, - }), + projection: [proj_base @ .., ProjectionElem::Deref], } => { if the_place_err.base == &PlaceBase::Local(Local::new(1)) && - base.is_none() && + proj_base.is_empty() && !self.upvars.is_empty() { item_msg = format!("`{}`", access_place_desc.unwrap()); debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); @@ -115,7 +106,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ", as `Fn` closures cannot mutate their captured variables".to_string() } } else if { - if let (PlaceBase::Local(local), None) = (&the_place_err.base, base) { + if let (PlaceBase::Local(local), []) = (&the_place_err.base, proj_base) { self.body.local_decls[*local].is_ref_for_guard() } else { false @@ -126,7 +117,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { let source = self.borrowed_content_source(PlaceRef { base: the_place_err.base, - projection: base, + projection: proj_base, }); let pointer_type = source.describe_for_immutable_place(); opt_source = Some(source); @@ -149,23 +140,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), - projection: None, + projection: [], } => unreachable!(), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), - projection: None, + projection: [], } => { if let Place { base: PlaceBase::Static(_), - projection: None, + projection: box [], } = access_place { item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); reason = String::new(); @@ -178,33 +170,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: _, - projection: - Some(box Projection { - base: _, - elem: ProjectionElem::Index(_), - }), + projection: [.., ProjectionElem::Index(_)], } | PlaceRef { base: _, - projection: - Some(box Projection { - base: _, - elem: ProjectionElem::ConstantIndex { .. }, - }), + projection: [.., ProjectionElem::ConstantIndex { .. }], } | PlaceRef { base: _, - projection: Some(box Projection { - base: _, - elem: ProjectionElem::Subslice { .. }, - }), + projection: [.., ProjectionElem::Subslice { .. }], } | PlaceRef { base: _, - projection: Some(box Projection { - base: _, - elem: ProjectionElem::Downcast(..), - }), + projection: [.., ProjectionElem::Downcast(..)], } => bug!("Unexpected immutable place."), } @@ -262,22 +240,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // after the field access). PlaceRef { base, - projection: Some(box Projection { - base: Some(box Projection { - base: Some(box Projection { - base: base_proj, - elem: ProjectionElem::Deref, - }), - elem: ProjectionElem::Field(field, _), - }), - elem: ProjectionElem::Deref, - }), + projection: [proj_base @ .., + ProjectionElem::Deref, + ProjectionElem::Field(field, _), + ProjectionElem::Deref, + ], } => { err.span_label(span, format!("cannot {ACT}", ACT = act)); if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(&base, &base_proj, self.body, self.infcx.tcx).ty, + Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -292,7 +265,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Suggest removing a `&mut` from the use of a mutable reference. PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } if { self.body.local_decls.get(*local).map(|local_decl| { if let ClearCrossCrate::Set( @@ -328,7 +301,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // variable) mutations... PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } if self.body.local_decls[*local].can_be_made_mutable() => { // ... but it doesn't make sense to suggest it on // variables that are `ref x`, `ref mut x`, `&self`, @@ -349,13 +322,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Also suggest adding mut for upvars PlaceRef { base, - projection: Some(box Projection { - base: proj_base, - elem: ProjectionElem::Field(upvar_index, _), - }), + projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&base, &proj_base, self.body, self.infcx.tcx).ty + Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -385,7 +355,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // a local variable, then just suggest the user remove it. PlaceRef { base: PlaceBase::Local(_), - projection: None, + projection: [], } if { if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { snippet.starts_with("&mut ") @@ -400,10 +370,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: [ProjectionElem::Deref], } if { if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) = self.body.local_decls[*local].is_user_variable @@ -427,10 +394,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // arbitrary base for the projection? PlaceRef { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: [ProjectionElem::Deref], } if self.body.local_decls[*local].is_user_variable.is_some() => { let local_decl = &self.body.local_decls[*local]; @@ -510,10 +474,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base, - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: [ProjectionElem::Deref], // FIXME document what is this 1 magic number about } if *base == PlaceBase::Local(Local::new(1)) && !self.upvars.is_empty() => @@ -527,10 +488,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: _, - projection: Some(box Projection { - base: _, - elem: ProjectionElem::Deref, - }), + projection: [.., ProjectionElem::Deref], } => { err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -711,10 +669,10 @@ fn annotate_struct_field( } /// If possible, suggest replacing `ref` with `ref mut`. -fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> { - let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap(); +fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option { + let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?; if hi_src.starts_with("ref") - && hi_src["ref".len()..].starts_with(Pattern_White_Space) + && hi_src["ref".len()..].starts_with(rustc_lexer::is_whitespace) { let replacement = format!("ref mut{}", &hi_src["ref".len()..]); Some(replacement) diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 5c230913a0..1e5f613aed 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -8,9 +8,8 @@ use rustc::infer::InferCtxt; use rustc::mir::visit::TyContext; use rustc::mir::visit::Visitor; use rustc::mir::{ - BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, Projection, - ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, - UserTypeProjection, + BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, ProjectionElem, Rvalue, + SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty}; @@ -229,14 +228,11 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { match place { Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } | Place { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }), + projection: box [ProjectionElem::Deref], } => { debug!( "Recording `killed` facts for borrows of local={:?} at location={:?}", @@ -261,7 +257,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { Place { base: PlaceBase::Local(local), - projection: Some(_), + projection: box [.., _], } => { // Kill conflicting borrows of the innermost local. debug!( diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index aba3ef1cbb..3ba8d7044b 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -274,7 +274,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { if let Place { base: PlaceBase::Local(borrowed_local), - projection: None, + projection: box [], } = place { if body.local_decls[*borrowed_local].name.is_some() && local != *borrowed_local @@ -457,7 +457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// True if an edge `source -> target` is a backedge -- in other words, if the target /// dominates the source. fn is_back_edge(&self, source: Location, target: Location) -> bool { - target.dominates(source, &self.body.dominators()) + target.dominates(source, &self.dominators) } /// Determine how the borrow was later used. @@ -495,11 +495,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Operand::Constant(c) => c.span, Operand::Copy(Place { base: PlaceBase::Local(l), - projection: None, + projection: box [], }) | Operand::Move(Place { base: PlaceBase::Local(l), - projection: None, + projection: box [], }) => { let local_decl = &self.body.local_decls[*l]; if local_decl.name.is_none() { @@ -541,10 +541,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // it which simplifies the termination logic. let mut queue = vec![location]; let mut target = if let Some(&Statement { - kind: StatementKind::Assign(Place { + kind: StatementKind::Assign(box(Place { base: PlaceBase::Local(local), - projection: None, - }, _), + projection: box [], + }, _)), .. }) = stmt { @@ -567,7 +567,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("was_captured_by_trait_object: stmt={:?}", stmt); // The only kind of statement that we care about is assignments... - if let StatementKind::Assign(place, box rvalue) = &stmt.kind { + if let StatementKind::Assign(box(place, rvalue)) = &stmt.kind { let into = match place.local_or_deref_local() { Some(into) => into, None => { @@ -583,11 +583,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::Use(operand) => match operand { Operand::Copy(Place { base: PlaceBase::Local(from), - projection: None, + projection: box [], }) | Operand::Move(Place { base: PlaceBase::Local(from), - projection: None, + projection: box [], }) if *from == target => { @@ -602,11 +602,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) => match operand { Operand::Copy(Place { base: PlaceBase::Local(from), - projection: None, + projection: box [], }) | Operand::Move(Place { base: PlaceBase::Local(from), - projection: None, + projection: box [], }) if *from == target => { @@ -639,7 +639,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let TerminatorKind::Call { destination: Some((Place { base: PlaceBase::Local(dest), - projection: None, + projection: box [], }, block)), args, .. @@ -653,7 +653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let found_target = args.iter().any(|arg| { if let Operand::Move(Place { base: PlaceBase::Local(potential), - projection: None, + projection: box [], }) = arg { *potential == target } else { diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 05451cdfb8..f0beb4d3ae 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -1,5 +1,5 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; -use crate::dataflow::indexes::BorrowIndex; +use crate::dataflow::indexes::{BorrowIndex, MovePathIndex}; use polonius_engine::AllFacts as PoloniusAllFacts; use polonius_engine::Atom; use rustc::mir::Local; @@ -11,7 +11,7 @@ use std::fs::{self, File}; use std::io::Write; use std::path::Path; -crate type AllFacts = PoloniusAllFacts; +crate type AllFacts = PoloniusAllFacts; crate trait AllFactsExt { /// Returns `true` if there is a need to gather `AllFacts` given the @@ -58,14 +58,17 @@ impl AllFactsExt for AllFacts { cfg_edge, killed, outlives, - region_live_at, invalidates, var_used, var_defined, var_drop_used, var_uses_region, var_drops_region, - var_initialized_on_exit, + child, + path_belongs_to_var, + initialized_at, + moved_out_at, + path_accessed_at, ]) } Ok(()) @@ -84,6 +87,12 @@ impl Atom for LocationIndex { } } +impl Atom for MovePathIndex { + fn index(self) -> usize { + Idx::index(self) + } +} + struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 71106af767..1d429e3a6d 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -66,7 +66,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.check_activations(location); match statement.kind { - StatementKind::Assign(ref lhs, ref rhs) => { + StatementKind::Assign(box(ref lhs, ref rhs)) => { self.consume_rvalue( location, rhs, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index d65cdde303..1ff3228afa 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -4,15 +4,17 @@ use crate::borrow_check::nll::facts::AllFactsExt; use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; use crate::borrow_check::nll::region_infer::values::RegionValueElements; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::MoveData; +use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind}; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, + Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::fmt::Debug; use std::env; @@ -52,6 +54,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, + promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -59,7 +62,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body); + renumber::renumber_mir(infcx, body, promoted); let source = MirSource::item(def_id); mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); @@ -67,6 +70,85 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( universal_regions } + +// This function populates an AllFacts instance with base facts related to +// MovePaths and needed for the move analysis. +fn populate_polonius_move_facts( + all_facts: &mut AllFacts, + move_data: &MoveData<'_>, + location_table: &LocationTable, + body: &Body<'_>) { + all_facts + .path_belongs_to_var + .extend( + move_data + .rev_lookup + .iter_locals_enumerated() + .map(|(v, &m)| (m, v))); + + for (child, move_path) in move_data.move_paths.iter_enumerated() { + all_facts + .child + .extend( + move_path + .parents(&move_data.move_paths) + .iter() + .map(|&parent| (child, parent))); + } + + // initialized_at + for init in move_data.inits.iter() { + + match init.location { + InitLocation::Statement(location) => { + let block_data = &body[location.block]; + let is_terminator = location.statement_index == block_data.statements.len(); + + if is_terminator && init.kind == InitKind::NonPanicPathOnly { + // We are at the terminator of an init that has a panic path, + // and where the init should not happen on panic + + for &successor in block_data.terminator().successors() { + if body[successor].is_cleanup { + continue; + } + + // The initialization happened in (or rather, when arriving at) + // the successors, but not in the unwind block. + let first_statement = Location { block: successor, statement_index: 0}; + all_facts + .initialized_at + .push((init.path, location_table.start_index(first_statement))); + } + + } else { + // In all other cases, the initialization just happens at the + // midpoint, like any other effect. + all_facts.initialized_at.push((init.path, location_table.mid_index(location))); + } + }, + // Arguments are initialized on function entry + InitLocation::Argument(local) => { + assert!(body.local_kind(local) == LocalKind::Arg); + let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 }; + all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry))); + + } + } + } + + + // moved_out_at + // deinitialisation is assumed to always happen! + all_facts + .moved_out_at + .extend( + move_data + .moves + .iter() + .map(|mo| (mo.path, location_table.mid_index(mo.source)))); +} + /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. @@ -75,6 +157,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, @@ -84,7 +167,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( errors_buffer: &mut Vec, ) -> ( RegionInferenceContext<'tcx>, - Option>>, + Option>>, Option>, ) { let mut all_facts = if AllFacts::enabled(infcx.tcx) { @@ -105,6 +188,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx, param_env, body, + promoted, def_id, &universal_regions, location_table, @@ -119,6 +203,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); + populate_polonius_move_facts(all_facts, move_data, location_table, body); } // Create the region inference context, taking ownership of the diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index efa18587b7..26a89b4e7a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -13,7 +13,7 @@ use rustc::infer::NLLRegionVariableOrigin; use rustc::mir::{ConstraintCategory, Location, Body}; use rustc::ty::{self, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_errors::{Diagnostic, DiagnosticBuilder}; +use rustc_errors::DiagnosticBuilder; use std::collections::VecDeque; use syntax::errors::Applicability; use syntax::symbol::kw; @@ -22,7 +22,7 @@ use syntax_pos::Span; mod region_name; mod var_name; -crate use self::region_name::{RegionName, RegionNameSource}; +crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx}; impl ConstraintDescription for ConstraintCategory { fn description(&self) -> &'static str { @@ -54,6 +54,39 @@ enum Trace { NotVisited, } +/// Various pieces of state used when reporting borrow checker errors. +pub struct ErrorReportingCtx<'a, 'b, 'tcx> { + /// The region inference context used for borrow chekcing this MIR body. + #[allow(dead_code)] // FIXME(mark-i-m): used by outlives suggestions + region_infcx: &'b RegionInferenceContext<'tcx>, + + /// The inference context used for type checking. + infcx: &'b InferCtxt<'a, 'tcx>, + + /// The MIR def we are reporting errors on. + mir_def_id: DefId, + + /// The MIR body we are reporting errors on (for convenience). + body: &'b Body<'tcx>, + + /// Any upvars for the MIR body we have kept track of during borrow checking. + upvars: &'b [Upvar], +} + +/// Information about the various region constraints involved in a borrow checker error. +#[derive(Clone, Debug)] +pub struct ErrorConstraintInfo { + // fr: outlived_fr + fr: RegionVid, + fr_is_local: bool, + outlived_fr: RegionVid, + outlived_fr_is_local: bool, + + // Category and span for best blame constraint + category: ConstraintCategory, + span: Span, +} + impl<'tcx> RegionInferenceContext<'tcx> { /// Tries to find the best constraint to blame for the fact that /// `R: from_region`, where `R` is some region that meets @@ -257,16 +290,16 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`. - pub(super) fn report_error( - &self, + pub(super) fn report_error<'a>( + &'a self, body: &Body<'tcx>, upvars: &[Upvar], - infcx: &InferCtxt<'_, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, fr: RegionVid, outlived_fr: RegionVid, - errors_buffer: &mut Vec, - ) { + renctx: &mut RegionErrorNamingCtx, + ) -> DiagnosticBuilder<'a> { debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); let (category, _, span) = self.best_blame_constraint(body, fr, |r| { @@ -279,8 +312,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let tables = infcx.tcx.typeck_tables_of(mir_def_id); let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables)); if let Some(diag) = nice.try_report_from_nll() { - diag.buffer(errors_buffer); - return; + return diag; } } @@ -293,45 +325,28 @@ impl<'tcx> RegionInferenceContext<'tcx> { "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}", fr_is_local, outlived_fr_is_local, category ); + + let errctx = ErrorReportingCtx { + region_infcx: self, + infcx, + mir_def_id, + body, + upvars, + }; + + let errci = ErrorConstraintInfo { + fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span + }; + match (category, fr_is_local, outlived_fr_is_local) { (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => { - self.report_fnmut_error( - body, - upvars, - infcx, - mir_def_id, - fr, - outlived_fr, - span, - errors_buffer, - ) + self.report_fnmut_error(&errctx, &errci, renctx) } (ConstraintCategory::Assignment, true, false) - | (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error( - body, - upvars, - infcx, - mir_def_id, - fr, - outlived_fr, - category, - span, - errors_buffer, - ), - _ => self.report_general_error( - body, - upvars, - infcx, - mir_def_id, - fr, - fr_is_local, - outlived_fr, - outlived_fr_is_local, - category, - span, - errors_buffer, - ), - }; + | (ConstraintCategory::CallArgument, true, false) => + self.report_escaping_data_error(&errctx, &errci, renctx), + _ => self.report_general_error(&errctx, &errci, renctx), + } } /// We have a constraint `fr1: fr2` that is not satisfied, where @@ -379,19 +394,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn report_fnmut_error( &self, - body: &Body<'tcx>, - upvars: &[Upvar], - infcx: &InferCtxt<'_, 'tcx>, - mir_def_id: DefId, - _fr: RegionVid, - outlived_fr: RegionVid, - span: Span, - errors_buffer: &mut Vec, - ) { - let mut diag = infcx + errctx: &ErrorReportingCtx<'_, '_, 'tcx>, + errci: &ErrorConstraintInfo, + renctx: &mut RegionErrorNamingCtx, + ) -> DiagnosticBuilder<'_> { + let ErrorConstraintInfo { + outlived_fr, span, .. + } = errci; + + let mut diag = errctx + .infcx .tcx .sess - .struct_span_err(span, "captured variable cannot escape `FnMut` closure body"); + .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body"); // We should check if the return type of this closure is in fact a closure - in that // case, we can special case the error further. @@ -403,11 +418,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { "returns a reference to a captured variable which escapes the closure body" }; - diag.span_label(span, message); + diag.span_label(*span, message); - match self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, &mut 1) - .unwrap().source - { + match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source { RegionNameSource::NamedEarlyBoundRegion(fr_span) | RegionNameSource::NamedFreeRegion(fr_span) | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) @@ -427,7 +440,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); diag.note("...therefore, they cannot allow references to captured variables to escape"); - diag.buffer(errors_buffer); + diag } /// Reports a error specifically for when data is escaping a closure. @@ -444,20 +457,22 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn report_escaping_data_error( &self, - body: &Body<'tcx>, - upvars: &[Upvar], - infcx: &InferCtxt<'_, 'tcx>, - mir_def_id: DefId, - fr: RegionVid, - outlived_fr: RegionVid, - category: ConstraintCategory, - span: Span, - errors_buffer: &mut Vec, - ) { + errctx: &ErrorReportingCtx<'_, '_, 'tcx>, + errci: &ErrorConstraintInfo, + renctx: &mut RegionErrorNamingCtx, + ) -> DiagnosticBuilder<'_> { + let ErrorReportingCtx { + infcx, body, upvars, .. + } = errctx; + + let ErrorConstraintInfo { + span, category, .. + } = errci; + let fr_name_and_span = - self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, fr); + self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.fr); let outlived_fr_name_and_span = - self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, outlived_fr); + self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.outlived_fr); let escapes_from = match self.universal_regions.defining_ty { DefiningTy::Closure(..) => "closure", @@ -469,27 +484,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Revert to the normal error in these cases. // Assignments aren't "escapes" in function items. if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) - || (category == ConstraintCategory::Assignment && escapes_from == "function") + || (*category == ConstraintCategory::Assignment && escapes_from == "function") || escapes_from == "const" { return self.report_general_error( - body, - upvars, - infcx, - mir_def_id, - fr, - true, - outlived_fr, - false, - category, - span, - errors_buffer, + errctx, + &ErrorConstraintInfo { + fr_is_local: true, + outlived_fr_is_local: false, + .. *errci + }, + renctx, ); } let mut diag = borrowck_errors::borrowed_data_escapes_closure( infcx.tcx, - span, + *span, escapes_from, ); @@ -513,12 +524,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); diag.span_label( - span, + *span, format!("`{}` escapes the {} body here", fr_name, escapes_from), ); } - diag.buffer(errors_buffer); + diag } /// Reports a region inference error for the general case with named/synthesized lifetimes to @@ -538,41 +549,37 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn report_general_error( &self, - body: &Body<'tcx>, - upvars: &[Upvar], - infcx: &InferCtxt<'_, 'tcx>, - mir_def_id: DefId, - fr: RegionVid, - fr_is_local: bool, - outlived_fr: RegionVid, - outlived_fr_is_local: bool, - category: ConstraintCategory, - span: Span, - errors_buffer: &mut Vec, - ) { + errctx: &ErrorReportingCtx<'_, '_, 'tcx>, + errci: &ErrorConstraintInfo, + renctx: &mut RegionErrorNamingCtx, + ) -> DiagnosticBuilder<'_> { + let ErrorReportingCtx { + infcx, mir_def_id, .. + } = errctx; + let ErrorConstraintInfo { + fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, .. + } = errci; + let mut diag = infcx.tcx.sess.struct_span_err( - span, + *span, "lifetime may not live long enough" ); - let counter = &mut 1; - let fr_name = self.give_region_a_name( - infcx, body, upvars, mir_def_id, fr, counter).unwrap(); - fr_name.highlight_region_name(&mut diag); - let outlived_fr_name = - self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, counter).unwrap(); - outlived_fr_name.highlight_region_name(&mut diag); - - let mir_def_name = if infcx.tcx.is_closure(mir_def_id) { + let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) { "closure" } else { "function" }; + let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap(); + fr_name.highlight_region_name(&mut diag); + let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap(); + outlived_fr_name.highlight_region_name(&mut diag); + match (category, outlived_fr_is_local, fr_is_local) { (ConstraintCategory::Return, true, _) => { diag.span_label( - span, + *span, format!( "{} was supposed to return data with lifetime `{}` but it is returning \ data with lifetime `{}`", @@ -582,7 +589,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } _ => { diag.span_label( - span, + *span, format!( "{}requires that `{}` must outlive `{}`", category.description(), @@ -593,9 +600,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - self.add_static_impl_trait_suggestion(infcx, &mut diag, fr, fr_name, outlived_fr); + self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr); - diag.buffer(errors_buffer); + diag } /// Adds a suggestion to errors where a `impl Trait` is returned. @@ -704,8 +711,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { borrow_region, |r| self.provides_universal_region(r, borrow_region, outlived_region) ); - let outlived_fr_name = - self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_region, &mut 1); + + let mut renctx = RegionErrorNamingCtx::new(); + let errctx = ErrorReportingCtx { + infcx, body, upvars, mir_def_id, + region_infcx: self, + }; + let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region); + (category, from_closure, span, outlived_fr_name) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 3f5b2f4bce..6fa9426910 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -1,5 +1,9 @@ use std::fmt::{self, Display}; -use crate::borrow_check::nll::region_infer::RegionInferenceContext; + +use crate::borrow_check::nll::region_infer::{ + RegionInferenceContext, + error_reporting::ErrorReportingCtx, +}; use crate::borrow_check::nll::universal_regions::DefiningTy; use crate::borrow_check::nll::ToRegionVid; use crate::borrow_check::Upvar; @@ -13,29 +17,75 @@ use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::symbol::kw; -use syntax_pos::Span; -use syntax_pos::symbol::InternedString; +use rustc_data_structures::fx::FxHashMap; +use syntax_pos::{Span, symbol::InternedString}; -#[derive(Debug)] +/// A name for a particular region used in emitting diagnostics. This name could be a generated +/// name like `'1`, a name used by the user like `'a`, or a name like `'static`. +#[derive(Debug, Clone)] crate struct RegionName { + /// The name of the region (interned). crate name: InternedString, + /// Where the region comes from. crate source: RegionNameSource, } -#[derive(Debug)] +/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that +/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`. +/// This helps to print the right kinds of diagnostics. +#[derive(Debug, Clone)] crate enum RegionNameSource { + /// A bound (not free) region that was substituted at the def site (not an HRTB). NamedEarlyBoundRegion(Span), + /// A free region that the user has a name (`'a`) for. NamedFreeRegion(Span), + /// The `'static` region. Static, + /// The free region corresponding to the environment of a closure. SynthesizedFreeEnvRegion(Span, String), + /// The region name corresponds to a region where the type annotation is completely missing + /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. CannotMatchHirTy(Span, String), + /// The region name corresponds a reference that was found by traversing the type in the HIR. MatchedHirTy(Span), + /// A region name from the generics list of a struct/enum/union. MatchedAdtAndSegment(Span), + /// The region corresponding to a closure upvar. AnonRegionFromUpvar(Span, String), + /// The region corresponding to the return type of a closure. AnonRegionFromOutput(Span, String, String), AnonRegionFromYieldTy(Span, String), } +/// Records region names that have been assigned before so that we can use the same ones in later +/// diagnostics. +#[derive(Debug, Clone)] +crate struct RegionErrorNamingCtx { + /// Record the region names generated for each region in the given + /// MIR def so that we can reuse them later in help/error messages. + renctx: FxHashMap, + + /// The counter for generating new region names. + counter: usize, +} + +impl RegionErrorNamingCtx { + crate fn new() -> Self { + Self { + counter: 1, + renctx: FxHashMap::default(), + } + } + + crate fn get(&self, region: &RegionVid) -> Option<&RegionName> { + self.renctx.get(region) + } + + crate fn insert(&mut self, region: RegionVid, name: RegionName) { + self.renctx.insert(region, name); + } +} + impl RegionName { #[allow(dead_code)] crate fn was_named(&self) -> bool { @@ -63,43 +113,40 @@ impl RegionName { self.name } - crate fn highlight_region_name( - &self, - diag: &mut DiagnosticBuilder<'_> - ) { + crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) { match &self.source { - RegionNameSource::NamedFreeRegion(span) | - RegionNameSource::NamedEarlyBoundRegion(span) => { - diag.span_label( - *span, - format!("lifetime `{}` defined here", self), - ); - }, + RegionNameSource::NamedFreeRegion(span) + | RegionNameSource::NamedEarlyBoundRegion(span) => { + diag.span_label(*span, format!("lifetime `{}` defined here", self)); + } RegionNameSource::SynthesizedFreeEnvRegion(span, note) => { diag.span_label( *span, format!("lifetime `{}` represents this closure's body", self), ); diag.note(¬e); - }, + } RegionNameSource::CannotMatchHirTy(span, type_name) => { diag.span_label(*span, format!("has type `{}`", type_name)); - }, + } RegionNameSource::MatchedHirTy(span) => { diag.span_label( *span, format!("let's call the lifetime of this reference `{}`", self), ); - }, + } RegionNameSource::MatchedAdtAndSegment(span) => { diag.span_label(*span, format!("let's call this `{}`", self)); - }, + } RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => { diag.span_label( *span, - format!("lifetime `{}` appears in the type of `{}`", self, upvar_name), + format!( + "lifetime `{}` appears in the type of `{}`", + self, upvar_name + ), ); - }, + } RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => { diag.span_label( *span, @@ -151,39 +198,49 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// and then return the name `'1` for us to use. crate fn give_region_a_name( &self, - infcx: &InferCtxt<'_, 'tcx>, - body: &Body<'tcx>, - upvars: &[Upvar], - mir_def_id: DefId, + errctx: &ErrorReportingCtx<'_, '_, 'tcx>, + renctx: &mut RegionErrorNamingCtx, fr: RegionVid, - counter: &mut usize, ) -> Option { - debug!("give_region_a_name(fr={:?}, counter={})", fr, counter); + let ErrorReportingCtx { + infcx, body, mir_def_id, upvars, .. + } = errctx; + + debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter); assert!(self.universal_regions.is_universal_region(fr)); - let value = self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter) + if let Some(value) = renctx.get(&fr) { + return Some(value.clone()); + } + + let value = self + .give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx) .or_else(|| { self.give_name_if_anonymous_region_appears_in_arguments( - infcx, body, mir_def_id, fr, counter, + infcx, body, *mir_def_id, fr, renctx, ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_upvars( - infcx.tcx, upvars, fr, counter, + infcx.tcx, upvars, fr, renctx ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_output( - infcx, body, mir_def_id, fr, counter, + infcx, body, *mir_def_id, fr, renctx, ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_yield_ty( - infcx, body, mir_def_id, fr, counter, + infcx, body, *mir_def_id, fr, renctx, ) }); + if let Some(ref value) = value { + renctx.insert(fr, value.clone()); + } + debug!("give_region_a_name: gave name {:?}", value); value } @@ -197,7 +254,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, mir_def_id: DefId, fr: RegionVid, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let error_region = self.to_error_region(fr)?; @@ -208,7 +265,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let span = self.get_named_span(tcx, error_region, ebr.name); Some(RegionName { name: ebr.name, - source: RegionNameSource::NamedEarlyBoundRegion(span) + source: RegionNameSource::NamedEarlyBoundRegion(span), }) } else { None @@ -227,12 +284,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { name, source: RegionNameSource::NamedFreeRegion(span), }) - }, + } ty::BoundRegion::BrEnv => { - let mir_hir_id = tcx.hir() - .as_local_hir_id(mir_def_id) - .expect("non-local mir"); + let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir"); let def_ty = self.universal_regions.defining_ty; if let DefiningTy::Closure(def_id, substs) = def_ty { @@ -243,7 +298,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } else { bug!("Closure is not defined by a closure expr"); }; - let region_name = self.synthesize_region_name(counter); + let region_name = self.synthesize_region_name(renctx); let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); let note = match closure_kind_ty.to_opt_closure_kind() { @@ -265,7 +320,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { name: region_name, source: RegionNameSource::SynthesizedFreeEnvRegion( args_span, - note.to_string() + note.to_string(), ), }) } else { @@ -335,7 +390,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { body: &Body<'tcx>, mir_def_id: DefId, fr: RegionVid, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?; @@ -349,12 +404,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr, arg_ty, argument_index, - counter, + renctx, ) { return Some(region_name); } - self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, counter) + self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, renctx) } fn give_name_if_we_can_match_hir_ty_from_argument( @@ -365,7 +420,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_index: usize, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?; let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?; @@ -379,7 +434,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { body, needle_fr, argument_ty, - counter, + renctx, ), _ => self.give_name_if_we_can_match_hir_ty( @@ -387,7 +442,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { needle_fr, argument_ty, argument_hir_ty, - counter, + renctx, ), } } @@ -409,11 +464,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { body: &Body<'tcx>, needle_fr: RegionVid, argument_ty: Ty<'tcx>, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { + let counter = renctx.counter; let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(needle_fr, *counter); - let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)); + highlight.highlighting_region_vid(needle_fr, counter); + let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0; debug!( "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -428,7 +484,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // This counter value will already have been used, so this function will increment // it so the next value will be used next and return the region name that would // have been used. - name: self.synthesize_region_name(counter), + name: self.synthesize_region_name(renctx), source: RegionNameSource::CannotMatchHirTy(span, type_name), }) } else { @@ -455,7 +511,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// type. Once we find that, we can use the span of the `hir::Ty` /// to add the highlight. /// - /// This is a somewhat imperfect process, so long the way we also + /// This is a somewhat imperfect process, so along the way we also /// keep track of the **closest** type we've found. If we fail to /// find the exact `&` or `'_` to highlight, then we may fall back /// to highlighting that closest type instead. @@ -465,7 +521,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_hir_ty: &hir::Ty, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut vec![(argument_ty, argument_hir_ty)]; @@ -483,7 +539,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { hir::TyKind::Rptr(_lifetime, referent_hir_ty), ) => { if region.to_region_vid() == needle_fr { - let region_name = self.synthesize_region_name(counter); + let region_name = self.synthesize_region_name(renctx); // Just grab the first character, the `&`. let source_map = tcx.sess.source_map(); @@ -515,7 +571,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { substs, needle_fr, last_segment, - counter, + renctx, search_stack, ) { return Some(name); @@ -559,18 +615,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { substs: SubstsRef<'tcx>, needle_fr: RegionVid, last_segment: &'hir hir::PathSegment, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>, ) -> Option { // Did the user give explicit arguments? (e.g., `Foo<..>`) let args = last_segment.args.as_ref()?; - let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; + let lifetime = + self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; match lifetime.name { hir::LifetimeName::Param(_) | hir::LifetimeName::Error | hir::LifetimeName::Static | hir::LifetimeName::Underscore => { - let region_name = self.synthesize_region_name(counter); + let region_name = self.synthesize_region_name(renctx); let ampersand_span = lifetime.span; Some(RegionName { name: region_name, @@ -578,7 +635,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } - hir::LifetimeName::Implicit => { + hir::LifetimeName::ImplicitObjectLifetimeDefault + | hir::LifetimeName::Implicit => { // In this case, the user left off the lifetime; so // they wrote something like: // @@ -656,12 +714,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, upvars: &[Upvar], fr: RegionVid, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let upvar_index = self.get_upvar_index_for_region(tcx, fr)?; let (upvar_name, upvar_span) = self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index); - let region_name = self.synthesize_region_name(counter); + let region_name = self.synthesize_region_name(renctx); Some(RegionName { name: region_name, @@ -679,7 +737,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { body: &Body<'tcx>, mir_def_id: DefId, fr: RegionVid, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { let tcx = infcx.tcx; @@ -693,8 +751,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(fr, *counter); - let type_name = infcx.extract_type_name(&return_ty, Some(highlight)); + highlight.highlighting_region_vid(fr, renctx.counter); + let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0; let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir"); @@ -724,11 +782,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { // This counter value will already have been used, so this function will increment it // so the next value will be used next and return the region name that would have been // used. - name: self.synthesize_region_name(counter), + name: self.synthesize_region_name(renctx), source: RegionNameSource::AnonRegionFromOutput( return_span, mir_description.to_string(), - type_name + type_name, ), }) } @@ -739,7 +797,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { body: &Body<'tcx>, mir_def_id: DefId, fr: RegionVid, - counter: &mut usize, + renctx: &mut RegionErrorNamingCtx, ) -> Option { // Note: generators from `async fn` yield `()`, so we don't have to // worry about them here. @@ -756,8 +814,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(fr, *counter); - let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)); + highlight.highlighting_region_vid(fr, renctx.counter); + let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0; let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir"); @@ -779,16 +837,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); Some(RegionName { - name: self.synthesize_region_name(counter), + name: self.synthesize_region_name(renctx), source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), }) } - /// Creates a synthetic region named `'1`, incrementing the - /// counter. - fn synthesize_region_name(&self, counter: &mut usize) -> InternedString { - let c = *counter; - *counter += 1; + /// Creates a synthetic region named `'1`, incrementing the counter. + fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString { + let c = renctx.counter; + renctx.counter += 1; InternedString::intern(&format!("'{:?}", c)) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 40388722bc..78e7943598 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1,15 +1,20 @@ -use super::universal_regions::UniversalRegions; -use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph; -use crate::borrow_check::nll::constraints::{ - ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet, -}; -use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}; -use crate::borrow_check::nll::region_infer::values::{ - PlaceholderIndices, RegionElement, ToElementIndex, +use std::rc::Rc; + +use crate::borrow_check::nll::{ + constraints::{ + graph::NormalConstraintGraph, + ConstraintSccIndex, + OutlivesConstraint, + OutlivesConstraintSet, + }, + member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, + region_infer::values::{ + PlaceholderIndices, RegionElement, ToElementIndex + }, + type_check::{free_region_relations::UniversalRegionRelations, Locations}, }; -use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations; -use crate::borrow_check::nll::type_check::Locations; use crate::borrow_check::Upvar; + use rustc::hir::def_id::DefId; use rustc::infer::canonical::QueryOutlivesConstraint; use rustc::infer::opaque_types; @@ -31,16 +36,16 @@ use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{Diagnostic, DiagnosticBuilder}; use syntax_pos::Span; -use std::rc::Rc; +crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx}; +use self::values::{LivenessValues, RegionValueElements, RegionValues}; +use super::universal_regions::UniversalRegions; +use super::ToRegionVid; mod dump_mir; mod error_reporting; -crate use self::error_reporting::{RegionName, RegionNameSource}; mod graphviz; -pub mod values; -use self::values::{LivenessValues, RegionValueElements, RegionValues}; -use super::ToRegionVid; +pub mod values; pub struct RegionInferenceContext<'tcx> { /// Contains the definition for every region variable. Region @@ -487,6 +492,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { errors_buffer, ); + // If we produce any errors, we keep track of the names of all regions, so that we can use + // the same error names in any suggestions we produce. Note that we need names to be unique + // across different errors for the same MIR def so that we can make suggestions that fix + // multiple problems. + let mut region_naming = RegionErrorNamingCtx::new(); + self.check_universal_regions( infcx, body, @@ -494,6 +505,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id, outlives_requirements.as_mut(), errors_buffer, + &mut region_naming, ); self.check_member_constraints(infcx, mir_def_id, errors_buffer); @@ -1312,6 +1324,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id: DefId, mut propagated_outlives_requirements: Option<&mut Vec>>, errors_buffer: &mut Vec, + region_naming: &mut RegionErrorNamingCtx, ) { for (fr, fr_definition) in self.definitions.iter_enumerated() { match fr_definition.origin { @@ -1327,6 +1340,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr, &mut propagated_outlives_requirements, errors_buffer, + region_naming, ); } @@ -1358,6 +1372,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { longer_fr: RegionVid, propagated_outlives_requirements: &mut Option<&mut Vec>>, errors_buffer: &mut Vec, + region_naming: &mut RegionErrorNamingCtx, ) { debug!("check_universal_region(fr={:?})", longer_fr); @@ -1385,6 +1400,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id, propagated_outlives_requirements, errors_buffer, + region_naming, ); return; } @@ -1401,8 +1417,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id, propagated_outlives_requirements, errors_buffer, + region_naming, ) { // continuing to iterate just reports more errors than necessary + // + // FIXME It would also allow us to report more Outlives Suggestions, though, so + // it's not clear that that's a bad thing. Somebody should try commenting out this + // line and see it is actually a regression. return; } } @@ -1418,6 +1439,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir_def_id: DefId, propagated_outlives_requirements: &mut Option<&mut Vec>>, errors_buffer: &mut Vec, + region_naming: &mut RegionErrorNamingCtx, ) -> Option { // If it is known that `fr: o`, carry on. if self.universal_region_relations.outlives(longer_fr, shorter_fr) { @@ -1466,7 +1488,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { // // Note: in this case, we use the unapproximated regions to report the // error. This gives better error messages in some cases. - self.report_error(body, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer); + let db = self.report_error( + body, + upvars, + infcx, + mir_def_id, + longer_fr, + shorter_fr, + region_naming, + ); + + db.buffer(errors_buffer); + Some(ErrorReported) } diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c1d1185cf1..c479c38f30 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,16 +1,26 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{Location, Body}; +use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc_data_structures::indexed_vec::IndexVec; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>) { +pub fn renumber_mir<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + body: &mut Body<'tcx>, + promoted: &mut IndexVec>, +) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; + + for body in promoted.iter_mut() { + visitor.visit_body(body); + } + visitor.visit_body(body); } @@ -44,14 +54,6 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { } impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { - fn visit_body(&mut self, body: &mut Body<'tcx>) { - for promoted in body.promoted.iter_mut() { - self.visit_body(promoted); - } - - self.super_body(body); - } - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 2a066538cc..049d83bb22 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -1,7 +1,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Body}; +use rustc::mir::{Body, Local, Location}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; @@ -72,16 +72,10 @@ impl LocalUseMap { let mut locals_with_use_data: IndexVec = IndexVec::from_elem_n(false, body.local_decls.len()); - live_locals - .iter() - .for_each(|&local| locals_with_use_data[local] = true); - - LocalUseMapBuild { - local_use_map: &mut local_use_map, - elements, - locals_with_use_data, - } - .visit_body(body); + live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); + + LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } + .visit_body(body); local_use_map } @@ -151,10 +145,8 @@ impl LocalUseMapBuild<'_> { location: Location, ) { let point_index = elements.point_from_location(location); - let appearance_index = appearances.push(Appearance { - point_index, - next: *first_appearance, - }); + let appearance_index = + appearances.push(Appearance { point_index, next: *first_appearance }); *first_appearance = Some(appearance_index); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 8970009b6e..3f2ec1ba97 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -58,9 +58,9 @@ pub(super) fn generate<'tcx>( }; if !live_locals.is_empty() { - trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table); + trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); - polonius::populate_var_liveness_facts(typeck, body, location_table); + polonius::populate_access_facts(typeck, body, location_table, move_data); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index 20d7ec55e3..d61464b3f3 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -1,22 +1,28 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; +use crate::dataflow::indexes::MovePathIndex; +use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; -use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location}; +use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::{Body, Local, Location, Place}; use rustc::ty::subst::Kind; use rustc::ty::Ty; use super::TypeChecker; type VarPointRelations = Vec<(Local, LocationIndex)>; +type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>; -struct LivenessPointFactsExtractor<'me> { +struct UseFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, + var_drop_used: &'me mut VarPointRelations, + move_data: &'me MoveData<'me>, + path_accessed_at: &'me mut MovePathPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts -impl LivenessPointFactsExtractor<'_> { +impl UseFactsExtractor<'_> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -30,15 +36,50 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_use()"); self.var_used.push((local, self.location_to_index(location))); } + + fn insert_drop_use(&mut self, local: Local, location: Location) { + debug!("LivenessFactsExtractor::insert_drop_use()"); + self.var_drop_used.push((local, self.location_to_index(location))); + } + + fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { + debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location); + self.path_accessed_at.push((path, self.location_to_index(location))); + } + + fn place_to_mpi(&self, place: &Place<'_>) -> Option { + match self.move_data.rev_lookup.find(place.as_ref()) { + LookupResult::Exact(mpi) => Some(mpi), + LookupResult::Parent(mmpi) => mmpi, + } + } } -impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { +impl Visitor<'tcx> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), Some(DefUse::Use) => self.insert_use(local, location), + Some(DefUse::Drop) => self.insert_drop_use(local, location), + _ => (), + } + } + + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + self.super_place(place, context, location); + match context { + PlaceContext::NonMutatingUse(_) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + + PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } _ => (), - // NOTE: Drop handling is now done in trace() } } } @@ -54,23 +95,27 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty }); } -pub(super) fn populate_var_liveness_facts( +pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - mir: &Body<'tcx>, + body: &Body<'tcx>, location_table: &LocationTable, + move_data: &MoveData<'_>, ) { debug!("populate_var_liveness_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { - LivenessPointFactsExtractor { + UseFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, + var_drop_used: &mut facts.var_drop_used, + path_accessed_at: &mut facts.path_accessed_at, location_table, + move_data, } - .visit_body(mir); + .visit_body(body); } - for (local, local_decl) in mir.local_decls.iter_enumerated() { + for (local, local_decl) in body.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 039ed939ad..9b55881cb1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -1,4 +1,3 @@ -use crate::borrow_check::location::LocationTable; use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements}; use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; use crate::borrow_check::nll::type_check::liveness::polonius; @@ -38,7 +37,6 @@ pub(super) fn trace( flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, live_locals: Vec, - location_table: &LocationTable, ) { debug!("trace()"); @@ -52,7 +50,6 @@ pub(super) fn trace( local_use_map, move_data, drop_data: FxHashMap::default(), - location_table, }; LivenessResults::new(cx).compute_for_all_locals(live_locals); @@ -82,9 +79,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { /// Index indicating where each variable is assigned, used, or /// dropped. local_use_map: &'me LocalUseMap, - - /// Maps between a MIR Location and a LocationIndex - location_table: &'me LocationTable, } struct DropData<'tcx> { @@ -131,12 +125,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for local in live_locals { self.reset_local_state(); self.add_defs_for(local); - - // FIXME: this is temporary until we can generate our own initialization - if self.cx.typeck.borrowck_context.all_facts.is_some() { - self.add_polonius_var_initialized_on_exit_for(local) - } - self.compute_use_live_points_for(local); self.compute_drop_live_points_for(local); @@ -157,63 +145,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None - // - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) { - let move_path = self.cx.move_data.rev_lookup.find_local(local); - let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap(); - for block in self.cx.body.basic_blocks().indices() { - debug!("polonius: generating initialization facts for {:?} in {:?}", local, block); - - // iterate through the block, applying the effects of each statement - // up to and including location, and populate `var_initialized_on_exit` - self.cx.flow_inits.reset_to_entry_of(block); - let start_location = Location { block, statement_index: 0 }; - self.cx.flow_inits.apply_local_effect(start_location); - - for statement_index in 0..self.cx.body[block].statements.len() { - let current_location = Location { block, statement_index }; - - self.cx.flow_inits.reconstruct_statement_effect(current_location); - - // statement has not yet taken effect: - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_initialized_on_exit - .push((local, self.cx.location_table.start_index(current_location))); - } - - // statement has now taken effect - self.cx.flow_inits.apply_local_effect(current_location); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_initialized_on_exit - .push((local, self.cx.location_table.mid_index(current_location))); - } - } - - let terminator_location = self.cx.body.terminator_loc(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_initialized_on_exit - .push((local, self.cx.location_table.start_index(terminator_location))); - } - - // apply the effects of the terminator and push it if needed - self.cx.flow_inits.reset_to_exit_of(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_initialized_on_exit - .push((local, self.cx.location_table.mid_index(terminator_location))); - } - } - } - /// Clear the value of fields that are "per local variable". fn reset_local_state(&mut self) { self.defs.clear(); @@ -273,11 +204,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) { - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - if let Some(facts) = self.cx.typeck.borrowck_context.all_facts { - facts.var_drop_used.push((local, self.cx.location_table.mid_index(location))); - } if self.drop_live_at.insert(drop_point) { self.drop_locations.push(location); self.stack.push(drop_point); @@ -468,13 +394,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { ) { debug!("add_use_live_facts_for(value={:?})", value); - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - value, - live_at, - self.location_table, - ) + Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at) } /// Some variable with type `live_ty` is "drop live" at `location` @@ -525,13 +445,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { // All things in the `outlives` array may be touched by // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - kind, - live_at, - self.location_table, - ); + Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); } @@ -542,7 +456,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeFoldable<'tcx>, live_at: &HybridBitSet, - location_table: &LocationTable, ) { debug!("make_all_regions_live(value={:?})", value); debug!( @@ -559,15 +472,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { .constraints .liveness_constraints .add_elements(live_region_vid, live_at); - - // FIXME: remove this when we can generate our own region-live-at reliably - if let Some(facts) = typeck.borrowck_context.all_facts { - for point in live_at.iter() { - let loc = elements.to_location(point); - facts.region_live_at.push((live_region_vid, location_table.start_index(loc))); - facts.region_live_at.push((live_region_vid, location_table.mid_index(loc))); - } - } }); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 70d6c15d8e..6a764b19c4 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -112,6 +112,7 @@ pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -157,6 +158,7 @@ pub(crate) fn type_check<'tcx>( mir_def_id, param_env, body, + promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, @@ -180,6 +182,7 @@ fn type_check_internal<'a, 'tcx, R>( mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &'a Body<'tcx>, + promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -197,7 +200,7 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body); + let mut verifier = TypeVerifier::new(&mut checker, body, promoted); verifier.visit_body(body); verifier.errors_reported }; @@ -254,6 +257,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, + promoted: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -272,12 +276,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - self.sanitize_constant(constant, location); - self.sanitize_type(constant, constant.ty); + self.sanitize_type(constant, constant.literal.ty); if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( - constant.ty, + constant.literal.ty, ty::Variance::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), @@ -289,7 +292,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { constant, "bad constant user type {:?} vs {:?}: {:?}", annotation, - constant.ty, + constant.literal.ty, terr, ); } @@ -299,7 +302,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { location.to_locations(), ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( - constant.ty, def_id, UserSubsts { substs, user_self_ty: None }, + constant.literal.ty, def_id, UserSubsts { substs, user_self_ty: None }, )), ) { span_mirbug!( @@ -381,9 +384,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>) -> Self { + fn new( + cx: &'a mut TypeChecker<'b, 'tcx>, + body: &'b Body<'tcx>, + promoted: &'b IndexVec>, + ) -> Self { TypeVerifier { body, + promoted, mir_def_id: cx.mir_def_id, cx, last_span: body.span, @@ -403,41 +411,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } } - /// Checks that the constant's `ty` field matches up with what would be - /// expected from its literal. Unevaluated constants and well-formed - /// constraints are checked by `visit_constant`. - fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { - debug!( - "sanitize_constant(constant={:?}, location={:?})", - constant, location - ); - - let literal = constant.literal; - - if let ConstValue::Unevaluated(..) = literal.val { - return; - } - - debug!("sanitize_constant: expected_ty={:?}", literal.ty); - - if let Err(terr) = self.cx.eq_types( - literal.ty, - constant.ty, - location.to_locations(), - ConstraintCategory::Boring, - ) { - span_mirbug!( - self, - constant, - "constant {:?} should have type {:?} but has {:?} ({:?})", - constant, - literal.ty, - constant.ty, - terr, - ); - } - } - /// Checks that the types internal to the `place` match up with /// what would be expected. fn sanitize_place( @@ -448,107 +421,104 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ) -> PlaceTy<'tcx> { debug!("sanitize_place: {:?}", place); - place.iterate(|place_base, place_projection| { - let mut place_ty = match place_base { - PlaceBase::Local(index) => - PlaceTy::from_ty(self.body.local_decls[*index].ty), - PlaceBase::Static(box Static { kind, ty: sty }) => { - let sty = self.sanitize_type(place, sty); - let check_err = - |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, - place: &Place<'tcx>, - ty, - sty| { - if let Err(terr) = verifier.cx.eq_types( - sty, - ty, - location.to_locations(), - ConstraintCategory::Boring, - ) { - span_mirbug!( - verifier, - place, - "bad promoted type ({:?}: {:?}): {:?}", - ty, - sty, - terr - ); - }; + let mut place_ty = match &place.base { + PlaceBase::Local(index) => + PlaceTy::from_ty(self.body.local_decls[*index].ty), + PlaceBase::Static(box Static { kind, ty: sty, def_id }) => { + let sty = self.sanitize_type(place, sty); + let check_err = + |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, + place: &Place<'tcx>, + ty, + sty| { + if let Err(terr) = verifier.cx.eq_types( + sty, + ty, + location.to_locations(), + ConstraintCategory::Boring, + ) { + span_mirbug!( + verifier, + place, + "bad promoted type ({:?}: {:?}): {:?}", + ty, + sty, + terr + ); }; - match kind { - StaticKind::Promoted(promoted) => { - if !self.errors_reported { - let promoted_body = &self.body.promoted[*promoted]; - self.sanitize_promoted(promoted_body, location); - - let promoted_ty = promoted_body.return_ty(); - check_err(self, place, promoted_ty, sty); - } + }; + match kind { + StaticKind::Promoted(promoted, _) => { + if !self.errors_reported { + let promoted_body = &self.promoted[*promoted]; + self.sanitize_promoted(promoted_body, location); + + let promoted_ty = promoted_body.return_ty(); + check_err(self, place, promoted_ty, sty); } - StaticKind::Static(def_id) => { - let ty = self.tcx().type_of(*def_id); - let ty = self.cx.normalize(ty, location); + } + StaticKind::Static => { + let ty = self.tcx().type_of(*def_id); + let ty = self.cx.normalize(ty, location); - check_err(self, place, ty, sty); - } + check_err(self, place, ty, sty); } - PlaceTy::from_ty(sty) } - }; + PlaceTy::from_ty(sty) + } + }; - // FIXME use place_projection.is_empty() when is available - if place.projection.is_none() { - if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { - let is_promoted = match place { - Place { - base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), - .. - }), - projection: None, - } => true, - _ => false, - }; + if place.projection.is_empty() { + if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { + let is_promoted = match place { + Place { + base: PlaceBase::Static(box Static { + kind: StaticKind::Promoted(..), + .. + }), + projection: box [], + } => true, + _ => false, + }; - if !is_promoted { - let tcx = self.tcx(); - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().copy_trait().unwrap(), - substs: tcx.mk_substs_trait(place_ty.ty, &[]), - }; + if !is_promoted { + let tcx = self.tcx(); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty.ty, &[]), + }; - // In order to have a Copy operand, the type T of the - // value must be Copy. Note that we prove that T: Copy, - // rather than using the `is_copy_modulo_regions` - // test. This is important because - // `is_copy_modulo_regions` ignores the resulting region - // obligations and assumes they pass. This can result in - // bounds from Copy impls being unsoundly ignored (e.g., - // #29149). Note that we decide to use Copy before knowing - // whether the bounds fully apply: in effect, the rule is - // that if a value of some type could implement Copy, then - // it must. - self.cx.prove_trait_ref( - trait_ref, - location.to_locations(), - ConstraintCategory::CopyBound, - ); - } + // To have a `Copy` operand, the type `T` of the + // value must be `Copy`. Note that we prove that `T: Copy`, + // rather than using the `is_copy_modulo_regions` + // test. This is important because + // `is_copy_modulo_regions` ignores the resulting region + // obligations and assumes they pass. This can result in + // bounds from `Copy` impls being unsoundly ignored (e.g., + // #29149). Note that we decide to use `Copy` before knowing + // whether the bounds fully apply: in effect, the rule is + // that if a value of some type could implement `Copy`, then + // it must. + self.cx.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::CopyBound, + ); } } + } - for proj in place_projection { - if place_ty.variant_index.is_none() { - if place_ty.ty.references_error() { - assert!(self.errors_reported); - return PlaceTy::from_ty(self.tcx().types.err); - } + for elem in place.projection.iter() { + if place_ty.variant_index.is_none() { + if place_ty.ty.references_error() { + assert!(self.errors_reported); + return PlaceTy::from_ty(self.tcx().types.err); } - place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location) } + place_ty = self.sanitize_projection(place_ty, elem, place, location) + } - place_ty - }) + place_ty } fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) { @@ -1373,7 +1343,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!("check_stmt: {:?}", stmt); let tcx = self.tcx(); match stmt.kind { - StatementKind::Assign(ref place, ref rv) => { + StatementKind::Assign(box(ref place, ref rv)) => { // Assignments to temporaries are not "interesting"; // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting @@ -1381,7 +1351,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let category = match *place { Place { base: PlaceBase::Local(RETURN_PLACE), - projection: None, + projection: box [], } => if let BorrowCheckContext { universal_regions: UniversalRegions { @@ -1400,7 +1370,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }, Place { base: PlaceBase::Local(l), - projection: None, + projection: box [], } if !body.local_decls[l].is_user_variable.is_some() => { ConstraintCategory::Boring } @@ -1480,7 +1450,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); }; } - StatementKind::AscribeUserType(ref place, variance, box ref projection) => { + StatementKind::AscribeUserType(box(ref place, ref projection), variance) => { let place_ty = place.ty(body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, @@ -1687,7 +1657,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let category = match *dest { Place { base: PlaceBase::Local(RETURN_PLACE), - projection: None, + projection: box [], } => { if let BorrowCheckContext { universal_regions: @@ -1709,7 +1679,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Place { base: PlaceBase::Local(l), - projection: None, + projection: box [], } if !body.local_decls[l].is_user_variable.is_some() => { ConstraintCategory::Boring } @@ -2029,6 +1999,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ), &traits::SelectionError::Unimplemented, false, + false, ); } } @@ -2443,19 +2414,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // *p`, where the `p` has type `&'b mut Foo`, for example, we // need to ensure that `'b: 'a`. - let mut borrowed_projection = &borrowed_place.projection; - debug!( "add_reborrow_constraint({:?}, {:?}, {:?})", location, borrow_region, borrowed_place ); - while let Some(box proj) = borrowed_projection { - debug!("add_reborrow_constraint - iteration {:?}", borrowed_projection); - match proj.elem { + let mut cursor = &*borrowed_place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + + debug!("add_reborrow_constraint - iteration {:?}", elem); + + match elem { ProjectionElem::Deref => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&borrowed_place.base, &proj.base, body, tcx).ty; + let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty; debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); match base_ty.sty { @@ -2517,10 +2490,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // other field access } } - - // The "propagate" case. We need to check that our base is valid - // for the borrow's lifetime. - borrowed_projection = &proj.base; } } diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 43a012e149..bac0809081 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict; use crate::borrow_check::AccessDepth; use crate::dataflow::indexes::BorrowIndex; use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase}; -use rustc::mir::{ProjectionElem, BorrowKind}; +use rustc::mir::BorrowKind; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::graph::dominators::Dominators; @@ -133,20 +133,11 @@ pub(super) fn is_active<'tcx>( /// Determines if a given borrow is borrowing local data /// This is called for all Yield statements on movable generators pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool { - place.iterate(|place_base, place_projection| { - match place_base { - PlaceBase::Static(..) => return false, - PlaceBase::Local(..) => {}, - } - - for proj in place_projection { - // Reborrow of already borrowed data is ignored - // Any errors will be caught on the initial borrow - if proj.elem == ProjectionElem::Deref { - return false; - } - } + match place.base { + PlaceBase::Static(_) => false, - true - }) + // Reborrow of already borrowed data is ignored + // Any errors will be caught on the initial borrow + PlaceBase::Local(_) => !place.is_indirect(), + } } diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index 72d5588c34..411fa5b596 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -25,55 +25,54 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { body: &Body<'tcx>, locals_state_at_exit: &LocalsStateAtExit, ) -> bool { - self.iterate(|place_base, place_projection| { - let ignore = match place_base { - // If a local variable is immutable, then we only need to track borrows to guard - // against two kinds of errors: - // * The variable being dropped while still borrowed (e.g., because the fn returns - // a reference to a local variable) - // * The variable being moved while still borrowed - // - // In particular, the variable cannot be mutated -- the "access checks" will fail -- - // so we don't have to worry about mutation while borrowed. - PlaceBase::Local(index) => { - match locals_state_at_exit { - LocalsStateAtExit::AllAreInvalidated => false, - LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => { - let ignore = !has_storage_dead_or_moved.contains(*index) && - body.local_decls[*index].mutability == Mutability::Not; - debug!("ignore_borrow: local {:?} => {:?}", index, ignore); - ignore - } + let ignore = match self.base { + // If a local variable is immutable, then we only need to track borrows to guard + // against two kinds of errors: + // * The variable being dropped while still borrowed (e.g., because the fn returns + // a reference to a local variable) + // * The variable being moved while still borrowed + // + // In particular, the variable cannot be mutated -- the "access checks" will fail -- + // so we don't have to worry about mutation while borrowed. + PlaceBase::Local(index) => { + match locals_state_at_exit { + LocalsStateAtExit::AllAreInvalidated => false, + LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => { + let ignore = !has_storage_dead_or_moved.contains(index) && + body.local_decls[index].mutability == Mutability::Not; + debug!("ignore_borrow: local {:?} => {:?}", index, ignore); + ignore } } - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => - false, - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { - tcx.is_mutable_static(*def_id) - } - }; + } + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => + false, + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { + tcx.is_mutable_static(def_id) + } + }; - for proj in place_projection { - if proj.elem == ProjectionElem::Deref { - let ty = Place::ty_from(place_base, &proj.base, body, tcx).ty; - match ty.sty { - // For both derefs of raw pointers and `&T` - // references, the original path is `Copy` and - // therefore not significant. In particular, - // there is nothing the user can do to the - // original path that would invalidate the - // newly created reference -- and if there - // were, then the user could have copied the - // original path into a new variable and - // borrowed *that* one, leaving the original - // path unborrowed. - ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => return true, - _ => {} - } + for (i, elem) in self.projection.iter().enumerate() { + let proj_base = &self.projection[..i]; + + if *elem == ProjectionElem::Deref { + let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty; + if let ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) = ty.sty { + // For both derefs of raw pointers and `&T` + // references, the original path is `Copy` and + // therefore not significant. In particular, + // there is nothing the user can do to the + // original path that would invalidate the + // newly created reference -- and if there + // were, then the user could have copied the + // original path into a new variable and + // borrowed *that* one, leaving the original + // path unborrowed. + return true; } } + } - ignore - }) + ignore } } diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 4dd2794f11..dafa0b6631 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -3,8 +3,7 @@ use crate::borrow_check::Overlap; use crate::borrow_check::{Deep, Shallow, AccessDepth}; use rustc::hir; use rustc::mir::{ - Body, BorrowKind, Place, PlaceBase, PlaceRef, Projection, ProjectionElem, ProjectionsIter, - StaticKind, + Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem, StaticKind, }; use rustc::ty::{self, TyCtxt}; use std::cmp::max; @@ -67,39 +66,35 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( // it's so common that it's a speed win to check for it first. if let Place { base: PlaceBase::Local(l1), - projection: None, + projection: box [], } = borrow_place { if let PlaceRef { base: PlaceBase::Local(l2), - projection: None, + projection: [], } = access_place { return l1 == l2; } } - borrow_place.iterate(|borrow_base, borrow_projections| { - access_place.iterate(|access_base, access_projections| { - place_components_conflict( - tcx, - param_env, - body, - (borrow_base, borrow_projections), - borrow_kind, - (access_base, access_projections), - access, - bias, - ) - }) - }) + place_components_conflict( + tcx, + param_env, + body, + borrow_place, + borrow_kind, + access_place, + access, + bias, + ) } fn place_components_conflict<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, - borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>), + borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, - access_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>), + access_place: PlaceRef<'_, 'tcx>, access: AccessDepth, bias: PlaceConflictBias, ) -> bool { @@ -145,8 +140,8 @@ fn place_components_conflict<'tcx>( // and either equal or disjoint. // - If we did run out of access, the borrow can access a part of it. - let borrow_base = borrow_projections.0; - let access_base = access_projections.0; + let borrow_base = &borrow_place.base; + let access_base = access_place.base; match place_base_conflict(tcx, param_env, borrow_base, access_base) { Overlap::Arbitrary => { @@ -163,147 +158,157 @@ fn place_components_conflict<'tcx>( } } - let mut borrow_projections = borrow_projections.1; - let mut access_projections = access_projections.1; - - loop { - // loop invariant: borrow_c is always either equal to access_c or disjoint from it. - if let Some(borrow_c) = borrow_projections.next() { - debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c); + // loop invariant: borrow_c is always either equal to access_c or disjoint from it. + for (i, (borrow_c, access_c)) in + borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate() + { + debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c); + let borrow_proj_base = &borrow_place.projection[..i]; - if let Some(access_c) = access_projections.next() { - debug!("borrow_conflicts_with_place: access_c = {:?}", access_c); + debug!("borrow_conflicts_with_place: access_c = {:?}", access_c); - // Borrow and access path both have more components. - // - // Examples: - // - // - borrow of `a.(...)`, access to `a.(...)` - // - borrow of `a.(...)`, access to `b.(...)` - // - // Here we only see the components we have checked so - // far (in our examples, just the first component). We - // check whether the components being borrowed vs - // accessed are disjoint (as in the second example, - // but not the first). - match place_projection_conflict(tcx, body, borrow_base, borrow_c, access_c, bias) { - Overlap::Arbitrary => { - // We have encountered different fields of potentially - // the same union - the borrow now partially overlaps. - // - // There is no *easy* way of comparing the fields - // further on, because they might have different types - // (e.g., borrows of `u.a.0` and `u.b.y` where `.0` and - // `.y` come from different structs). - // - // We could try to do some things here - e.g., count - // dereferences - but that's probably not a good - // idea, at least for now, so just give up and - // report a conflict. This is unsafe code anyway so - // the user could always use raw pointers. - debug!("borrow_conflicts_with_place: arbitrary -> conflict"); - return true; - } - Overlap::EqualOrDisjoint => { - // This is the recursive case - proceed to the next element. - } - Overlap::Disjoint => { - // We have proven the borrow disjoint - further - // projections will remain disjoint. - debug!("borrow_conflicts_with_place: disjoint"); - return false; - } - } - } else { - // Borrow path is longer than the access path. Examples: + // Borrow and access path both have more components. + // + // Examples: + // + // - borrow of `a.(...)`, access to `a.(...)` + // - borrow of `a.(...)`, access to `b.(...)` + // + // Here we only see the components we have checked so + // far (in our examples, just the first component). We + // check whether the components being borrowed vs + // accessed are disjoint (as in the second example, + // but not the first). + match place_projection_conflict( + tcx, + body, + borrow_base, + borrow_proj_base, + borrow_c, + access_c, + bias, + ) { + Overlap::Arbitrary => { + // We have encountered different fields of potentially + // the same union - the borrow now partially overlaps. // - // - borrow of `a.b.c`, access to `a.b` + // There is no *easy* way of comparing the fields + // further on, because they might have different types + // (e.g., borrows of `u.a.0` and `u.b.y` where `.0` and + // `.y` come from different structs). // - // Here, we know that the borrow can access a part of - // our place. This is a conflict if that is a part our - // access cares about. + // We could try to do some things here - e.g., count + // dereferences - but that's probably not a good + // idea, at least for now, so just give up and + // report a conflict. This is unsafe code anyway so + // the user could always use raw pointers. + debug!("borrow_conflicts_with_place: arbitrary -> conflict"); + return true; + } + Overlap::EqualOrDisjoint => { + // This is the recursive case - proceed to the next element. + } + Overlap::Disjoint => { + // We have proven the borrow disjoint - further + // projections will remain disjoint. + debug!("borrow_conflicts_with_place: disjoint"); + return false; + } + } + } + + if borrow_place.projection.len() > access_place.projection.len() { + for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate() + { + // Borrow path is longer than the access path. Examples: + // + // - borrow of `a.b.c`, access to `a.b` + // + // Here, we know that the borrow can access a part of + // our place. This is a conflict if that is a part our + // access cares about. - let base = &borrow_c.base; - let elem = &borrow_c.elem; - let base_ty = Place::ty_from(borrow_base, base, body, tcx).ty; + let proj_base = &borrow_place.projection[..access_place.projection.len() + i]; + let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty; - match (elem, &base_ty.sty, access) { - (_, _, Shallow(Some(ArtificialField::ArrayLength))) - | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { - // The array length is like additional fields on the - // type; it does not overlap any existing data there. - // Furthermore, if cannot actually be a prefix of any - // borrowed place (at least in MIR as it is currently.) - // - // e.g., a (mutable) borrow of `a[5]` while we read the - // array length of `a`. - debug!("borrow_conflicts_with_place: implicit field"); - return false; - } + match (elem, &base_ty.sty, access) { + (_, _, Shallow(Some(ArtificialField::ArrayLength))) + | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { + // The array length is like additional fields on the + // type; it does not overlap any existing data there. + // Furthermore, if cannot actually be a prefix of any + // borrowed place (at least in MIR as it is currently.) + // + // e.g., a (mutable) borrow of `a[5]` while we read the + // array length of `a`. + debug!("borrow_conflicts_with_place: implicit field"); + return false; + } - (ProjectionElem::Deref, _, Shallow(None)) => { - // e.g., a borrow of `*x.y` while we shallowly access `x.y` or some - // prefix thereof - the shallow access can't touch anything behind - // the pointer. - debug!("borrow_conflicts_with_place: shallow access behind ptr"); - return false; - } - (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => { - // Shouldn't be tracked - bug!("Tracking borrow behind shared reference."); - } - (ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => { - // Values behind a mutable reference are not access either by dropping a - // value, or by StorageDead - debug!("borrow_conflicts_with_place: drop access behind ptr"); - return false; - } + (ProjectionElem::Deref, _, Shallow(None)) => { + // e.g., a borrow of `*x.y` while we shallowly access `x.y` or some + // prefix thereof - the shallow access can't touch anything behind + // the pointer. + debug!("borrow_conflicts_with_place: shallow access behind ptr"); + return false; + } + (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => { + // Shouldn't be tracked + bug!("Tracking borrow behind shared reference."); + } + (ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => { + // Values behind a mutable reference are not access either by dropping a + // value, or by StorageDead + debug!("borrow_conflicts_with_place: drop access behind ptr"); + return false; + } - (ProjectionElem::Field { .. }, ty::Adt(def, _), AccessDepth::Drop) => { - // Drop can read/write arbitrary projections, so places - // conflict regardless of further projections. - if def.has_dtor(tcx) { - return true; - } + (ProjectionElem::Field { .. }, ty::Adt(def, _), AccessDepth::Drop) => { + // Drop can read/write arbitrary projections, so places + // conflict regardless of further projections. + if def.has_dtor(tcx) { + return true; } + } - (ProjectionElem::Deref, _, Deep) - | (ProjectionElem::Deref, _, AccessDepth::Drop) - | (ProjectionElem::Field { .. }, _, _) - | (ProjectionElem::Index { .. }, _, _) - | (ProjectionElem::ConstantIndex { .. }, _, _) - | (ProjectionElem::Subslice { .. }, _, _) - | (ProjectionElem::Downcast { .. }, _, _) => { - // Recursive case. This can still be disjoint on a - // further iteration if this a shallow access and - // there's a deref later on, e.g., a borrow - // of `*x.y` while accessing `x`. - } + (ProjectionElem::Deref, _, Deep) + | (ProjectionElem::Deref, _, AccessDepth::Drop) + | (ProjectionElem::Field { .. }, _, _) + | (ProjectionElem::Index { .. }, _, _) + | (ProjectionElem::ConstantIndex { .. }, _, _) + | (ProjectionElem::Subslice { .. }, _, _) + | (ProjectionElem::Downcast { .. }, _, _) => { + // Recursive case. This can still be disjoint on a + // further iteration if this a shallow access and + // there's a deref later on, e.g., a borrow + // of `*x.y` while accessing `x`. } } - } else { - // Borrow path ran out but access path may not - // have. Examples: - // - // - borrow of `a.b`, access to `a.b.c` - // - borrow of `a.b`, access to `a.b` - // - // In the first example, where we didn't run out of - // access, the borrow can access all of our place, so we - // have a conflict. - // - // If the second example, where we did, then we still know - // that the borrow can access a *part* of our place that - // our access cares about, so we still have a conflict. - if borrow_kind == BorrowKind::Shallow && access_projections.next().is_some() { - debug!("borrow_conflicts_with_place: shallow borrow"); - return false; - } else { - debug!("borrow_conflicts_with_place: full borrow, CONFLICT"); - return true; - } } } + + // Borrow path ran out but access path may not + // have. Examples: + // + // - borrow of `a.b`, access to `a.b.c` + // - borrow of `a.b`, access to `a.b` + // + // In the first example, where we didn't run out of + // access, the borrow can access all of our place, so we + // have a conflict. + // + // If the second example, where we did, then we still know + // that the borrow can access a *part* of our place that + // our access cares about, so we still have a conflict. + if borrow_kind == BorrowKind::Shallow + && borrow_place.projection.len() < access_place.projection.len() + { + debug!("borrow_conflicts_with_place: shallow borrow"); + false + } else { + debug!("borrow_conflicts_with_place: full borrow, CONFLICT"); + true + } } // Given that the bases of `elem1` and `elem2` are always either equal @@ -329,11 +334,11 @@ fn place_base_conflict<'tcx>( } (PlaceBase::Static(s1), PlaceBase::Static(s2)) => { match (&s1.kind, &s2.kind) { - (StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => { - if def_id_1 != def_id_2 { + (StaticKind::Static, StaticKind::Static) => { + if s1.def_id != s2.def_id { debug!("place_element_conflict: DISJOINT-STATIC"); Overlap::Disjoint - } else if tcx.is_mutable_static(*def_id_1) { + } else if tcx.is_mutable_static(s1.def_id) { // We ignore mutable statics - they can only be unsafe code. debug!("place_element_conflict: IGNORE-STATIC-MUT"); Overlap::Disjoint @@ -342,7 +347,7 @@ fn place_base_conflict<'tcx>( Overlap::EqualOrDisjoint } }, - (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => { + (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => { if promoted_1 == promoted_2 { if let ty::Array(_, len) = s1.ty.sty { if let Some(0) = len.try_eval_usize(tcx, param_env) { @@ -381,11 +386,12 @@ fn place_projection_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pi1_base: &PlaceBase<'tcx>, - pi1: &Projection<'tcx>, - pi2: &Projection<'tcx>, + pi1_proj_base: &[PlaceElem<'tcx>], + pi1_elem: &PlaceElem<'tcx>, + pi2_elem: &PlaceElem<'tcx>, bias: PlaceConflictBias, ) -> Overlap { - match (&pi1.elem, &pi2.elem) { + match (pi1_elem, pi2_elem) { (ProjectionElem::Deref, ProjectionElem::Deref) => { // derefs (e.g., `*x` vs. `*x`) - recur. debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF"); @@ -397,7 +403,7 @@ fn place_projection_conflict<'tcx>( debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); Overlap::EqualOrDisjoint } else { - let ty = Place::ty_from(pi1_base, &pi1.base, body, tcx).ty; + let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty; match ty.sty { ty::Adt(def, _) if def.is_union() => { // Different fields of a union, we are basically stuck. @@ -493,7 +499,7 @@ fn place_projection_conflict<'tcx>( // element (like -1 in Python) and `min_length` the first. // Therefore, `min_length - offset_from_end` gives the minimal possible // offset from the beginning - if *offset_from_begin >= min_length - offset_from_end { + if *offset_from_begin >= *min_length - *offset_from_end { debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-CONSTANT-INDEX-FE"); Overlap::EqualOrDisjoint } else { @@ -538,8 +544,8 @@ fn place_projection_conflict<'tcx>( | (ProjectionElem::Subslice { .. }, _) | (ProjectionElem::Downcast(..), _) => bug!( "mismatched projections in place_element_conflict: {:?} and {:?}", - pi1, - pi2 + pi1_elem, + pi2_elem ), } } diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index ecafd4eb11..0a268ec134 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -19,17 +19,9 @@ pub trait IsPrefixOf<'cx, 'tcx> { impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> { fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool { - let mut cursor = other.projection; - loop { - if self.projection == cursor { - return self.base == other.base; - } - - match cursor { - None => return false, - Some(proj) => cursor = &proj.base, - } - } + self.base == other.base + && self.projection.len() <= other.projection.len() + && self.projection == &other.projection[..self.projection.len()] } } @@ -81,112 +73,113 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // downcasts here, but may return a base of a downcast). 'cursor: loop { - let proj = match &cursor { + match &cursor { PlaceRef { base: PlaceBase::Local(_), - projection: None, + projection: [], } | // search yielded this leaf PlaceRef { base: PlaceBase::Static(_), - projection: None, + projection: [], } => { self.next = None; return Some(cursor); } PlaceRef { base: _, - projection: Some(proj), - } => proj, - }; - - match proj.elem { - ProjectionElem::Field(_ /*field*/, _ /*ty*/) => { - // FIXME: add union handling - self.next = Some(PlaceRef { - base: cursor.base, - projection: &proj.base, - }); - return Some(cursor); - } - ProjectionElem::Downcast(..) | - ProjectionElem::Subslice { .. } | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Index(_) => { - cursor = PlaceRef { - base: cursor.base, - projection: &proj.base, - }; - continue 'cursor; - } - ProjectionElem::Deref => { - // (handled below) - } - } - - assert_eq!(proj.elem, ProjectionElem::Deref); - - match self.kind { - PrefixSet::Shallow => { - // shallow prefixes are found by stripping away - // fields, but stop at *any* dereference. - // So we can just stop the traversal now. - self.next = None; - return Some(cursor); - } - PrefixSet::All => { - // all prefixes: just blindly enqueue the base - // of the projection - self.next = Some(PlaceRef { - base: cursor.base, - projection: &proj.base, - }); - return Some(cursor); - } - PrefixSet::Supporting => { - // fall through! - } - } - - assert_eq!(self.kind, PrefixSet::Supporting); - // supporting prefixes: strip away fields and - // derefs, except we stop at the deref of a shared - // reference. - - let ty = Place::ty_from(cursor.base, &proj.base, self.body, self.tcx).ty; - match ty.sty { - ty::RawPtr(_) | - ty::Ref( - _, /*rgn*/ - _, /*ty*/ - hir::MutImmutable - ) => { - // don't continue traversing over derefs of raw pointers or shared borrows. - self.next = None; - return Some(cursor); - } - - ty::Ref( - _, /*rgn*/ - _, /*ty*/ - hir::MutMutable, - ) => { - self.next = Some(PlaceRef { - base: cursor.base, - projection: &proj.base, - }); - return Some(cursor); - } - - ty::Adt(..) if ty.is_box() => { - self.next = Some(PlaceRef { - base: cursor.base, - projection: &proj.base, - }); - return Some(cursor); + projection: [proj_base @ .., elem], + } => { + match elem { + ProjectionElem::Field(_ /*field*/, _ /*ty*/) => { + // FIXME: add union handling + self.next = Some(PlaceRef { + base: cursor.base, + projection: proj_base, + }); + return Some(cursor); + } + ProjectionElem::Downcast(..) | + ProjectionElem::Subslice { .. } | + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Index(_) => { + cursor = PlaceRef { + base: cursor.base, + projection: proj_base, + }; + continue 'cursor; + } + ProjectionElem::Deref => { + // (handled below) + } + } + + assert_eq!(*elem, ProjectionElem::Deref); + + match self.kind { + PrefixSet::Shallow => { + // Shallow prefixes are found by stripping away + // fields, but stop at *any* dereference. + // So we can just stop the traversal now. + self.next = None; + return Some(cursor); + } + PrefixSet::All => { + // All prefixes: just blindly enqueue the base + // of the projection. + self.next = Some(PlaceRef { + base: cursor.base, + projection: proj_base, + }); + return Some(cursor); + } + PrefixSet::Supporting => { + // Fall through! + } + } + + assert_eq!(self.kind, PrefixSet::Supporting); + // Supporting prefixes: strip away fields and + // derefs, except we stop at the deref of a shared + // reference. + + let ty = Place::ty_from(cursor.base, proj_base, self.body, self.tcx).ty; + match ty.sty { + ty::RawPtr(_) | + ty::Ref( + _, /*rgn*/ + _, /*ty*/ + hir::MutImmutable + ) => { + // don't continue traversing over derefs of raw pointers or shared + // borrows. + self.next = None; + return Some(cursor); + } + + ty::Ref( + _, /*rgn*/ + _, /*ty*/ + hir::MutMutable, + ) => { + self.next = Some(PlaceRef { + base: cursor.base, + projection: proj_base, + }); + return Some(cursor); + } + + ty::Adt(..) if ty.is_box() => { + self.next = Some(PlaceRef { + base: cursor.base, + projection: proj_base, + }); + return Some(cursor); + } + + _ => panic!("unknown type fed to Projection Deref."), + } } - - _ => panic!("unknown type fed to Projection Deref."), } } } diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 2587d14a73..695080dfe2 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -89,7 +89,7 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc _location: Location, ) { match &statement.kind { - StatementKind::Assign(into, _) => { + StatementKind::Assign(box(into, _)) => { if let PlaceBase::Local(local) = into.base { debug!( "visit_statement: statement={:?} local={:?} \ @@ -120,7 +120,7 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc ); if let Place { base: PlaceBase::Local(user_local), - projection: None, + projection: box [], } = path.place { self.mbcx.used_mut.insert(user_local); } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 778d1e71ce..3ed6b4ff34 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -37,7 +37,7 @@ impl<'tcx> CFG<'tcx> { rvalue: Rvalue<'tcx>) { self.push(block, Statement { source_info, - kind: StatementKind::Assign(place.clone(), box rvalue) + kind: StatementKind::Assign(box(place.clone(), rvalue)) }); } diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index 5197981a85..39bdc871d8 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -38,9 +38,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: ty, }) }); + assert_eq!(literal.ty, ty); Constant { span, - ty, user_ty, literal, } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 7005f274e0..09b33c6654 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -126,9 +126,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::StaticRef { id } => block.and(Place { base: PlaceBase::Static(Box::new(Static { ty: expr.ty, - kind: StaticKind::Static(id), + kind: StaticKind::Static, + def_id: id, })), - projection: None, + projection: box [], }), ExprKind::PlaceTypeAscription { source, user_ty } => { @@ -146,9 +147,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - place.clone(), + box( + place.clone(), + UserTypeProjection { base: annotation_index, projs: vec![], } + ), Variance::Invariant, - box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); @@ -173,9 +176,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - Place::from(temp.clone()), + box( + Place::from(temp.clone()), + UserTypeProjection { base: annotation_index, projs: vec![], }, + ), Variance::Invariant, - box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index ec061e7453..7dfe98cbeb 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -500,14 +500,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mutability = match arg_place { Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } => this.local_decls[local].mutability, Place { base: PlaceBase::Local(local), - projection: Some(box Projection { - base: None, - elem: ProjectionElem::Deref, - }) + projection: box [ProjectionElem::Deref], } => { debug_assert!( this.local_decls[local].is_ref_for_guard(), @@ -517,24 +514,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Place { ref base, - projection: Some(box Projection { - base: ref base_proj, - elem: ProjectionElem::Field(upvar_index, _), - }), + projection: box [ref proj_base @ .., ProjectionElem::Field(upvar_index, _)], } | Place { ref base, - projection: Some(box Projection { - base: Some(box Projection { - base: ref base_proj, - elem: ProjectionElem::Field(upvar_index, _), - }), - elem: ProjectionElem::Deref, - }), + projection: box [ + ref proj_base @ .., + ProjectionElem::Field(upvar_index, _), + ProjectionElem::Deref + ], } => { let place = PlaceRef { base, - projection: base_proj, + projection: proj_base, }; // Not projected from the implicit `self` in a closure. @@ -591,7 +583,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = (!0u128) >> (128 - bits); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } // Helper to get the minimum value of the appropriate type @@ -602,6 +594,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = 1 << (bits - 1); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 02ab53fe8c..30d53502b1 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -114,7 +114,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.true_literal(), }, @@ -126,7 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.false_literal(), }, @@ -246,6 +244,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let success = this.cfg.start_new_block(); let cleanup = this.diverge_cleanup(); + + this.record_operands_moved(&args); + this.cfg.terminate( block, source_info, @@ -303,7 +304,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Create a "fake" temporary variable so that we check that the // value is Sized. Usually, this is caught in type checking, but // in the case of box expr there is no such check. - if destination.projection.is_some() { + if !destination.projection.is_empty() { this.local_decls .push(LocalDecl::new_temp(expr.ty, expr.span)); } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index d72b0addae..2b0237c7c0 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, kind: StatementKind::FakeRead( FakeReadCause::ForMatchedPlace, - scrutinee_place.clone(), + box(scrutinee_place.clone()), ), }); @@ -320,7 +320,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, Statement { source_info, - kind: StatementKind::FakeRead(FakeReadCause::ForLet, place), + kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place)), }, ); @@ -362,12 +362,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, Statement { source_info: pattern_source_info, - kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()), + kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place.clone())), }, ); let ty_source_info = self.source_info(user_ty_span); - let user_ty = box pat_ascription_ty.user_ty( + let user_ty = pat_ascription_ty.user_ty( &mut self.canonical_user_type_annotations, place.ty(&self.local_decls, self.hir.tcx()).ty, ty_source_info.span, @@ -377,7 +377,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info: ty_source_info, kind: StatementKind::AscribeUserType( - place, + box( + place, + user_ty, + ), // We always use invariant as the variance here. This is because the // variance field from the ascription refers to the variance to use // when applying the type to the value being matched, but this @@ -393,7 +396,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // contrast, is intended to be used to relate `T` to the type of // ``. ty::Variance::Invariant, - user_ty, ), }, ); @@ -657,6 +659,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } + PatternKind::Or { ref pats } => { + for pat in pats { + self.visit_bindings(&pat, pattern_user_ty.clone(), f); + } + } } } } @@ -937,16 +944,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for Binding { source, .. } in matched_candidates.iter().flat_map(|candidate| &candidate.bindings) { - let mut cursor = &source.projection; - while let Some(box Projection { base, elem }) = cursor { - cursor = base; - if let ProjectionElem::Deref = elem { - fake_borrows.insert(Place { - base: source.base.clone(), - projection: cursor.clone(), - }); - break; - } + if let Some(i) = + source.projection.iter().rposition(|elem| *elem == ProjectionElem::Deref) + { + let proj_base = &source.projection[..i]; + + fake_borrows.insert(Place { + base: source.base.clone(), + projection: proj_base.to_vec().into_boxed_slice(), + }); } } } @@ -1290,18 +1296,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Insert a Shallow borrow of the prefixes of any fake borrows. for place in fake_borrows { - let mut prefix_cursor = &place.projection; - while let Some(box Projection { base, elem }) = prefix_cursor { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + if let ProjectionElem::Deref = elem { // Insert a shallow borrow after a deref. For other // projections the borrow of prefix_cursor will // conflict with any mutation of base. all_fake_borrows.push(PlaceRef { base: &place.base, - projection: base, + projection: proj_base, }); } - prefix_cursor = base; } all_fake_borrows.push(place.as_ref()); @@ -1340,13 +1347,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// any, and then branches to the arm. Returns the block for the case where /// the guard fails. /// - /// Note: we check earlier that if there is a guard, there cannot be move - /// bindings (unless feature(bind_by_move_pattern_guards) is used). This - /// isn't really important for the self-consistency of this fn, but the - /// reason for it should be clear: after we've done the assignments, if - /// there were move bindings, further tests would be a use-after-move. - /// bind_by_move_pattern_guards avoids this by only moving the binding once - /// the guard has evaluated to true (see below). + /// Note: we do not check earlier that if there is a guard, + /// there cannot be move bindings. We avoid a use-after-move by only + /// moving the binding once the guard has evaluated to true (see below). fn bind_and_guard_matched_candidate<'pat>( &mut self, candidate: Candidate<'pat, 'tcx>, @@ -1488,7 +1491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BorrowKind::Shallow, Place { base: place.base.clone(), - projection: place.projection.clone(), + projection: place.projection.to_vec().into_boxed_slice(), }, ); self.cfg.push_assign( @@ -1519,7 +1522,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: guard_end, kind: StatementKind::FakeRead( FakeReadCause::ForMatchGuard, - Place::from(temp), + box(Place::from(temp)), ), }); } @@ -1569,7 +1572,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { post_guard_block, Statement { source_info: guard_end, - kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, place), + kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, box(place)), }, ); } @@ -1602,7 +1605,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ascription.user_ty, ); - let user_ty = box ascription.user_ty.clone().user_ty( + let user_ty = ascription.user_ty.clone().user_ty( &mut self.canonical_user_type_annotations, ascription.source.ty(&self.local_decls, self.hir.tcx()).ty, source_info.span @@ -1612,9 +1615,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - ascription.source.clone(), + box( + ascription.source.clone(), + user_ty, + ), ascription.variance, - user_ty, ), }, ); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index d9b748f71f..8d049b5398 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -108,8 +108,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatternKind::Range(PatternRange { lo, hi, ty, end }) => { - let (range, bias) = match ty.sty { + PatternKind::Range(PatternRange { lo, hi, end }) => { + let (range, bias) = match lo.ty.sty { ty::Char => { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } @@ -195,6 +195,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate.match_pairs.push(MatchPair::new(place, subpattern)); Ok(()) } + + PatternKind::Or { .. } => { + Err(match_pair) + } } } } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 1c93abd40d..d5890d00ea 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -63,7 +63,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatternKind::Range(range) => { - assert!(range.ty == match_pair.pattern.ty); + assert_eq!(range.lo.ty, match_pair.pattern.ty); + assert_eq!(range.hi.ty, match_pair.pattern.ty); Test { span: match_pair.pattern.span, kind: TestKind::Range(range), @@ -86,6 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::AscribeUserType { .. } | PatternKind::Array { .. } | PatternKind::Wild | + PatternKind::Or { .. } | PatternKind::Binding { .. } | PatternKind::Leaf { .. } | PatternKind::Deref { .. } => { @@ -129,6 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::Slice { .. } | PatternKind::Array { .. } | PatternKind::Wild | + PatternKind::Or { .. } | PatternKind::Binding { .. } | PatternKind::AscribeUserType { .. } | PatternKind::Leaf { .. } | @@ -270,8 +273,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } else { if let [success, fail] = *make_target_blocks(self) { + assert_eq!(value.ty, ty); + let expect = self.literal_operand(test.span, value); let val = Operand::Copy(place.clone()); - let expect = self.literal_operand(test.span, ty, value); self.compare(block, success, fail, source_info, BinOp::Eq, expect, val); } else { bug!("`TestKind::Eq` should have two target blocks"); @@ -279,13 +283,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { + TestKind::Range(PatternRange { ref lo, ref hi, ref end }) => { let lower_bound_success = self.cfg.start_new_block(); let target_blocks = make_target_blocks(self); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. - let lo = self.literal_operand(test.span, ty, lo); - let hi = self.literal_operand(test.span, ty, hi); + let lo = self.literal_operand(test.span, lo); + let hi = self.literal_operand(test.span, hi); let val = Operand::Copy(place.clone()); if let [success, fail] = *target_blocks { @@ -387,7 +391,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { use rustc::middle::lang_items::EqTraitLangItem; - let mut expect = self.literal_operand(source_info.span, value.ty, value); + let mut expect = self.literal_operand(source_info.span, value); let mut val = Operand::Copy(place.clone()); // If we're using `b"..."` as a pattern, we need to insert an @@ -439,8 +443,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => bug!("non_scalar_compare called on non-reference type: {}", ty), }; - let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem); - let (mty, method) = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem, None); + let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty, source_info.span); @@ -449,7 +453,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::Call { func: Operand::Constant(box Constant { span: source_info.span, - ty: mty, // FIXME(#54571): This constant comes from user input (a // constant in a pattern). Are there forms where users can add @@ -656,8 +659,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test.ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test.ty)?; + let test_ty = test.lo.ty; + let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test_ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test_ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -774,8 +778,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.ty)?; - let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?; + let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.lo.ty)?; + let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.lo.ty)?; match (b, range.end) { (Less, _) | diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 56025eeaaa..d038310dd4 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -26,12 +26,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// without any user type annotation. pub fn literal_operand(&mut self, span: Span, - ty: Ty<'tcx>, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, - ty, user_ty: None, literal, }; @@ -47,7 +45,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } pub fn push_usize(&mut self, @@ -61,7 +59,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, &temp, Constant { span: source_info.span, - ty: self.hir.usize_ty(), user_ty: None, literal: self.hir.usize_literal(value), }); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 6a3bb8b8b8..647d7515fe 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -94,7 +94,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let body = tcx.hir().body(body_id); let explicit_arguments = - body.arguments + body.params .iter() .enumerate() .map(|(index, arg)| { @@ -511,7 +511,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function -struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Arg>, Option); +struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Param>, Option); fn construct_fn<'a, 'tcx, A>( hir: Cx<'a, 'tcx>, @@ -609,7 +609,7 @@ where unpack!(block = builder.in_breakable_scope( None, START_BLOCK, - Place::RETURN_PLACE, + Place::return_place(), |builder| { builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { builder.args_and_body(block, &arguments, arg_scope, &body.value) @@ -670,7 +670,7 @@ fn construct_const<'a, 'tcx>( let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; let expr = builder.hir.mirror(ast_expr); - unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr)); + unpack!(block = builder.into_expr(&Place::return_place(), block, expr)); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -763,7 +763,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.basic_blocks, self.source_scopes, ClearCrossCrate::Set(self.source_scope_local_data), - IndexVec::new(), yield_ty, self.local_decls, self.canonical_user_type_annotations, @@ -872,7 +871,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let body = self.hir.mirror(ast_body); - self.into(&Place::RETURN_PLACE, block, body) + self.into(&Place::return_place(), block, body) } fn set_correct_source_scope_for_arg( diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index a04c041ca9..a26ec72584 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -104,25 +104,14 @@ struct Scope { /// the span of that region_scope region_scope_span: Span, - /// Whether there's anything to do for the cleanup path, that is, - /// when unwinding through this scope. This includes destructors, - /// but not StorageDead statements, which don't get emitted at all - /// for unwinding, for several reasons: - /// * clang doesn't emit llvm.lifetime.end for C++ unwinding - /// * LLVM's memory dependency analysis can't handle it atm - /// * polluting the cleanup MIR with StorageDead creates - /// landing pads even though there's no actual destructors - /// * freeing up stack space has no effect during unwinding - /// Note that for generators we do emit StorageDeads, for the - /// use of optimizations in the MIR generator transform. - needs_cleanup: bool, - /// set of places to drop when exiting this scope. This starts /// out empty but grows as variables are declared during the /// building process. This is a stack, so we always drop from the /// end of the vector (top of the stack) first. drops: Vec, + moved_locals: Vec, + /// The cache for drop chain on “normal” exit into a particular BasicBlock. cached_exits: FxHashMap<(BasicBlock, region::Scope), BasicBlock>, @@ -172,7 +161,7 @@ struct CachedBlock { generator_drop: Option, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub(crate) enum DropKind { Value, Storage, @@ -202,8 +191,7 @@ pub enum BreakableTarget { impl CachedBlock { fn invalidate(&mut self) { - self.generator_drop = None; - self.unwind = None; + *self = CachedBlock::default(); } fn get(&self, generator_drop: bool) -> Option { @@ -261,6 +249,25 @@ impl Scope { scope: self.source_scope } } + + + /// Whether there's anything to do for the cleanup path, that is, + /// when unwinding through this scope. This includes destructors, + /// but not StorageDead statements, which don't get emitted at all + /// for unwinding, for several reasons: + /// * clang doesn't emit llvm.lifetime.end for C++ unwinding + /// * LLVM's memory dependency analysis can't handle it atm + /// * polluting the cleanup MIR with StorageDead creates + /// landing pads even though there's no actual destructors + /// * freeing up stack space has no effect during unwinding + /// Note that for generators we do emit StorageDeads, for the + /// use of optimizations in the MIR generator transform. + fn needs_cleanup(&self) -> bool { + self.drops.iter().any(|drop| match drop.kind { + DropKind::Value => true, + DropKind::Storage => false, + }) + } } impl<'tcx> Scopes<'tcx> { @@ -274,8 +281,8 @@ impl<'tcx> Scopes<'tcx> { source_scope: vis_scope, region_scope: region_scope.0, region_scope_span: region_scope.1.span, - needs_cleanup: false, drops: vec![], + moved_locals: vec![], cached_generator_drop: None, cached_exits: Default::default(), cached_unwind: CachedBlock::default(), @@ -295,7 +302,7 @@ impl<'tcx> Scopes<'tcx> { fn may_panic(&self, scope_count: usize) -> bool { let len = self.len(); - self.scopes[(len - scope_count)..].iter().any(|s| s.needs_cleanup) + self.scopes[(len - scope_count)..].iter().any(|s| s.needs_cleanup()) } /// Finds the breakable scope for a given label. This is used for @@ -314,7 +321,7 @@ impl<'tcx> Scopes<'tcx> { match target { BreakableTarget::Return => { let scope = &self.breakable_scopes[0]; - if scope.break_destination != Place::RETURN_PLACE { + if scope.break_destination != Place::return_place() { span_bug!(span, "`return` in item with no return scope"); } (scope.break_block, scope.region_scope, Some(scope.break_destination.clone())) @@ -480,7 +487,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, unwind_to, self.arg_count, - false, + false, // not generator + false, // not unwind path )); block.unit() @@ -572,7 +580,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, unwind_to, self.arg_count, - false, + false, // not generator + false, // not unwind path )); scope = next_scope; @@ -622,7 +631,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, unwind_to, self.arg_count, - true, + true, // is generator + true, // is cached path )); } @@ -801,10 +811,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // cache of outer scope stays intact. scope.invalidate_cache(!needs_drop, self.is_generator, this_scope); if this_scope { - if let DropKind::Value = drop_kind { - scope.needs_cleanup = true; - } - let region_scope_span = region_scope.span(self.hir.tcx(), &self.hir.region_scope_tree); // Attribute scope exit drops to scope's closing brace. @@ -822,6 +828,75 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local); } + /// Indicates that the "local operand" stored in `local` is + /// *moved* at some point during execution (see `local_scope` for + /// more information about what a "local operand" is -- in short, + /// it's an intermediate operand created as part of preparing some + /// MIR instruction). We use this information to suppress + /// redundant drops on the non-unwind paths. This results in less + /// MIR, but also avoids spurious borrow check errors + /// (c.f. #64391). + /// + /// Example: when compiling the call to `foo` here: + /// + /// ```rust + /// foo(bar(), ...) + /// ``` + /// + /// we would evaluate `bar()` to an operand `_X`. We would also + /// schedule `_X` to be dropped when the expression scope for + /// `foo(bar())` is exited. This is relevant, for example, if the + /// later arguments should unwind (it would ensure that `_X` gets + /// dropped). However, if no unwind occurs, then `_X` will be + /// unconditionally consumed by the `call`: + /// + /// ``` + /// bb { + /// ... + /// _R = CALL(foo, _X, ...) + /// } + /// ``` + /// + /// However, `_X` is still registered to be dropped, and so if we + /// do nothing else, we would generate a `DROP(_X)` that occurs + /// after the call. This will later be optimized out by the + /// drop-elaboation code, but in the meantime it can lead to + /// spurious borrow-check errors -- the problem, ironically, is + /// not the `DROP(_X)` itself, but the (spurious) unwind pathways + /// that it creates. See #64391 for an example. + pub fn record_operands_moved( + &mut self, + operands: &[Operand<'tcx>], + ) { + let scope = match self.local_scope() { + None => { + // if there is no local scope, operands won't be dropped anyway + return; + } + + Some(local_scope) => { + self.scopes.iter_mut().find(|scope| scope.region_scope == local_scope) + .unwrap_or_else(|| bug!("scope {:?} not found in scope list!", local_scope)) + } + }; + + // look for moves of a local variable, like `MOVE(_X)` + let locals_moved = operands.iter().flat_map(|operand| match operand { + Operand::Copy(_) | Operand::Constant(_) => None, + Operand::Move(place) => place.as_local(), + }); + + for local in locals_moved { + // check if we have a Drop for this operand and -- if so + // -- add it to the list of moved operands. Note that this + // local might not have been an operand created for this + // call, it could come from other places too. + if scope.drops.iter().any(|drop| drop.local == local && drop.kind == DropKind::Value) { + scope.moved_locals.push(local); + } + } + } + // Other // ===== /// Branch based on a boolean condition. @@ -853,11 +928,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ if self.local_scope().is_none() => (), Operand::Copy(Place { base: PlaceBase::Local(cond_temp), - projection: None, + projection: box [], }) | Operand::Move(Place { base: PlaceBase::Local(cond_temp), - projection: None, + projection: box [], }) => { // Manually drop the condition on both branches. let top_scope = self.scopes.scopes.last_mut().unwrap(); @@ -1020,6 +1095,7 @@ fn build_scope_drops<'tcx>( last_unwind_to: BasicBlock, arg_count: usize, generator_drop: bool, + is_cached_path: bool, ) -> BlockAnd<()> { debug!("build_scope_drops({:?} -> {:?})", block, scope); @@ -1046,8 +1122,17 @@ fn build_scope_drops<'tcx>( let drop_data = &scope.drops[drop_idx]; let source_info = scope.source_info(drop_data.span); let local = drop_data.local; + match drop_data.kind { DropKind::Value => { + // If the operand has been moved, and we are not on an unwind + // path, then don't generate the drop. (We only take this into + // account for non-unwind paths so as not to disturb the + // caching mechanism.) + if !is_cached_path && scope.moved_locals.iter().any(|&o| o == local) { + continue; + } + let unwind_to = get_unwind_to(scope, is_generator, drop_idx, generator_drop) .unwrap_or(last_unwind_to); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 36d80d0cb5..435159827e 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -11,11 +11,11 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef}; use rustc::mir; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, subst::Subst}; use rustc::ty::layout::{self, LayoutOf, VariantIdx}; -use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc_data_structures::fx::FxHashMap; +use crate::interpret::eval_nullary_intrinsic; use syntax::source_map::{Span, DUMMY_SP}; @@ -50,17 +50,6 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>( InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default()) } -pub(crate) fn eval_promoted<'mir, 'tcx>( - tcx: TyCtxt<'tcx>, - cid: GlobalId<'tcx>, - body: &'mir mir::Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let span = tcx.def_span(cid.instance.def_id()); - let mut ecx = mk_eval_cx(tcx, span, param_env); - eval_body_using_ecx(&mut ecx, cid, body, param_env) -} - fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>, op: OpTy<'tcx>, @@ -146,9 +135,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, cid: GlobalId<'tcx>, body: &'mir mir::Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env); + debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); let tcx = ecx.tcx.tcx; let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); @@ -174,7 +162,6 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx, cid.instance.def_id(), ret, - param_env, )?; debug!("eval_body_using_ecx done: {:?}", *ret); @@ -361,7 +348,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } // This is a const fn. Call it. - Ok(Some(match ecx.load_mir(instance.def) { + Ok(Some(match ecx.load_mir(instance.def, None) { Ok(body) => body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { @@ -395,7 +382,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, return Ok(()); } // An intrinsic that we do not support - let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..]; + let intrinsic_name = ecx.tcx.item_name(instance.def_id()); Err( ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into() ) @@ -415,7 +402,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _bin_op: mir::BinOp, _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { Err( ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(), ) @@ -531,6 +518,9 @@ pub fn const_variant_index<'tcx>( ecx.read_discriminant(op).unwrap().1 } +/// Turn an interpreter error into something to report to the user. +/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. +/// Should be called only if the error is actually going to to be reported! pub fn error_to_const_error<'mir, 'tcx>( ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, mut error: InterpErrorInfo<'tcx>, @@ -540,6 +530,12 @@ pub fn error_to_const_error<'mir, 'tcx>( ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span } } +pub fn note_on_undefined_behavior_error() -> &'static str { + "The rules on what exactly is undefined behavior aren't clear, \ + so this check might be overzealous. Please open an issue on the rustc \ + repository if you believe it should not be considered undefined behavior." +} + fn validate_and_turn_into_const<'tcx>( tcx: TyCtxt<'tcx>, constant: RawConst<'tcx>, @@ -579,10 +575,7 @@ fn validate_and_turn_into_const<'tcx>( let err = error_to_const_error(&ecx, error); match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { Ok(mut diag) => { - diag.note("The rules on what exactly is undefined behavior aren't clear, \ - so this check might be overzealous. Please open an issue on the rust compiler \ - repository if you believe it should not be considered undefined behavior", - ); + diag.note(note_on_undefined_behavior_error()); diag.emit(); ErrorHandled::Reported } @@ -595,7 +588,7 @@ pub fn const_eval_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { - // see comment in const_eval_provider for what we're doing here + // see comment in const_eval_raw_provider for what we're doing here if key.param_env.reveal == Reveal::All { let mut key = key.clone(); key.param_env.reveal = Reveal::UserFacing; @@ -610,6 +603,23 @@ pub fn const_eval_provider<'tcx>( other => return other, } } + + // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. + // Catch such calls and evaluate them instead of trying to load a constant's MIR. + if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { + let ty = key.value.instance.ty(tcx); + let substs = match ty.sty { + ty::FnDef(_, substs) => substs, + _ => bug!("intrinsic with type {:?}", ty), + }; + return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs) + .map_err(|error| { + let span = tcx.def_span(def_id); + let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span }; + error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic") + }) + } + tcx.const_eval_raw(key).and_then(|val| { validate_and_turn_into_const(tcx, val, key) }) @@ -662,15 +672,9 @@ pub fn const_eval_raw_provider<'tcx>( Default::default() ); - let res = ecx.load_mir(cid.instance.def); - res.map(|body| { - if let Some(index) = cid.promoted { - &body.promoted[index] - } else { - body - } - }).and_then( - |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env) + let res = ecx.load_mir(cid.instance.def, cid.promoted); + res.and_then( + |body| eval_body_using_ecx(&mut ecx, cid, body) ).and_then(|place| { Ok(RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index c071b3101f..444cc008ae 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -10,19 +10,17 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, path: MovePathIndex, mut cond: F) -> Option - where F: FnMut(&mir::Projection<'tcx>) -> bool + where F: FnMut(&mir::PlaceElem<'tcx>) -> bool { let mut next_child = move_data.move_paths[path].first_child; while let Some(child_index) = next_child { - match move_data.move_paths[child_index].place.projection { - Some(ref proj) => { - if cond(proj) { - return Some(child_index) - } + let move_path_children = &move_data.move_paths[child_index]; + if let Some(elem) = move_path_children.place.projection.last() { + if cond(elem) { + return Some(child_index) } - _ => {} } - next_child = move_data.move_paths[child_index].next_sibling; + next_child = move_path_children.next_sibling; } None diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs new file mode 100644 index 0000000000..886044c069 --- /dev/null +++ b/src/librustc_mir/dataflow/generic.rs @@ -0,0 +1,512 @@ +//! Dataflow analysis with arbitrary transfer functions. +//! +//! This module is a work in progress. You should instead use `BitDenotation` in +//! `librustc_mir/dataflow/mod.rs` and encode your transfer function as a [gen/kill set][gk]. In +//! doing so, your analysis will run faster and you will be able to generate graphviz diagrams for +//! debugging with no extra effort. The interface in this module is intended only for dataflow +//! problems that cannot be expressed using gen/kill sets. +//! +//! FIXME(ecstaticmorse): In the long term, the plan is to preserve the existing `BitDenotation` +//! interface, but make `Engine` and `ResultsCursor` the canonical way to perform and inspect a +//! dataflow analysis. This requires porting the graphviz debugging logic to this module, deciding +//! on a way to handle the `before` methods in `BitDenotation` and creating an adapter so that +//! gen-kill problems can still be evaluated efficiently. See the discussion in [#64566][] for more +//! information. +//! +//! [gk]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems +//! [#64566]: https://github.com/rust-lang/rust/pull/64566 + +use std::cmp::Ordering; +use std::ops; + +use rustc::mir::{self, traversal, BasicBlock, Location}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::work_queue::WorkQueue; + +use crate::dataflow::BottomValue; + +/// A specific kind of dataflow analysis. +/// +/// To run a dataflow analysis, one must set the initial state of the `START_BLOCK` via +/// `initialize_start_block` and define a transfer function for each statement or terminator via +/// the various `effect` methods. The entry set for all other basic blocks is initialized to +/// `Self::BOTTOM_VALUE`. The dataflow `Engine` then iteratively updates the various entry sets for +/// each block with the cumulative effects of the transfer functions of all preceding blocks. +/// +/// You should use an `Engine` to actually run an analysis, and a `ResultsCursor` to inspect the +/// results of that analysis like so: +/// +/// ```ignore(cross-crate-imports) +/// fn do_my_analysis(body: &mir::Body<'tcx>, dead_unwinds: &BitSet) { +/// // `MyAnalysis` implements `Analysis`. +/// let analysis = MyAnalysis::new(); +/// +/// let results = Engine::new(body, dead_unwinds, analysis).iterate_to_fixpoint(); +/// let mut cursor = ResultsCursor::new(body, results); +/// +/// for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() { +/// cursor.seek_after(Location { block: START_BLOCK, statement_index }); +/// let state = cursor.get(); +/// println!("{:?}", state); +/// } +/// } +/// ``` +pub trait Analysis<'tcx>: BottomValue { + /// The index type used to access the dataflow state. + type Idx: Idx; + + /// A name, used for debugging, that describes this dataflow analysis. + /// + /// The name should be suitable as part of a filename, so avoid whitespace, slashes or periods + /// and try to keep it short. + const NAME: &'static str; + + /// The size of each bitvector allocated for each block. + fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize; + + /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow + /// analysis. + fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet); + + /// Updates the current dataflow state with the effect of evaluating a statement. + fn apply_statement_effect( + &self, + state: &mut BitSet, + statement: &mir::Statement<'tcx>, + location: Location, + ); + + /// Updates the current dataflow state with the effect of evaluating a statement. + /// + /// Note that the effect of a successful return from a `Call` terminator should **not** be + /// acounted for in this function. That should go in `apply_call_return_effect`. For example, + /// in the `InitializedPlaces` analyses, the return place is not marked as initialized here. + fn apply_terminator_effect( + &self, + state: &mut BitSet, + terminator: &mir::Terminator<'tcx>, + location: Location, + ); + + /// Updates the current dataflow state with the effect of a successful return from a `Call` + /// terminator. + /// + /// This is separated from `apply_terminator_effect` to properly track state across + /// unwind edges for `Call`s. + fn apply_call_return_effect( + &self, + state: &mut BitSet, + block: BasicBlock, + func: &mir::Operand<'tcx>, + args: &[mir::Operand<'tcx>], + return_place: &mir::Place<'tcx>, + ); + + /// Applies the cumulative effect of an entire basic block to the dataflow state (except for + /// `call_return_effect`, which is handled in the `Engine`). + /// + /// The default implementation calls `statement_effect` for every statement in the block before + /// finally calling `terminator_effect`. However, some dataflow analyses are able to coalesce + /// transfer functions for an entire block and apply them at once. Such analyses should + /// override `block_effect`. + fn apply_whole_block_effect( + &self, + state: &mut BitSet, + block: BasicBlock, + block_data: &mir::BasicBlockData<'tcx>, + ) { + for (statement_index, stmt) in block_data.statements.iter().enumerate() { + let location = Location { block, statement_index }; + self.apply_statement_effect(state, stmt, location); + } + + let location = Location { block, statement_index: block_data.statements.len() }; + self.apply_terminator_effect(state, block_data.terminator(), location); + } + + /// Applies the cumulative effect of a sequence of statements (and possibly a terminator) + /// within a single basic block. + /// + /// When called with `0..block_data.statements.len() + 1` as the statement range, this function + /// is equivalent to `apply_whole_block_effect`. + fn apply_partial_block_effect( + &self, + state: &mut BitSet, + block: BasicBlock, + block_data: &mir::BasicBlockData<'tcx>, + mut range: ops::Range, + ) { + if range.is_empty() { + return; + } + + // The final location might be a terminator, so iterate through all statements until the + // final one, then check to see whether the final one is a statement or terminator. + // + // This can't cause the range to wrap-around since we check that the range contains at + // least one element above. + range.end -= 1; + let final_location = Location { block, statement_index: range.end }; + + for statement_index in range { + let location = Location { block, statement_index }; + let stmt = &block_data.statements[statement_index]; + self.apply_statement_effect(state, stmt, location); + } + + if final_location.statement_index == block_data.statements.len() { + let terminator = block_data.terminator(); + self.apply_terminator_effect(state, terminator, final_location); + } else { + let stmt = &block_data.statements[final_location.statement_index]; + self.apply_statement_effect(state, stmt, final_location); + } + } +} + +#[derive(Clone, Copy, Debug)] +enum CursorPosition { + AtBlockStart(BasicBlock), + After(Location), +} + +impl CursorPosition { + fn block(&self) -> BasicBlock { + match *self { + Self::AtBlockStart(block) => block, + Self::After(Location { block, .. }) => block, + } + } +} + +/// Inspect the results of dataflow analysis. +/// +/// This cursor has linear performance when visiting statements in a block in order. Visiting +/// statements within a block in reverse order is `O(n^2)`, where `n` is the number of statements +/// in that block. +pub struct ResultsCursor<'mir, 'tcx, A> +where + A: Analysis<'tcx>, +{ + body: &'mir mir::Body<'tcx>, + results: Results<'tcx, A>, + state: BitSet, + + pos: CursorPosition, + + /// Whether the effects of `apply_call_return_effect` are currently stored in `state`. + /// + /// This flag ensures that multiple calls to `seek_after_assume_call_returns` with the same + /// target only result in one invocation of `apply_call_return_effect`. + is_call_return_effect_applied: bool, +} + +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> +where + A: Analysis<'tcx>, +{ + /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`. + pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self { + ResultsCursor { + body, + pos: CursorPosition::AtBlockStart(mir::START_BLOCK), + is_call_return_effect_applied: false, + state: results.entry_sets[mir::START_BLOCK].clone(), + results, + } + } + + /// Resets the cursor to the start of the given `block`. + pub fn seek_to_block_start(&mut self, block: BasicBlock) { + self.state.overwrite(&self.results.entry_sets[block]); + self.pos = CursorPosition::AtBlockStart(block); + self.is_call_return_effect_applied = false; + } + + /// Updates the cursor to hold the dataflow state immediately before `target`. + pub fn seek_before(&mut self, target: Location) { + assert!(target <= self.body.terminator_loc(target.block)); + + if target.statement_index == 0 { + self.seek_to_block_start(target.block); + } else { + self._seek_after(Location { + block: target.block, + statement_index: target.statement_index - 1, + }); + } + } + + /// Updates the cursor to hold the dataflow state at `target`. + /// + /// If `target` is a `Call` terminator, `apply_call_return_effect` will not be called. See + /// `seek_after_assume_call_returns` if you wish to observe the dataflow state upon a + /// successful return. + pub fn seek_after(&mut self, target: Location) { + assert!(target <= self.body.terminator_loc(target.block)); + + // This check ensures the correctness of a call to `seek_after_assume_call_returns` + // followed by one to `seek_after` with the same target. + if self.is_call_return_effect_applied { + self.seek_to_block_start(target.block); + } + + self._seek_after(target); + } + + /// Equivalent to `seek_after`, but also calls `apply_call_return_effect` if `target` is a + /// `Call` terminator whose callee is convergent. + pub fn seek_after_assume_call_returns(&mut self, target: Location) { + assert!(target <= self.body.terminator_loc(target.block)); + + self._seek_after(target); + + if target != self.body.terminator_loc(target.block) { + return; + } + + let term = self.body.basic_blocks()[target.block].terminator(); + if let mir::TerminatorKind::Call { + destination: Some((return_place, _)), + func, + args, + .. + } = &term.kind { + if !self.is_call_return_effect_applied { + self.is_call_return_effect_applied = true; + self.results.analysis.apply_call_return_effect( + &mut self.state, + target.block, + func, + args, + return_place, + ); + } + } + } + + fn _seek_after(&mut self, target: Location) { + let Location { block: target_block, statement_index: target_index } = target; + + if self.pos.block() != target_block { + self.seek_to_block_start(target_block); + } + + // If we're in the same block but after the target statement, we need to reset to the start + // of the block. + if let CursorPosition::After(Location { statement_index: curr_index, .. }) = self.pos { + match curr_index.cmp(&target_index) { + Ordering::Equal => return, + Ordering::Less => {}, + Ordering::Greater => self.seek_to_block_start(target_block), + } + } + + // The cursor is now in the same block as the target location pointing at an earlier + // statement. + debug_assert_eq!(self.pos.block(), target_block); + if let CursorPosition::After(Location { statement_index, .. }) = self.pos { + debug_assert!(statement_index < target_index); + } + + let first_unapplied_statement = match self.pos { + CursorPosition::AtBlockStart(_) => 0, + CursorPosition::After(Location { statement_index, .. }) => statement_index + 1, + }; + + let block_data = &self.body.basic_blocks()[target_block]; + self.results.analysis.apply_partial_block_effect( + &mut self.state, + target_block, + block_data, + first_unapplied_statement..target_index + 1, + ); + + self.pos = CursorPosition::After(target); + self.is_call_return_effect_applied = false; + } + + /// Gets the dataflow state at the current location. + pub fn get(&self) -> &BitSet { + &self.state + } +} + +/// A completed dataflow analysis. +pub struct Results<'tcx, A> +where + A: Analysis<'tcx>, +{ + analysis: A, + entry_sets: IndexVec>, +} + +/// All information required to iterate a dataflow analysis to fixpoint. +pub struct Engine<'a, 'tcx, A> +where + A: Analysis<'tcx>, +{ + analysis: A, + bits_per_block: usize, + body: &'a mir::Body<'tcx>, + dead_unwinds: &'a BitSet, + entry_sets: IndexVec>, +} + +impl Engine<'a, 'tcx, A> +where + A: Analysis<'tcx>, +{ + pub fn new( + body: &'a mir::Body<'tcx>, + dead_unwinds: &'a BitSet, + analysis: A, + ) -> Self { + let bits_per_block = analysis.bits_per_block(body); + + let bottom_value_set = if A::BOTTOM_VALUE == true { + BitSet::new_filled(bits_per_block) + } else { + BitSet::new_empty(bits_per_block) + }; + + let mut entry_sets = IndexVec::from_elem(bottom_value_set, body.basic_blocks()); + analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); + + Engine { + analysis, + bits_per_block, + body, + dead_unwinds, + entry_sets, + } + } + + pub fn iterate_to_fixpoint(mut self) -> Results<'tcx, A> { + let mut temp_state = BitSet::new_empty(self.bits_per_block); + + let mut dirty_queue: WorkQueue = + WorkQueue::with_none(self.body.basic_blocks().len()); + + for (bb, _) in traversal::reverse_postorder(self.body) { + dirty_queue.insert(bb); + } + + // Add blocks that are not reachable from START_BLOCK to the work queue. These blocks will + // be processed after the ones added above. + for bb in self.body.basic_blocks().indices() { + dirty_queue.insert(bb); + } + + while let Some(bb) = dirty_queue.pop() { + let bb_data = &self.body[bb]; + let on_entry = &self.entry_sets[bb]; + + temp_state.overwrite(on_entry); + self.analysis.apply_whole_block_effect(&mut temp_state, bb, bb_data); + + self.propagate_bits_into_graph_successors_of( + &mut temp_state, + (bb, bb_data), + &mut dirty_queue, + ); + } + + Results { + analysis: self.analysis, + entry_sets: self.entry_sets, + } + } + + fn propagate_bits_into_graph_successors_of( + &mut self, + in_out: &mut BitSet, + (bb, bb_data): (BasicBlock, &'a mir::BasicBlockData<'tcx>), + dirty_list: &mut WorkQueue, + ) { + match bb_data.terminator().kind { + mir::TerminatorKind::Return + | mir::TerminatorKind::Resume + | mir::TerminatorKind::Abort + | mir::TerminatorKind::GeneratorDrop + | mir::TerminatorKind::Unreachable => {} + + mir::TerminatorKind::Goto { target } + | mir::TerminatorKind::Assert { target, cleanup: None, .. } + | mir::TerminatorKind::Yield { resume: target, drop: None, .. } + | mir::TerminatorKind::Drop { target, location: _, unwind: None } + | mir::TerminatorKind::DropAndReplace { target, value: _, location: _, unwind: None } => + { + self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); + } + + mir::TerminatorKind::Yield { resume: target, drop: Some(drop), .. } => { + self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); + self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list); + } + + mir::TerminatorKind::Assert { target, cleanup: Some(unwind), .. } + | mir::TerminatorKind::Drop { target, location: _, unwind: Some(unwind) } + | mir::TerminatorKind::DropAndReplace { + target, + value: _, + location: _, + unwind: Some(unwind), + } => { + self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); + if !self.dead_unwinds.contains(bb) { + self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); + } + } + + mir::TerminatorKind::SwitchInt { ref targets, .. } => { + for target in targets { + self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list); + } + } + + mir::TerminatorKind::Call { cleanup, ref destination, ref func, ref args, .. } => { + if let Some(unwind) = cleanup { + if !self.dead_unwinds.contains(bb) { + self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); + } + } + + if let Some((ref dest_place, dest_bb)) = *destination { + // N.B.: This must be done *last*, after all other + // propagation, as documented in comment above. + self.analysis.apply_call_return_effect(in_out, bb, func, args, dest_place); + self.propagate_bits_into_entry_set_for(in_out, dest_bb, dirty_list); + } + } + + mir::TerminatorKind::FalseEdges { real_target, imaginary_target } => { + self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list); + self.propagate_bits_into_entry_set_for(in_out, imaginary_target, dirty_list); + } + + mir::TerminatorKind::FalseUnwind { real_target, unwind } => { + self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list); + if let Some(unwind) = unwind { + if !self.dead_unwinds.contains(bb) { + self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); + } + } + } + } + } + + fn propagate_bits_into_entry_set_for( + &mut self, + in_out: &BitSet, + bb: BasicBlock, + dirty_queue: &mut WorkQueue, + ) { + let entry_set = &mut self.entry_sets[bb]; + let set_changed = self.analysis.join(entry_set, &in_out); + if set_changed { + dirty_queue.insert(bb); + } + } +} diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index d94ebdbae2..1c43a553cc 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,19 +93,10 @@ struct BorrowedLocalsVisitor<'gk> { } fn find_local(place: &Place<'_>) -> Option { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - if proj.elem == ProjectionElem::Deref { - return None; - } - } - - if let PlaceBase::Local(local) = place_base { - Some(*local) - } else { - None - } - }) + match place.base { + PlaceBase::Local(local) if !place.is_indirect() => Some(local), + _ => None, + } } impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> { diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 018fd2e97b..a86fcb30f4 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { // If the borrowed place is a local with no projections, all other borrows of this // local must conflict. This is purely an optimization so we don't have to call // `places_conflict` for every borrow. - if place.projection.is_none() { + if place.projection.is_empty() { trans.kill_all(other_borrows_of_local); return; } @@ -268,12 +268,8 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> { debug!("Borrows::statement_effect: stmt={:?}", stmt); match stmt.kind { - mir::StatementKind::Assign(ref lhs, ref rhs) => { - // Make sure there are no remaining borrows for variables - // that are assigned over. - self.kill_borrows_on_place(trans, lhs); - - if let mir::Rvalue::Ref(_, _, ref place) = **rhs { + mir::StatementKind::Assign(box(ref lhs, ref rhs)) => { + if let mir::Rvalue::Ref(_, _, ref place) = *rhs { if place.ignore_borrow( self.tcx, self.body, @@ -287,6 +283,10 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> { trans.gen(*index); } + + // Make sure there are no remaining borrows for variables + // that are assigned over. + self.kill_borrows_on_place(trans, lhs); } mir::StatementKind::StorageDead(local) => { diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 0e01701ea9..0f66b13fdc 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -119,8 +119,8 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { match stmt.kind { StatementKind::StorageLive(l) => sets.gen(l), StatementKind::StorageDead(l) => sets.kill(l), - StatementKind::Assign(ref place, _) - | StatementKind::SetDiscriminant { ref place, .. } => { + StatementKind::Assign(box(ref place, _)) + | StatementKind::SetDiscriminant { box ref place, .. } => { if let PlaceBase::Local(local) = place.base { sets.gen(local); } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 7fe2a890a5..5ab4e25b68 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -30,6 +30,7 @@ use self::move_paths::MoveData; mod at_location; pub mod drop_flag_effects; +pub mod generic; mod graphviz; mod impls; pub mod move_paths; @@ -56,7 +57,7 @@ where /// string (as well as that of rendering up-front); in exchange, you /// don't have to hand over ownership of your value or deal with /// borrowing it. -pub(crate) struct DebugFormatted(String); +pub struct DebugFormatted(String); impl DebugFormatted { pub fn new(input: &dyn fmt::Debug) -> DebugFormatted { @@ -70,7 +71,7 @@ impl fmt::Debug for DebugFormatted { } } -pub(crate) trait Dataflow<'tcx, BD: BitDenotation<'tcx>> { +pub trait Dataflow<'tcx, BD: BitDenotation<'tcx>> { /// Sets up and runs the dataflow problem, using `p` to render results if /// implementation so chooses. fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted { @@ -121,7 +122,7 @@ pub struct MoveDataParamEnv<'tcx> { pub(crate) param_env: ty::ParamEnv<'tcx>, } -pub(crate) fn do_dataflow<'a, 'tcx, BD, P>( +pub fn do_dataflow<'a, 'tcx, BD, P>( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, def_id: DefId, @@ -453,34 +454,10 @@ where { self.flow_state.each_gen_bit(f) } -} - -pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location, - analysis: &T, - result: &DataflowResults<'tcx, T>, - body: &Body<'tcx>) - -> BitSet { - let mut trans = GenKill::from_elem(HybridBitSet::new_empty(analysis.bits_per_block())); - for stmt in 0..loc.statement_index { - let mut stmt_loc = loc; - stmt_loc.statement_index = stmt; - analysis.before_statement_effect(&mut trans, stmt_loc); - analysis.statement_effect(&mut trans, stmt_loc); + pub fn get(&self) -> &BitSet { + self.flow_state.as_dense() } - - // Apply the pre-statement effect of the statement we're evaluating. - if loc.statement_index == body[loc.block].statements.len() { - analysis.before_terminator_effect(&mut trans, loc); - } else { - analysis.before_statement_effect(&mut trans, loc); - } - - // Apply the transfer function for all preceding statements to the fixpoint - // at the start of the block. - let mut state = result.sets().entry_set_for(loc.block.index()).to_owned(); - trans.apply(&mut state); - state } pub struct DataflowAnalysis<'a, 'tcx, O> @@ -565,7 +542,7 @@ pub struct GenKill { pub(crate) kill_set: T, } -type GenKillSet = GenKill>; +pub type GenKillSet = GenKill>; impl GenKill { /// Creates a new tuple where `gen_set == kill_set == elem`. @@ -580,28 +557,28 @@ impl GenKill { } impl GenKillSet { - pub(crate) fn clear(&mut self) { + pub fn clear(&mut self) { self.gen_set.clear(); self.kill_set.clear(); } - fn gen(&mut self, e: E) { + pub fn gen(&mut self, e: E) { self.gen_set.insert(e); self.kill_set.remove(e); } - fn gen_all(&mut self, i: impl IntoIterator>) { + pub fn gen_all(&mut self, i: impl IntoIterator>) { for j in i { self.gen(*j.borrow()); } } - fn kill(&mut self, e: E) { + pub fn kill(&mut self, e: E) { self.gen_set.remove(e); self.kill_set.insert(e); } - fn kill_all(&mut self, i: impl IntoIterator>) { + pub fn kill_all(&mut self, i: impl IntoIterator>) { for j in i { self.kill(*j.borrow()); } diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index b26547c4ff..d97f3b7417 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -11,7 +11,7 @@ //! `a[x]` would still overlap them both. But that is not this //! representation does today.) -use rustc::mir::{Local, PlaceElem, Operand, ProjectionElem}; +use rustc::mir::{Local, Operand, PlaceElem, ProjectionElem}; use rustc::ty::Ty; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -26,36 +26,36 @@ pub trait Lift { } impl<'tcx> Lift for Operand<'tcx> { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl Lift for Local { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl<'tcx> Lift for Ty<'tcx> { type Abstract = AbstractType; - fn lift(&self) -> Self::Abstract { AbstractType } + fn lift(&self) -> Self::Abstract { + AbstractType + } } impl<'tcx> Lift for PlaceElem<'tcx> { type Abstract = AbstractElem; fn lift(&self) -> Self::Abstract { match *self { - ProjectionElem::Deref => - ProjectionElem::Deref, - ProjectionElem::Field(ref f, ty) => - ProjectionElem::Field(f.clone(), ty.lift()), - ProjectionElem::Index(ref i) => - ProjectionElem::Index(i.lift()), - ProjectionElem::Subslice {from, to} => - ProjectionElem::Subslice { from: from, to: to }, - ProjectionElem::ConstantIndex {offset,min_length,from_end} => - ProjectionElem::ConstantIndex { - offset, - min_length, - from_end, - }, - ProjectionElem::Downcast(a, u) => - ProjectionElem::Downcast(a, u.clone()), + ProjectionElem::Deref => ProjectionElem::Deref, + ProjectionElem::Field(ref f, ty) => ProjectionElem::Field(f.clone(), ty.lift()), + ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()), + ProjectionElem::Subslice { from, to } => { + ProjectionElem::Subslice { from: from, to: to } + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u.clone()), } } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 366b96b53b..698c501662 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -1,16 +1,18 @@ -use rustc::ty::{self, TyCtxt}; -use rustc::mir::*; use rustc::mir::tcx::RvalueInitializationState; -use rustc_data_structures::indexed_vec::{IndexVec}; -use smallvec::{SmallVec, smallvec}; +use rustc::mir::*; +use rustc::ty::{self, TyCtxt}; +use rustc_data_structures::indexed_vec::IndexVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use std::mem; use super::abs_domain::Lift; -use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; -use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind}; use super::IllegalMoveOriginKind::*; +use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError}; +use super::{ + LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, +}; struct MoveDataBuilder<'a, 'tcx> { body: &'a Body<'tcx>, @@ -33,15 +35,19 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { moves: IndexVec::new(), loc_map: LocationMap::new(body), rev_lookup: MovePathLookup { - locals: body.local_decls.indices().map(|i| { - Self::new_move_path( - &mut move_paths, - &mut path_map, - &mut init_path_map, - None, - Place::from(i), - ) - }).collect(), + locals: body + .local_decls + .indices() + .map(|i| { + Self::new_move_path( + &mut move_paths, + &mut path_map, + &mut init_path_map, + None, + Place::from(i), + ) + }) + .collect(), projections: Default::default(), }, move_paths, @@ -49,27 +55,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { inits: IndexVec::new(), init_loc_map: LocationMap::new(body), init_path_map, - } + }, } } - fn new_move_path(move_paths: &mut IndexVec>, - path_map: &mut IndexVec>, - init_path_map: &mut IndexVec>, - parent: Option, - place: Place<'tcx>) - -> MovePathIndex - { - let move_path = move_paths.push(MovePath { - next_sibling: None, - first_child: None, - parent, - place, - }); + fn new_move_path( + move_paths: &mut IndexVec>, + path_map: &mut IndexVec>, + init_path_map: &mut IndexVec>, + parent: Option, + place: Place<'tcx>, + ) -> MovePathIndex { + let move_path = + move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place }); if let Some(parent) = parent { - let next_sibling = - mem::replace(&mut move_paths[parent].first_child, Some(move_path)); + let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path)); move_paths[move_path].next_sibling = next_sibling; } @@ -91,69 +92,76 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// problematic for borrowck. /// /// Maybe we should have separate "borrowck" and "moveck" modes. - fn move_path_for(&mut self, place: &Place<'tcx>) - -> Result> - { + fn move_path_for(&mut self, place: &Place<'tcx>) -> Result> { debug!("lookup({:?})", place); - place.iterate(|place_base, place_projection| { - let mut base = match place_base { - PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[*local], - PlaceBase::Static(..) => { - return Err(MoveError::cannot_move_out_of(self.loc, Static)); - } - }; + let mut base = match place.base { + PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[local], + PlaceBase::Static(..) => { + return Err(MoveError::cannot_move_out_of(self.loc, Static)); + } + }; - for proj in place_projection { - let body = self.builder.body; - let tcx = self.builder.tcx; - let place_ty = Place::ty_from(place_base, &proj.base, body, tcx).ty; - match place_ty.sty { - ty::Ref(..) | ty::RawPtr(..) => - return Err(MoveError::cannot_move_out_of( - self.loc, - BorrowedContent { - target_place: Place { - base: place_base.clone(), - projection: Some(Box::new(proj.clone())), - } - })), - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => - return Err(MoveError::cannot_move_out_of(self.loc, - InteriorOfTypeWithDestructor { - container_ty: place_ty - })), - // move out of union - always move the entire union - ty::Adt(adt, _) if adt.is_union() => - return Err(MoveError::UnionMove { path: base }), - ty::Slice(_) => + for (i, elem) in place.projection.iter().enumerate() { + let proj_base = &place.projection[..i]; + let body = self.builder.body; + let tcx = self.builder.tcx; + let place_ty = Place::ty_from(&place.base, proj_base, body, tcx).ty; + match place_ty.sty { + ty::Ref(..) | ty::RawPtr(..) => { + let proj = &place.projection[..i+1]; + return Err(MoveError::cannot_move_out_of( + self.loc, + BorrowedContent { + target_place: Place { + base: place.base.clone(), + projection: proj.to_vec().into_boxed_slice(), + }, + }, + )); + } + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfTypeWithDestructor { container_ty: place_ty }, + )); + } + // move out of union - always move the entire union + ty::Adt(adt, _) if adt.is_union() => { + return Err(MoveError::UnionMove { path: base }); + } + ty::Slice(_) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, + is_index: match elem { + ProjectionElem::Index(..) => true, + _ => false, + }, + }, + )); + } + ty::Array(..) => match elem { + ProjectionElem::Index(..) => { return Err(MoveError::cannot_move_out_of( self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: match proj.elem { - ProjectionElem::Index(..) => true, - _ => false - }, - })), - ty::Array(..) => match proj.elem { - ProjectionElem::Index(..) => - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: true - })), - _ => { - // FIXME: still badly broken - } - }, - _ => {} - }; + InteriorOfSliceOrArray { ty: place_ty, is_index: true }, + )); + } + _ => { + // FIXME: still badly broken + } + }, + _ => {} + }; - base = match self - .builder - .data - .rev_lookup - .projections - .entry((base, proj.elem.lift())) + let proj = &place.projection[..i+1]; + base = match self + .builder + .data + .rev_lookup + .projections + .entry((base, elem.lift())) { Entry::Occupied(ent) => *ent.get(), Entry::Vacant(ent) => { @@ -163,18 +171,17 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { &mut self.builder.data.init_path_map, Some(base), Place { - base: place_base.clone(), - projection: Some(Box::new(proj.clone())), + base: place.base.clone(), + projection: proj.to_vec().into_boxed_slice(), }, ); ent.insert(path); path } }; - } + } - Ok(base) - }) + Ok(base) } fn create_move_path(&mut self, place: &Place<'tcx>) { @@ -186,7 +193,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn finalize( - self + self, ) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { debug!("{}", { debug!("moves for {:?}:", self.body.span); @@ -200,11 +207,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { "done dumping moves" }); - if !self.errors.is_empty() { - Err((self.data, self.errors)) - } else { - Ok(self.data) - } + if !self.errors.is_empty() { Err((self.data, self.errors)) } else { Ok(self.data) } } } @@ -222,10 +225,7 @@ pub(super) fn gather_moves<'tcx>( builder.gather_statement(source, stmt); } - let terminator_loc = Location { - block: bb, - statement_index: block.statements.len() - }; + let terminator_loc = Location { block: bb, statement_index: block.statements.len() }; builder.gather_terminator(terminator_loc, block.terminator()); } @@ -238,11 +238,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { let path = self.data.rev_lookup.locals[arg]; let init = self.data.inits.push(Init { - path, kind: InitKind::Deep, location: InitLocation::Argument(arg), + path, + kind: InitKind::Deep, + location: InitLocation::Argument(arg), }); - debug!("gather_args: adding init {:?} of {:?} for argument {:?}", - init, path, arg); + debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg); self.data.init_path_map[path].push(init); } @@ -267,7 +268,7 @@ struct Gatherer<'b, 'a, 'tcx> { impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { match stmt.kind { - StatementKind::Assign(ref place, ref rval) => { + StatementKind::Assign(box(ref place, ref rval)) => { self.create_move_path(place); if let RvalueInitializationState::Shallow = rval.initialization_state() { // Box starts out uninitialized - need to create a separate @@ -297,26 +298,26 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { StatementKind::StorageDead(local) => { self.gather_move(&Place::from(local)); } - StatementKind::SetDiscriminant{ .. } => { - span_bug!(stmt.source_info.span, - "SetDiscriminant should not exist during borrowck"); + StatementKind::SetDiscriminant { .. } => { + span_bug!( + stmt.source_info.span, + "SetDiscriminant should not exist during borrowck" + ); } - StatementKind::Retag { .. } | - StatementKind::AscribeUserType(..) | - StatementKind::Nop => {} + StatementKind::Retag { .. } + | StatementKind::AscribeUserType(..) + | StatementKind::Nop => {} } } fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { match *rvalue { - Rvalue::Use(ref operand) | - Rvalue::Repeat(ref operand, _) | - Rvalue::Cast(_, ref operand, _) | - Rvalue::UnaryOp(_, ref operand) => { - self.gather_operand(operand) - } - Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | - Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { + Rvalue::Use(ref operand) + | Rvalue::Repeat(ref operand, _) + | Rvalue::Cast(_, ref operand, _) + | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), + Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) + | Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { self.gather_operand(lhs); self.gather_operand(rhs); } @@ -325,11 +326,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_operand(operand); } } - Rvalue::Ref(..) | - Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::NullaryOp(NullOp::SizeOf, _) | - Rvalue::NullaryOp(NullOp::Box, _) => { + Rvalue::Ref(..) + | Rvalue::Discriminant(..) + | Rvalue::Len(..) + | Rvalue::NullaryOp(NullOp::SizeOf, _) + | Rvalue::NullaryOp(NullOp::Box, _) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always // completely initialize their place. @@ -346,16 +347,16 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_terminator(&mut self, term: &Terminator<'tcx>) { match term.kind { - TerminatorKind::Goto { target: _ } | - TerminatorKind::Resume | - TerminatorKind::Abort | - TerminatorKind::GeneratorDrop | - TerminatorKind::FalseEdges { .. } | - TerminatorKind::FalseUnwind { .. } | - TerminatorKind::Unreachable => { } + TerminatorKind::Goto { target: _ } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Unreachable => {} TerminatorKind::Return => { - self.gather_move(&Place::RETURN_PLACE); + self.gather_move(&Place::return_place()); } TerminatorKind::Assert { ref cond, .. } => { @@ -399,9 +400,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_operand(&mut self, operand: &Operand<'tcx>) { match *operand { - Operand::Constant(..) | - Operand::Copy(..) => {} // not-a-move - Operand::Move(ref place) => { // a move + Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move + Operand::Move(ref place) => { + // a move self.gather_move(place); } } @@ -419,8 +420,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { }; let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); - debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", - self.loc, place, move_out, path); + debug!( + "gather_move({:?}, {:?}): adding move {:?} of {:?}", + self.loc, place, move_out, path + ); self.builder.data.path_map[path].push(move_out); self.builder.data.loc_map[self.loc].push(move_out); @@ -433,9 +436,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // Check if we are assigning into a field of a union, if so, lookup the place // of the union so it is marked as initialized again. - if let Some(box Projection { base: proj_base, elem: ProjectionElem::Field(_, _) }) = - place.projection - { + if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection { if let ty::Adt(def, _) = Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.sty { @@ -452,8 +453,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { kind, }); - debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}", - self.loc, place, init, path); + debug!( + "gather_init({:?}, {:?}): adding init {:?} of {:?}", + self.loc, place, init, path + ); self.builder.data.init_path_map[path].push(init); self.builder.data.init_loc_map[self.loc].push(init); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 5c2255882b..156c19c636 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,9 +1,10 @@ -use rustc::ty::{Ty, TyCtxt}; +use core::slice::Iter; use rustc::mir::*; +use rustc::ty::{Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Enumerated, Idx, IndexVec}; use smallvec::SmallVec; -use syntax_pos::{Span}; +use syntax_pos::Span; use std::fmt; use std::ops::{Index, IndexMut}; @@ -137,12 +138,17 @@ impl IndexMut for LocationMap { } } -impl LocationMap where T: Default + Clone { +impl LocationMap +where + T: Default + Clone, +{ fn new(body: &Body<'_>) -> Self { LocationMap { - map: body.basic_blocks().iter().map(|block| { - vec![T::default(); block.statements.len()+1] - }).collect() + map: body + .basic_blocks() + .iter() + .map(|block| vec![T::default(); block.statements.len() + 1]) + .collect(), } } } @@ -178,7 +184,6 @@ pub struct Init { pub kind: InitKind, } - /// Initializations can be from an argument or from a statement. Arguments /// do not have locations, in those cases the `Local` is kept.. #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -224,7 +229,7 @@ pub struct MovePathLookup { /// subsequent search so that it is solely relative to that /// base-place). For the remaining lookup, we map the projection /// elem to the associated MovePathIndex. - projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex> + projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>, } mod builder; @@ -232,7 +237,7 @@ mod builder; #[derive(Copy, Clone, Debug)] pub enum LookupResult { Exact(MovePathIndex), - Parent(Option) + Parent(Option), } impl MovePathLookup { @@ -240,28 +245,32 @@ impl MovePathLookup { // alternative will *not* create a MovePath on the fly for an // unknown place, but will rather return the nearest available // parent. - pub fn find(&self, place_ref: PlaceRef<'cx, 'tcx>) -> LookupResult { - place_ref.iterate(|place_base, place_projection| { - let mut result = match place_base { - PlaceBase::Local(local) => self.locals[*local], - PlaceBase::Static(..) => return LookupResult::Parent(None), - }; - - for proj in place_projection { - if let Some(&subpath) = self.projections.get(&(result, proj.elem.lift())) { - result = subpath; - } else { - return LookupResult::Parent(Some(result)); - } + pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult { + let mut result = match place.base { + PlaceBase::Local(local) => self.locals[*local], + PlaceBase::Static(..) => return LookupResult::Parent(None), + }; + + for elem in place.projection.iter() { + if let Some(&subpath) = self.projections.get(&(result, elem.lift())) { + result = subpath; + } else { + return LookupResult::Parent(Some(result)); } + } - LookupResult::Exact(result) - }) + LookupResult::Exact(result) } pub fn find_local(&self, local: Local) -> MovePathIndex { self.locals[local] } + + /// An enumerated iterator of `local`s and their associated + /// `MovePathIndex`es. + pub fn iter_locals_enumerated(&self) -> Enumerated> { + self.locals.iter_enumerated() + } } #[derive(Debug)] @@ -289,7 +298,7 @@ pub(crate) enum IllegalMoveOriginKind<'tcx> { InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> }, /// Illegal move due to attempt to move out of a slice or array. - InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool, }, + InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool }, } #[derive(Debug)] @@ -318,11 +327,15 @@ impl<'tcx> MoveData<'tcx> { pub fn base_local(&self, mut mpi: MovePathIndex) -> Option { loop { let path = &self.move_paths[mpi]; - if let Place { - base: PlaceBase::Local(l), - projection: None, - } = path.place { return Some(l); } - if let Some(parent) = path.parent { mpi = parent; continue } else { return None } + if let Place { base: PlaceBase::Local(l), projection: box [] } = path.place { + return Some(l); + } + if let Some(parent) = path.parent { + mpi = parent; + continue; + } else { + return None; + } } } } diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 86c263a447..ba299e9463 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0001: r##" @@ -157,81 +157,6 @@ match x { See also the error E0303. "##, -E0008: r##" -Names bound in match arms retain their type in pattern guards. As such, if a -name is bound by move in a pattern, it should also be moved to wherever it is -referenced in the pattern guard code. Doing so however would prevent the name -from being available in the body of the match arm. Consider the following: - -```compile_fail,E0008 -match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, // use s. - _ => {}, -} -``` - -The variable `s` has type `String`, and its use in the guard is as a variable of -type `String`. The guard code effectively executes in a separate scope to the -body of the arm, so the value would be moved into this anonymous scope and -therefore becomes unavailable in the body of the arm. - -The problem above can be solved by using the `ref` keyword. - -``` -match Some("hi".to_string()) { - Some(ref s) if s.len() == 0 => {}, - _ => {}, -} -``` - -Though this example seems innocuous and easy to solve, the problem becomes clear -when it encounters functions which consume the value: - -```compile_fail,E0008 -struct A{} - -impl A { - fn consume(self) -> usize { - 0 - } -} - -fn main() { - let a = Some(A{}); - match a { - Some(y) if y.consume() > 0 => {} - _ => {} - } -} -``` - -In this situation, even the `ref` keyword cannot solve it, since borrowed -content cannot be moved. This problem cannot be solved generally. If the value -can be cloned, here is a not-so-specific solution: - -``` -#[derive(Clone)] -struct A{} - -impl A { - fn consume(self) -> usize { - 0 - } -} - -fn main() { - let a = Some(A{}); - match a{ - Some(ref y) if y.clone().consume() > 0 => {} - _ => {} - } -} -``` - -If the value will be consumed in the pattern guard, using its clone will not -move its ownership, so the code works. -"##, - E0009: r##" In a pattern, all values that don't implement the `Copy` trait have to be bound the same way. The goal here is to avoid binding simultaneously by-move and @@ -475,13 +400,15 @@ for item in xs { "##, E0301: r##" +#### Note: this error code is no longer emitted by the compiler. + Mutable borrows are not allowed in pattern guards, because matching cannot have side effects. Side effects could alter the matched object or the environment on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if mutable borrows were allowed: -```compile_fail,E0301 +```compile_fail,E0596 match Some(()) { None => { }, option if option.take().is_none() => { @@ -493,13 +420,15 @@ match Some(()) { "##, E0302: r##" +#### Note: this error code is no longer emitted by the compiler. + Assignments are not allowed in pattern guards, because matching cannot have side effects. Side effects could alter the matched object or the environment on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if assignments were allowed: -```compile_fail,E0302 +```compile_fail,E0594 match Some(()) { None => { }, option if { option = None; false } => { }, @@ -748,7 +677,7 @@ It is not allowed to use or capture an uninitialized variable. For example: ```compile_fail,E0381 fn main() { let x: i32; - let y = x; // error, use of possibly uninitialized variable + let y = x; // error, use of possibly-uninitialized variable } ``` @@ -1717,7 +1646,14 @@ fn print_fancy_ref(fancy_ref: &FancyNum){ "##, E0507: r##" -You tried to move out of a value which was borrowed. Erroneous code example: +You tried to move out of a value which was borrowed. + +This can also happen when using a type implementing `Fn` or `FnMut`, as neither +allows moving out of them (they usually represent closures which can be called +more than once). Much of the text following applies equally well to non-`FnOnce` +closure bodies. + +Erroneous code example: ```compile_fail,E0507 use std::cell::RefCell; @@ -1989,7 +1925,6 @@ When matching on a variable it cannot be mutated in the match guards, as this could cause the match to be non-exhaustive: ```compile_fail,E0510 -#![feature(bind_by_move_pattern_guards)] let mut x = Some(0); match x { None => (), @@ -2448,9 +2383,10 @@ information. There are some known bugs that trigger this message. "##, -} -register_diagnostics! { +; + +// E0008, // cannot bind by-move into a pattern guard // E0298, // cannot compare constants // E0299, // mismatched types between arms // E0471, // constant evaluation error (in pattern) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1c6a743155..a33d7207ed 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -927,7 +927,7 @@ fn convert_path_expr<'a, 'tcx>( ExprKind::Literal { literal: cx.tcx.mk_const(ty::Const { val: ConstValue::Unevaluated(def_id, substs), - ty: cx.tcx.type_of(def_id), + ty: cx.tables().node_type(expr.hir_id), }), user_ty, } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3d9349df5b..740dc2011c 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -170,13 +170,13 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { method_name: Symbol, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { + -> &'tcx ty::Const<'tcx> { let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssocKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); + return ty::Const::zero_sized(self.tcx, method_ty); } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 8a3d904e77..a6d955f336 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -517,9 +517,9 @@ struct PatternContext<'tcx> { pub struct Witness<'tcx>(Vec>); impl<'tcx> Witness<'tcx> { - pub fn single_pattern(&self) -> &Pattern<'tcx> { + pub fn single_pattern(self) -> Pattern<'tcx> { assert_eq!(self.0.len(), 1); - &self.0[0] + self.0.into_iter().next().unwrap() } fn push_wild_constructor<'a>( @@ -609,7 +609,6 @@ impl<'tcx> Witness<'tcx> { ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), - ty, end, }), _ => PatternKind::Wild, @@ -880,10 +879,10 @@ impl<'tcx> IntRange<'tcx> { let range = loop { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), - box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.eval_bits(tcx, param_env, ty), - hi.eval_bits(tcx, param_env, ty), - ty, + box PatternKind::Range(PatternRange { lo, hi, end }) => break ConstantRange( + lo.eval_bits(tcx, param_env, lo.ty), + hi.eval_bits(tcx, param_env, hi.ty), + lo.ty, end, ), box PatternKind::AscribeUserType { ref subpattern, .. } => { @@ -1339,11 +1338,11 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), - PatternKind::Range(PatternRange { lo, hi, ty, end }) => + PatternKind::Range(PatternRange { lo, hi, end }) => Some(vec![ConstantRange( - lo.eval_bits(cx.tcx, cx.param_env, ty), - hi.eval_bits(cx.tcx, cx.param_env, ty), - ty, + lo.eval_bits(cx.tcx, cx.param_env, lo.ty), + hi.eval_bits(cx.tcx, cx.param_env, hi.ty), + lo.ty, end, )]), PatternKind::Array { .. } => match pcx.ty.sty { @@ -1360,6 +1359,9 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Slice(pat_len)]) } } + PatternKind::Or { .. } => { + bug!("support for or-patterns has not been fully implemented yet."); + } } } @@ -1656,7 +1658,7 @@ fn constructor_covered_by_range<'tcx>( ) -> Result { let (from, to, end, ty) = match pat.kind { box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), - box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty), + box PatternKind::Range(PatternRange { lo, hi, end }) => (lo, hi, end, lo.ty), _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); @@ -1885,6 +1887,10 @@ fn specialize<'p, 'a: 'p, 'tcx>( "unexpected ctor {:?} for slice pat", constructor) } } + + PatternKind::Or { .. } => { + bug!("support for or-patterns has not been fully implemented yet."); + } }; debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head); diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 17fd9377a1..161c58a175 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -5,11 +5,6 @@ use super::_match::WitnessPreference::*; use super::{Pattern, PatternContext, PatternError, PatternKind}; use rustc::middle::borrowck::SignalledError; -use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; -use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; -use rustc::middle::expr_use_visitor as euv; -use rustc::middle::mem_categorization::cmt_; -use rustc::middle::region; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -36,9 +31,7 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError { let mut visitor = MatchVisitor { tcx, - body_owner: def_id, tables: tcx.body_tables(body_id), - region_scope_tree: &tcx.region_scope_tree(def_id), param_env: tcx.param_env(def_id), identity_substs: InternalSubsts::identity_for_item(tcx, def_id), signalled_error: SignalledError::NoErrorsSeen, @@ -53,15 +46,13 @@ fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBu struct MatchVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body_owner: DefId, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, identity_substs: SubstsRef<'tcx>, - region_scope_tree: &'a region::ScopeTree, signalled_error: SignalledError, } -impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } @@ -91,15 +82,14 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn visit_body(&mut self, body: &'tcx hir::Body) { intravisit::walk_body(self, body); - for arg in &body.arguments { - self.check_irrefutable(&arg.pat, "function argument"); - self.check_patterns(false, slice::from_ref(&arg.pat)); + for param in &body.params { + self.check_irrefutable(¶m.pat, "function argument"); + self.check_patterns(false, slice::from_ref(¶m.pat)); } } } - -impl<'a, 'tcx> PatternContext<'a, 'tcx> { +impl PatternContext<'_, '_> { fn report_inlining_errors(&self, pat_span: Span) { for error in &self.errors { match *error { @@ -131,7 +121,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } -impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { +impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_patterns(&mut self, has_guard: bool, pats: &[P]) { check_legality_of_move_bindings(self, has_guard, pats); for pat in pats { @@ -151,11 +141,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. - if let Some(ref guard) = arm.guard { + if arm.guard.is_some() { self.signalled_error = SignalledError::SawSomeError; - if !self.tcx.features().bind_by_move_pattern_guards { - check_for_mutation_in_guard(self, &guard); - } } // Third, perform some lints. @@ -277,37 +264,26 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { expand_pattern(cx, pattern) ]].into_iter().collect(); - let wild_pattern = Pattern { - ty: pattern_ty, - span: DUMMY_SP, - kind: box PatternKind::Wild, - }; - let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) { - UsefulWithWitness(witness) => witness, - NotUseful => return, - Useful => bug!() + let witnesses = match check_not_useful(cx, pattern_ty, &pats) { + Ok(_) => return, + Err(err) => err, }; - let pattern_string = witness[0].single_pattern().to_string(); + let joined_patterns = joined_uncovered_patterns(&witnesses); let mut err = struct_span_err!( self.tcx.sess, pat.span, E0005, - "refutable pattern in {}: `{}` not covered", - origin, pattern_string + "refutable pattern in {}: {} not covered", + origin, joined_patterns ); - let label_msg = match pat.node { - PatKind::Path(hir::QPath::Resolved(None, ref path)) - if path.segments.len() == 1 && path.segments[0].args.is_none() => { + err.span_label(pat.span, match &pat.node { + PatKind::Path(hir::QPath::Resolved(None, path)) + if path.segments.len() == 1 && path.segments[0].args.is_none() => { format!("interpreted as {} {} pattern, not new variable", path.res.article(), path.res.descr()) } - _ => format!("pattern `{}` not covered", pattern_string), - }; - err.span_label(pat.span, label_msg); - if let ty::Adt(def, _) = pattern_ty.sty { - if let Some(sp) = self.tcx.hir().span_if_local(def.did){ - err.span_label(sp, format!("`{}` defined here", pattern_ty)); - } - } + _ => pattern_not_convered_label(&witnesses, &joined_patterns), + }); + adt_defined_here(cx, &mut err, pattern_ty, &witnesses); err.emit(); }); } @@ -362,9 +338,9 @@ fn pat_is_catchall(pat: &Pat) -> bool { } // Check for unreachable patterns -fn check_arms<'a, 'tcx>( - cx: &mut MatchCheckCtxt<'a, 'tcx>, - arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)], +fn check_arms<'tcx>( + cx: &mut MatchCheckCtxt<'_, 'tcx>, + arms: &[(Vec<(&Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)], source: hir::MatchSource, ) { let mut seen = Matrix::empty(); @@ -445,104 +421,124 @@ fn check_arms<'a, 'tcx>( } } -fn check_exhaustive<'p, 'a, 'tcx>( - cx: &mut MatchCheckCtxt<'a, 'tcx>, +fn check_not_useful( + cx: &mut MatchCheckCtxt<'_, 'tcx>, + ty: Ty<'tcx>, + matrix: &Matrix<'_, 'tcx>, +) -> Result<(), Vec>> { + let wild_pattern = Pattern { ty, span: DUMMY_SP, kind: box PatternKind::Wild }; + match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) { + NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable. + UsefulWithWitness(pats) => Err(if pats.is_empty() { + vec![wild_pattern] + } else { + pats.into_iter().map(|w| w.single_pattern()).collect() + }), + Useful => bug!(), + } +} + +fn check_exhaustive<'tcx>( + cx: &mut MatchCheckCtxt<'_, 'tcx>, scrut_ty: Ty<'tcx>, sp: Span, - matrix: &Matrix<'p, 'tcx>, + matrix: &Matrix<'_, 'tcx>, ) { - let wild_pattern = Pattern { - ty: scrut_ty, - span: DUMMY_SP, - kind: box PatternKind::Wild, + let witnesses = match check_not_useful(cx, scrut_ty, matrix) { + Ok(_) => return, + Err(err) => err, }; - match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) { - UsefulWithWitness(pats) => { - let witnesses = if pats.is_empty() { - vec![&wild_pattern] - } else { - pats.iter().map(|w| w.single_pattern()).collect() - }; - const LIMIT: usize = 3; - let joined_patterns = match witnesses.len() { - 0 => bug!(), - 1 => format!("`{}`", witnesses[0]), - 2..=LIMIT => { - let (tail, head) = witnesses.split_last().unwrap(); - let head: Vec<_> = head.iter().map(|w| w.to_string()).collect(); - format!("`{}` and `{}`", head.join("`, `"), tail) - } - _ => { - let (head, tail) = witnesses.split_at(LIMIT); - let head: Vec<_> = head.iter().map(|w| w.to_string()).collect(); - format!("`{}` and {} more", head.join("`, `"), tail.len()) - } - }; + let joined_patterns = joined_uncovered_patterns(&witnesses); + let mut err = create_e0004( + cx.tcx.sess, sp, + format!("non-exhaustive patterns: {} not covered", joined_patterns), + ); + err.span_label(sp, pattern_not_convered_label(&witnesses, &joined_patterns)); + adt_defined_here(cx, &mut err, scrut_ty, &witnesses); + err.help( + "ensure that all possible cases are being handled, \ + possibly by adding wildcards or more match arms" + ) + .emit(); +} - let label_text = match witnesses.len() { - 1 => format!("pattern {} not covered", joined_patterns), - _ => format!("patterns {} not covered", joined_patterns), - }; - let mut err = create_e0004(cx.tcx.sess, sp, format!( - "non-exhaustive patterns: {} not covered", - joined_patterns, - )); - err.span_label(sp, label_text); - // point at the definition of non-covered enum variants - if let ty::Adt(def, _) = scrut_ty.sty { - if let Some(sp) = cx.tcx.hir().span_if_local(def.did){ - err.span_label(sp, format!("`{}` defined here", scrut_ty)); - } - } - let patterns = witnesses.iter().map(|p| (**p).clone()).collect::>>(); - if patterns.len() < 4 { - for sp in maybe_point_at_variant(cx, scrut_ty, patterns.as_slice()) { - err.span_label(sp, "not covered"); - } - } - err.help("ensure that all possible cases are being handled, \ - possibly by adding wildcards or more match arms"); - err.emit(); +fn joined_uncovered_patterns(witnesses: &[Pattern<'_>]) -> String { + const LIMIT: usize = 3; + match witnesses { + [] => bug!(), + [witness] => format!("`{}`", witness), + [head @ .., tail] if head.len() < LIMIT => { + let head: Vec<_> = head.iter().map(<_>::to_string).collect(); + format!("`{}` and `{}`", head.join("`, `"), tail) } - NotUseful => { - // This is good, wildcard pattern isn't reachable + _ => { + let (head, tail) = witnesses.split_at(LIMIT); + let head: Vec<_> = head.iter().map(<_>::to_string).collect(); + format!("`{}` and {} more", head.join("`, `"), tail.len()) } - _ => bug!() } } -fn maybe_point_at_variant( - cx: &mut MatchCheckCtxt<'a, 'tcx>, - ty: Ty<'tcx>, - patterns: &[Pattern<'_>], -) -> Vec { +fn pattern_not_convered_label(witnesses: &[Pattern<'_>], joined_patterns: &str) -> String { + format!("pattern{} {} not covered", rustc_errors::pluralise!(witnesses.len()), joined_patterns) +} + +/// Point at the definition of non-covered `enum` variants. +fn adt_defined_here( + cx: &MatchCheckCtxt<'_, '_>, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + witnesses: &[Pattern<'_>], +) { + let ty = ty.peel_refs(); + if let ty::Adt(def, _) = ty.sty { + if let Some(sp) = cx.tcx.hir().span_if_local(def.did) { + err.span_label(sp, format!("`{}` defined here", ty)); + } + + if witnesses.len() < 4 { + for sp in maybe_point_at_variant(ty, &witnesses) { + err.span_label(sp, "not covered"); + } + } + } +} + +fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec { let mut covered = vec![]; if let ty::Adt(def, _) = ty.sty { // Don't point at variants that have already been covered due to other patterns to avoid - // visual clutter + // visual clutter. for pattern in patterns { - let pk: &PatternKind<'_> = &pattern.kind; - if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk { - if adt_def.did == def.did { + use PatternKind::{AscribeUserType, Deref, Variant, Or, Leaf}; + match &*pattern.kind { + AscribeUserType { subpattern, .. } | Deref { subpattern } => { + covered.extend(maybe_point_at_variant(ty, slice::from_ref(&subpattern))); + } + Variant { adt_def, variant_index, subpatterns, .. } if adt_def.did == def.did => { let sp = def.variants[*variant_index].ident.span; if covered.contains(&sp) { continue; } covered.push(sp); - let subpatterns = subpatterns.iter() + + let pats = subpatterns.iter() .map(|field_pattern| field_pattern.pattern.clone()) - .collect::>(); - covered.extend( - maybe_point_at_variant(cx, ty, subpatterns.as_slice()), - ); + .collect::>(); + covered.extend(maybe_point_at_variant(ty, &pats)); } - } - if let PatternKind::Leaf { subpatterns } = pk { - let subpatterns = subpatterns.iter() - .map(|field_pattern| field_pattern.pattern.clone()) - .collect::>(); - covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice())); + Leaf { subpatterns } => { + let pats = subpatterns.iter() + .map(|field_pattern| field_pattern.pattern.clone()) + .collect::>(); + covered.extend(maybe_point_at_variant(ty, &pats)); + } + Or { pats } => { + let pats = pats.iter().cloned().collect::>(); + covered.extend(maybe_point_at_variant(ty, &pats)); + } + _ => {} } } } @@ -582,19 +578,10 @@ fn check_legality_of_move_bindings( "cannot bind by-move with sub-bindings") .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); - } else if has_guard { - if !cx.tcx.features().bind_by_move_pattern_guards { - let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008, - "cannot bind by-move into a pattern guard"); - err.span_label(p.span, "moves value into pattern guard"); - if cx.tcx.sess.opts.unstable_features.is_nightly_build() { - err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ - crate attributes to enable"); - } - err.emit(); + } else if !has_guard { + if let Some(_by_ref_span) = by_ref_span { + span_vec.push(p.span); } - } else if let Some(_by_ref_span) = by_ref_span { - span_vec.push(p.span); } }; @@ -636,67 +623,6 @@ fn check_legality_of_move_bindings( } } -/// Ensures that a pattern guard doesn't borrow by mutable reference or assign. -// -// FIXME: this should be done by borrowck. -fn check_for_mutation_in_guard(cx: &MatchVisitor<'_, '_>, guard: &hir::Guard) { - let mut checker = MutationChecker { - cx, - }; - match guard { - hir::Guard::If(expr) => - ExprUseVisitor::new(&mut checker, - cx.tcx, - cx.body_owner, - cx.param_env, - cx.region_scope_tree, - cx.tables, - None).walk_expr(expr), - }; -} - -struct MutationChecker<'a, 'tcx> { - cx: &'a MatchVisitor<'a, 'tcx>, -} - -impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { - fn matched_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: euv::MatchMode) {} - fn consume(&mut self, _: hir::HirId, _: Span, _: &cmt_<'_>, _: ConsumeMode) {} - fn consume_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: ConsumeMode) {} - fn borrow(&mut self, - _: hir::HirId, - span: Span, - _: &cmt_<'_>, - _: ty::Region<'tcx>, - kind:ty:: BorrowKind, - _: LoanCause) { - match kind { - ty::MutBorrow => { - let mut err = struct_span_err!(self.cx.tcx.sess, span, E0301, - "cannot mutably borrow in a pattern guard"); - err.span_label(span, "borrowed mutably in pattern guard"); - if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() { - err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ - crate attributes to enable"); - } - err.emit(); - } - ty::ImmBorrow | ty::UniqueImmBorrow => {} - } - } - fn decl_without_init(&mut self, _: hir::HirId, _: Span) {} - fn mutate(&mut self, _: hir::HirId, span: Span, _: &cmt_<'_>, mode: MutateMode) { - match mode { - MutateMode::JustWrite | MutateMode::WriteAndRead => { - struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") - .span_label(span, "assignment in pattern guard") - .emit(); - } - MutateMode::Init => {} - } - } -} - /// Forbids bindings in `@` patterns. This is necessary for memory safety, /// because of the way rvalues are handled in the borrow check. (See issue /// #14587.) @@ -709,7 +635,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> { bindings_allowed: bool } -impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { +impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index c82bb5d2ed..4aaa5e8ee2 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -175,18 +175,35 @@ pub enum PatternKind<'tcx> { slice: Option>, suffix: Vec>, }, + + /// An or-pattern, e.g. `p | q`. + /// Invariant: `pats.len() >= 2`. + Or { + pats: Vec>, + }, } #[derive(Copy, Clone, Debug, PartialEq)] pub struct PatternRange<'tcx> { pub lo: &'tcx ty::Const<'tcx>, pub hi: &'tcx ty::Const<'tcx>, - pub ty: Ty<'tcx>, pub end: RangeEnd, } impl<'tcx> fmt::Display for Pattern<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Printing lists is a chore. + let mut first = true; + let mut start_or_continue = |s| { + if first { + first = false; + "" + } else { + s + } + }; + let mut start_or_comma = || start_or_continue(", "); + match *self.kind { PatternKind::Wild => write!(f, "_"), PatternKind::AscribeUserType { ref subpattern, .. } => @@ -225,9 +242,6 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } }; - let mut first = true; - let mut start_or_continue = || if first { first = false; "" } else { ", " }; - if let Some(variant) = variant { write!(f, "{}", variant.ident)?; @@ -242,12 +256,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { continue; } let name = variant.fields[p.field.index()].ident; - write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?; + write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; printed += 1; } if printed < variant.fields.len() { - write!(f, "{}..", start_or_continue())?; + write!(f, "{}..", start_or_comma())?; } return write!(f, " }}"); @@ -258,7 +272,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { if num_fields != 0 || variant.is_none() { write!(f, "(")?; for i in 0..num_fields { - write!(f, "{}", start_or_continue())?; + write!(f, "{}", start_or_comma())?; // Common case: the field is where we expect it. if let Some(p) = subpatterns.get(i) { @@ -296,7 +310,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { write!(f, "{}", value) } - PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { + PatternKind::Range(PatternRange { lo, hi, end }) => { write!(f, "{}", lo)?; match end { RangeEnd::Included => write!(f, "..=")?, @@ -306,14 +320,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } PatternKind::Slice { ref prefix, ref slice, ref suffix } | PatternKind::Array { ref prefix, ref slice, ref suffix } => { - let mut first = true; - let mut start_or_continue = || if first { first = false; "" } else { ", " }; write!(f, "[")?; for p in prefix { - write!(f, "{}{}", start_or_continue(), p)?; + write!(f, "{}{}", start_or_comma(), p)?; } if let Some(ref slice) = *slice { - write!(f, "{}", start_or_continue())?; + write!(f, "{}", start_or_comma())?; match *slice.kind { PatternKind::Wild => {} _ => write!(f, "{}", slice)? @@ -321,10 +333,16 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { write!(f, "..")?; } for p in suffix { - write!(f, "{}{}", start_or_continue(), p)?; + write!(f, "{}{}", start_or_comma(), p)?; } write!(f, "]") } + PatternKind::Or { ref pats } => { + for pat in pats { + write!(f, "{}{}", start_or_continue(" | "), pat)?; + } + Ok(()) + } } } } @@ -442,6 +460,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let mut kind = match (lo, hi) { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { + assert_eq!(lo.ty, ty); + assert_eq!(hi.ty, ty); let cmp = compare_const_vals( self.tcx, lo, @@ -451,7 +471,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range(PatternRange { lo, hi, ty, end }), + PatternKind::Range(PatternRange { lo, hi, end }), (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -465,7 +485,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Constant { value: lo } } (RangeEnd::Included, Some(Ordering::Less)) => { - PatternKind::Range(PatternRange { lo, hi, ty, end }) + PatternKind::Range(PatternRange { lo, hi, end }) } (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -645,15 +665,21 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fields.iter() .map(|field| { FieldPattern { - field: Field::new(self.tcx.field_index(field.node.hir_id, + field: Field::new(self.tcx.field_index(field.hir_id, self.tables)), - pattern: self.lower_pattern(&field.node.pat), + pattern: self.lower_pattern(&field.pat), } }) .collect(); self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns) } + + PatKind::Or(ref pats) => { + PatternKind::Or { + pats: pats.iter().map(|p| self.lower_pattern(p)).collect(), + } + } }; Pattern { @@ -1422,17 +1448,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Constant { value, }, - PatternKind::Range(PatternRange { - lo, - hi, - ty, - end, - }) => PatternKind::Range(PatternRange { - lo, - hi, - ty: ty.fold_with(folder), - end, - }), + PatternKind::Range(range) => PatternKind::Range(range), PatternKind::Slice { ref prefix, ref slice, @@ -1451,6 +1467,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { slice: slice.fold_with(folder), suffix: suffix.fold_with(folder) }, + PatternKind::Or { ref pats } => PatternKind::Or { pats: pats.fold_with(folder) }, } } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 26cfbfe53a..210647ac1e 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,4 +1,4 @@ -use rustc::ty::{self, Ty, TypeAndMut}; +use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc::ty::layout::{self, TyLayout, Size}; use rustc::ty::adjustment::{PointerCast}; use syntax::ast::FloatTy; @@ -36,15 +36,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The src operand does not matter, just its type match src.layout.ty.sty { ty::FnDef(def_id, substs) => { + // All reifications must be monomorphic, bail out otherwise. + if src.layout.ty.needs_subst() { + throw_inval!(TooGeneric); + } + if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { bug!("reifying a fn ptr that requires const arguments"); } - let instance = ty::Instance::resolve( - *self.tcx, - self.param_env, - def_id, - substs, - ).ok_or_else(|| err_inval!(TooGeneric))?; + let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } @@ -67,7 +67,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The src operand does not matter, just its type match src.layout.ty.sty { ty::Closure(def_id, substs) => { - let substs = self.subst_and_normalize_erasing_regions(substs)?; + // All reifications must be monomorphic, bail out otherwise. + if src.layout.ty.needs_subst() { + throw_inval!(TooGeneric); + } + let instance = ty::Instance::resolve_closure( *self.tcx, def_id, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 6f4227ed34..78996ed693 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -9,12 +9,11 @@ use rustc::mir; use rustc::ty::layout::{ self, Size, Align, HasDataLayout, LayoutOf, TyLayout }; -use rustc::ty::subst::{Subst, SubstsRef}; +use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::query::TyCtxtAt; use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::interpret::{ - ErrorHandled, GlobalId, Scalar, Pointer, FrameInfo, AllocId, InterpResult, truncate, sign_extend, }; @@ -291,44 +290,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP) } - pub(super) fn subst_and_normalize_erasing_regions>( - &self, - substs: T, - ) -> InterpResult<'tcx, T> { - match self.stack.last() { - Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions( - frame.instance.substs, - self.param_env, - &substs, - )), - None => if substs.needs_subst() { - throw_inval!(TooGeneric) - } else { - Ok(substs) - }, - } - } - - pub(super) fn resolve( - &self, - def_id: DefId, - substs: SubstsRef<'tcx> - ) -> InterpResult<'tcx, ty::Instance<'tcx>> { - trace!("resolve: {:?}, {:#?}", def_id, substs); - trace!("param_env: {:#?}", self.param_env); - let substs = self.subst_and_normalize_erasing_regions(substs)?; - trace!("substs: {:#?}", substs); - ty::Instance::resolve( - *self.tcx, - self.param_env, - def_id, - substs, - ).ok_or_else(|| err_inval!(TooGeneric).into()) - } - pub fn load_mir( &self, instance: ty::InstanceDef<'tcx>, + promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); @@ -338,7 +303,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { { throw_inval!(TypeckError) } - trace!("load mir {:?}", instance); + trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); + if let Some(promoted) = promoted { + return Ok(&self.tcx.promoted_mir(did)[promoted]); + } match instance { ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did)) @@ -349,34 +317,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - pub(super) fn monomorphize + Subst<'tcx>>( + /// Call this on things you got out of the MIR (so it is as generic as the current + /// stack frame), to bring it into the proper environment for this interpreter. + pub(super) fn subst_from_frame_and_normalize_erasing_regions>( &self, - t: T, - ) -> InterpResult<'tcx, T> { - match self.stack.last() { - Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)?), - None => if t.needs_subst() { - throw_inval!(TooGeneric) - } else { - Ok(t) - }, - } + value: T, + ) -> T { + self.tcx.subst_and_normalize_erasing_regions( + self.frame().instance.substs, + self.param_env, + &value, + ) } - fn monomorphize_with_substs + Subst<'tcx>>( + /// The `substs` are assumed to already be in our interpreter "universe" (param_env). + pub(super) fn resolve( &self, - t: T, + def_id: DefId, substs: SubstsRef<'tcx> - ) -> InterpResult<'tcx, T> { - // miri doesn't care about lifetimes, and will choke on some crazy ones - // let's simply get rid of them - let substituted = t.subst(*self.tcx, substs); - - if substituted.needs_subst() { - throw_inval!(TooGeneric) - } - - Ok(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted)) + ) -> InterpResult<'tcx, ty::Instance<'tcx>> { + trace!("resolve: {:?}, {:#?}", def_id, substs); + trace!("param_env: {:#?}", self.param_env); + trace!("substs: {:#?}", substs); + ty::Instance::resolve( + *self.tcx, + self.param_env, + def_id, + substs, + ).ok_or_else(|| err_inval!(TooGeneric).into()) } pub fn layout_of_local( @@ -391,7 +359,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { None => { let layout = crate::interpret::operand::from_known_layout(layout, || { let local_ty = frame.body.local_decls[local].ty; - let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?; + let local_ty = self.tcx.subst_and_normalize_erasing_regions( + frame.instance.substs, + self.param_env, + &local_ty, + ); self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { @@ -469,27 +441,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Issue #27023: must add any necessary padding to `size` // (to make it a multiple of `align`) before returning it. - // - // Namely, the returned size should be, in C notation: - // - // `size + ((size & (align-1)) ? align : 0)` - // - // emulated via the semi-standard fast bit trick: - // - // `(size + (align-1)) & -align` - - Ok(Some((size.align_to(align), align))) + let size = size.align_to(align); + + // Check if this brought us over the size limit. + if size.bytes() >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("wide pointer metadata contains invalid information: \ + total size is bigger than largest supported object"); + } + Ok(Some((size, align))) } ty::Dynamic(..) => { let vtable = metadata.expect("dyn trait fat ptr must have vtable"); - // the second entry in the vtable is the dynamic size of the object. + // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; let elem = layout.field(self, 0)?; - Ok(Some((elem.size * len, elem.align.abi))) + + // Make sure the slice is not too big. + let size = elem.size.checked_mul(len, &*self.tcx) + .ok_or_else(|| err_ub_format!("invalid slice: \ + total size is bigger than largest supported object"))?; + Ok(Some((size, elem.align.abi))) } ty::Foreign(_) => { @@ -696,14 +671,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Our result will later be validated anyway, and there seems no good reason // to have to fail early here. This is also more consistent with // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles. - let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| { - match err { - ErrorHandled::Reported => - err_inval!(ReferencedConstant), - ErrorHandled::TooGeneric => - err_inval!(TooGeneric), - } - })?; + let val = self.tcx.const_eval_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 1074ab941a..95647ce642 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -3,7 +3,7 @@ //! After a const evaluation has computed a value, before we destroy the const evaluator's session //! memory, we need to extract all memory allocations to the global memory pool so they stay around. -use rustc::ty::{Ty, TyCtxt, ParamEnv, self}; +use rustc::ty::{Ty, self}; use rustc::mir::interpret::{InterpResult, ErrorHandled}; use rustc::hir; use rustc::hir::def_id::DefId; @@ -11,32 +11,29 @@ use super::validity::RefTracking; use rustc_data_structures::fx::FxHashSet; use syntax::ast::Mutability; -use syntax_pos::Span; use super::{ - ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar, + ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar, }; use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext}; struct InternVisitor<'rt, 'mir, 'tcx> { - /// previously encountered safe references - ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>, + /// The ectx from which we intern. ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>, - param_env: ParamEnv<'tcx>, + /// Previously encountered safe references. + ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>, + /// A list of all encountered allocations. After type-based interning, we traverse this list to + /// also intern allocations that are only referenced by a raw pointer or inside a union. + leftover_allocations: &'rt mut FxHashSet, /// The root node of the value that we're looking at. This field is never mutated and only used /// for sanity assertions that will ICE when `const_qualif` screws up. mode: InternMode, /// This field stores the mutability of the value *currently* being checked. - /// It is set to mutable when an `UnsafeCell` is encountered - /// When recursing across a reference, we don't recurse but store the - /// value to be checked in `ref_tracking` together with the mutability at which we are checking - /// the value. - /// When encountering an immutable reference, we treat everything as immutable that is behind - /// it. + /// When encountering a mutable reference, we determine the pointee mutability + /// taking into account the mutability of the context: `& &mut i32` is entirely immutable, + /// despite the nested mutable reference! + /// The field gets updated when an `UnsafeCell` is encountered. mutability: Mutability, - /// A list of all encountered relocations. After type-based interning, we traverse this list to - /// also intern allocations that are only referenced by a raw pointer or inside a union. - leftover_relocations: &'rt mut FxHashSet, } #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] @@ -45,9 +42,10 @@ enum InternMode { /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mut` /// that will actually be treated as mutable. Static, - /// UnsafeCell is OK in the value of a constant, but not behind references in a constant + /// UnsafeCell is OK in the value of a constant: `const FOO = Cell::new(0)` creates + /// a new cell every time it is used. ConstBase, - /// `UnsafeCell` ICEs + /// `UnsafeCell` ICEs. Const, } @@ -55,48 +53,100 @@ enum InternMode { /// into the memory of other constants or statics struct IsStaticOrFn; +/// Intern an allocation without looking at its children. +/// `mode` is the mode of the environment where we found this pointer. +/// `mutablity` is the mutability of the place to be interned; even if that says +/// `immutable` things might become mutable if `ty` is not frozen. +/// `ty` can be `None` if there is no potential interior mutability +/// to account for (e.g. for vtables). +fn intern_shallow<'rt, 'mir, 'tcx>( + ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>, + leftover_allocations: &'rt mut FxHashSet, + mode: InternMode, + alloc_id: AllocId, + mutability: Mutability, + ty: Option>, +) -> InterpResult<'tcx, Option> { + trace!( + "InternVisitor::intern {:?} with {:?}", + alloc_id, mutability, + ); + // remove allocation + let tcx = ecx.tcx; + let memory = ecx.memory_mut(); + let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) { + Some(entry) => entry, + None => { + // Pointer not found in local memory map. It is either a pointer to the global + // map, or dangling. + // If the pointer is dangling (neither in local nor global memory), we leave it + // to validation to error. The `delay_span_bug` ensures that we don't forget such + // a check in validation. + if tcx.alloc_map.lock().get(alloc_id).is_none() { + tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer"); + } + // treat dangling pointers like other statics + // just to stop trying to recurse into them + return Ok(Some(IsStaticOrFn)); + }, + }; + // This match is just a canary for future changes to `MemoryKind`, which most likely need + // changes in this function. + match kind { + MemoryKind::Stack | MemoryKind::Vtable => {}, + } + // Set allocation mutability as appropriate. This is used by LLVM to put things into + // read-only memory, and also by Miri when evluating other constants/statics that + // access this one. + if mode == InternMode::Static { + // When `ty` is `None`, we assume no interior mutability. + let frozen = ty.map_or(true, |ty| ty.is_freeze( + ecx.tcx.tcx, + ecx.param_env, + ecx.tcx.span, + )); + // For statics, allocation mutability is the combination of the place mutability and + // the type mutability. + // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. + if mutability == Mutability::Immutable && frozen { + alloc.mutability = Mutability::Immutable; + } else { + // Just making sure we are not "upgrading" an immutable allocation to mutable. + assert_eq!(alloc.mutability, Mutability::Mutable); + } + } else { + // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`. + // But we still intern that as immutable as the memory cannot be changed once the + // initial value was computed. + // Constants are never mutable. + assert_eq!( + mutability, Mutability::Immutable, + "Something went very wrong: mutability requested for a constant" + ); + alloc.mutability = Mutability::Immutable; + }; + // link the alloc id to the actual allocation + let alloc = tcx.intern_const_alloc(alloc); + leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc)); + tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); + Ok(None) +} + impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> { - /// Intern an allocation without looking at its children fn intern_shallow( &mut self, - ptr: Pointer, + alloc_id: AllocId, mutability: Mutability, + ty: Option>, ) -> InterpResult<'tcx, Option> { - trace!( - "InternVisitor::intern {:?} with {:?}", - ptr, mutability, - ); - // remove allocation - let tcx = self.ecx.tcx; - let memory = self.ecx.memory_mut(); - let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) { - Some(entry) => entry, - None => { - // if the pointer is dangling (neither in local nor global memory), we leave it - // to validation to error. The `delay_span_bug` ensures that we don't forget such - // a check in validation. - if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() { - tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer"); - } - // treat dangling pointers like other statics - // just to stop trying to recurse into them - return Ok(Some(IsStaticOrFn)); - }, - }; - // This match is just a canary for future changes to `MemoryKind`, which most likely need - // changes in this function. - match kind { - MemoryKind::Stack | MemoryKind::Vtable => {}, - } - // Ensure llvm knows to only put this into immutable memory if the value is immutable either - // by being behind a reference or by being part of a static or const without interior - // mutability - alloc.mutability = mutability; - // link the alloc id to the actual allocation - let alloc = tcx.intern_const_alloc(alloc); - self.leftover_relocations.extend(alloc.relocations.iter().map(|&(_, ((), reloc))| reloc)); - tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc); - Ok(None) + intern_shallow( + self.ecx, + self.leftover_allocations, + self.mode, + alloc_id, + mutability, + ty, + ) } } @@ -119,14 +169,16 @@ for ) -> InterpResult<'tcx> { if let Some(def) = mplace.layout.ty.ty_adt_def() { if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() { - // We are crossing over an `UnsafeCell`, we can mutate again + // We are crossing over an `UnsafeCell`, we can mutate again. This means that + // References we encounter inside here are interned as pointing to mutable + // allocations. let old = std::mem::replace(&mut self.mutability, Mutability::Mutable); assert_ne!( self.mode, InternMode::Const, "UnsafeCells are not allowed behind references in constants. This should have \ been prevented statically by const qualification. If this were allowed one \ - would be able to change a constant at one use site and other use sites may \ - arbitrarily decide to change, too.", + would be able to change a constant at one use site and other use sites could \ + observe that mutation.", ); let walked = self.walk_aggregate(mplace, fields); self.mutability = old; @@ -145,12 +197,13 @@ for // Handle trait object vtables if let Ok(meta) = value.to_meta() { if let ty::Dynamic(..) = - self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty + self.ecx.tcx.struct_tail_erasing_lifetimes( + referenced_ty, self.ecx.param_env).sty { if let Ok(vtable) = meta.unwrap().to_ptr() { // explitly choose `Immutable` here, since vtables are immutable, even // if the reference of the fat pointer is mutable - self.intern_shallow(vtable, Mutability::Immutable)?; + self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?; } } } @@ -177,7 +230,7 @@ for (InternMode::Const, hir::Mutability::MutMutable) => { match referenced_ty.sty { ty::Array(_, n) - if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {} + if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {} ty::Slice(_) if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {} _ => bug!("const qualif failed to prevent mutable references"), @@ -195,21 +248,13 @@ for (Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable, _ => Mutability::Immutable, }; - // Compute the mutability of the allocation - let intern_mutability = intern_mutability( - self.ecx.tcx.tcx, - self.param_env, - mplace.layout.ty, - self.ecx.tcx.span, - mutability, - ); // Recursing behind references changes the intern mode for constants in order to // cause assertions to trigger if we encounter any `UnsafeCell`s. let mode = match self.mode { InternMode::ConstBase => InternMode::Const, other => other, }; - match self.intern_shallow(ptr, intern_mutability)? { + match self.intern_shallow(ptr.alloc_id, mutability, Some(mplace.layout.ty))? { // No need to recurse, these are interned already and statics may have // cycles, so we don't want to recurse there Some(IsStaticOrFn) => {}, @@ -224,69 +269,45 @@ for } } -/// Figure out the mutability of the allocation. -/// Mutable if it has interior mutability *anywhere* in the type. -fn intern_mutability<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - mutability: Mutability, -) -> Mutability { - let has_interior_mutability = !ty.is_freeze(tcx, param_env, span); - if has_interior_mutability { - Mutability::Mutable - } else { - mutability - } -} - pub fn intern_const_alloc_recursive( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, def_id: DefId, ret: MPlaceTy<'tcx>, - // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval - // must always be monomorphic, right? - param_env: ty::ParamEnv<'tcx>, ) -> InterpResult<'tcx> { let tcx = ecx.tcx; // this `mutability` is the mutability of the place, ignoring the type - let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) { + let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) { Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static), - None => (Mutability::Immutable, InternMode::ConstBase), // `static mut` doesn't care about interior mutability, it's mutable anyway Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static), + // consts, promoteds. FIXME: what about array lengths, array initializers? + None => (Mutability::Immutable, InternMode::ConstBase), }; - // type based interning - let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode)); - let leftover_relocations = &mut FxHashSet::default(); - - // This mutability is the combination of the place mutability and the type mutability. If either - // is mutable, `alloc_mutability` is mutable. This exists because the entire allocation needs - // to be mutable if it contains an `UnsafeCell` anywhere. The other `mutability` exists so that - // the visitor does not treat everything outside the `UnsafeCell` as mutable. - let alloc_mutability = intern_mutability( - tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability, - ); + // Type based interning. + // `ref_tracking` tracks typed references we have seen and still need to crawl for + // more typed information inside them. + // `leftover_allocations` collects *all* allocations we see, because some might not + // be available in a typed way. They get interned at the end. + let mut ref_tracking = RefTracking::new((ret, base_mutability, base_intern_mode)); + let leftover_allocations = &mut FxHashSet::default(); // start with the outermost allocation - InternVisitor { - ref_tracking: &mut ref_tracking, + intern_shallow( ecx, - mode: base_intern_mode, - leftover_relocations, - param_env, - mutability, - }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?; + leftover_allocations, + base_intern_mode, + ret.ptr.to_ptr()?.alloc_id, + base_mutability, + Some(ret.layout.ty) + )?; while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() { let interned = InternVisitor { ref_tracking: &mut ref_tracking, ecx, mode, - leftover_relocations, - param_env, + leftover_allocations, mutability, }.visit_value(mplace); if let Err(error) = interned { @@ -296,11 +317,7 @@ pub fn intern_const_alloc_recursive( let err = crate::const_eval::error_to_const_error(&ecx, error); match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { Ok(mut diag) => { - diag.note("The rules on what exactly is undefined behavior aren't clear, \ - so this check might be overzealous. Please open an issue on the rust \ - compiler repository if you believe it should not be considered \ - undefined behavior", - ); + diag.note(crate::const_eval::note_on_undefined_behavior_error()); diag.emit(); } Err(ErrorHandled::TooGeneric) | @@ -313,15 +330,23 @@ pub fn intern_const_alloc_recursive( // Intern the rest of the allocations as mutable. These might be inside unions, padding, raw // pointers, ... So we can't intern them according to their type rules - let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect(); + let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect(); while let Some(alloc_id) = todo.pop() { - if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) { - // We can't call the `intern` method here, as its logic is tailored to safe references. - // So we hand-roll the interning logic here again + if let Some((_, mut alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) { + // We can't call the `intern_shallow` method here, as its logic is tailored to safe + // references and a `leftover_allocations` set (where we only have a todo-list here). + // So we hand-roll the interning logic here again. + if base_intern_mode != InternMode::Static { + // If it's not a static, it *must* be immutable. + // We cannot have mutable memory inside a constant. + // FIXME: ideally we would assert that they already are immutable, to double- + // check our static checks. + alloc.mutability = Mutability::Immutable; + } let alloc = tcx.intern_const_alloc(alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); - for &(_, ((), reloc)) in alloc.relocations.iter() { - if leftover_relocations.insert(reloc) { + for &(_, ((), reloc)) in alloc.relocations().iter() { + if leftover_allocations.insert(reloc) { todo.push(reloc); } } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 89c5be137a..ec09e69ec8 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -5,17 +5,18 @@ use syntax::symbol::Symbol; use rustc::ty; use rustc::ty::layout::{LayoutOf, Primitive, Size}; +use rustc::ty::subst::SubstsRef; +use rustc::hir::def_id::DefId; +use rustc::ty::TyCtxt; use rustc::mir::BinOp; -use rustc::mir::interpret::{InterpResult, Scalar}; +use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue}; use super::{ - Machine, PlaceTy, OpTy, InterpCx, Immediate, + Machine, PlaceTy, OpTy, InterpCx, }; mod type_name; -pub use type_name::*; - fn numeric_intrinsic<'tcx, Tag>( name: &str, bits: u128, @@ -37,6 +38,50 @@ fn numeric_intrinsic<'tcx, Tag>( Ok(Scalar::from_uint(bits_out, size)) } +/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated +/// inside an `InterpCx` and instead have their value computed directly from rustc internal info. +crate fn eval_nullary_intrinsic<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> { + let tp_ty = substs.type_at(0); + let name = &*tcx.item_name(def_id).as_str(); + Ok(match name { + "type_name" => { + let alloc = type_name::alloc_type_name(tcx, tp_ty); + tcx.mk_const(ty::Const { + val: ConstValue::Slice { + data: alloc, + start: 0, + end: alloc.len(), + }, + ty: tcx.mk_static_str(), + }) + }, + "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)), + "size_of" | + "min_align_of" | + "pref_align_of" => { + let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; + let n = match name { + "pref_align_of" => layout.align.pref.bytes(), + "min_align_of" => layout.align.abi.bytes(), + "size_of" => layout.size.bytes(), + _ => bug!(), + }; + ty::Const::from_usize(tcx, n) + }, + "type_id" => ty::Const::from_bits( + tcx, + tcx.type_id_hash(tp_ty).into(), + param_env.and(tcx.types.u64), + ), + other => bug!("`{}` is not a zero arg intrinsic", other), + }) +} + impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Returns `true` if emulation happened. pub fn emulate_intrinsic( @@ -49,41 +94,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { - "min_align_of" => { - let elem_ty = substs.type_at(0); - let elem_align = self.layout_of(elem_ty)?.align.abi.bytes(); - let align_val = Scalar::from_uint(elem_align, dest.layout.size); - self.write_scalar(align_val, dest)?; - } - - "needs_drop" => { - let ty = substs.type_at(0); - let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env); - let val = Scalar::from_bool(ty_needs_drop); - self.write_scalar(val, dest)?; - } - - "size_of" => { - let ty = substs.type_at(0); - let size = self.layout_of(ty)?.size.bytes() as u128; - let size_val = Scalar::from_uint(size, dest.layout.size); - self.write_scalar(size_val, dest)?; - } - - "type_id" => { - let ty = substs.type_at(0); - let type_id = self.tcx.type_id_hash(ty) as u128; - let id_val = Scalar::from_uint(type_id, dest.layout.size); - self.write_scalar(id_val, dest)?; - } - + "min_align_of" | + "pref_align_of" | + "needs_drop" | + "size_of" | + "type_id" | "type_name" => { - let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0)); - let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc); - let id_ptr = self.memory.tag_static_base_pointer(name_id.into()); - let alloc_len = alloc.bytes.len() as u64; - let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self); - self.write_immediate(name_val, dest)?; + let gid = GlobalId { + instance, + promoted: None, + }; + let val = self.tcx.const_eval(self.param_env.and(gid))?; + let val = self.eval_const_to_op(val, None)?; + self.copy_op(val, dest)?; } | "ctpop" @@ -95,7 +118,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | "bitreverse" => { let ty = substs.type_at(0); let layout_of = self.layout_of(ty)?; - let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?; + let val = self.read_scalar(args[0])?.not_undef()?; + let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, _ => throw_unsup!(TypeNotPrimitive(ty)), @@ -110,18 +134,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(out_val, dest)?; } - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let lhs = self.read_immediate(args[0])?; let rhs = self.read_immediate(args[1])?; let (bin_op, ignore_overflow) = match intrinsic_name { - "overflowing_add" => (BinOp::Add, true), - "overflowing_sub" => (BinOp::Sub, true), - "overflowing_mul" => (BinOp::Mul, true), + "wrapping_add" => (BinOp::Add, true), + "wrapping_sub" => (BinOp::Sub, true), + "wrapping_mul" => (BinOp::Mul, true), "add_with_overflow" => (BinOp::Add, false), "sub_with_overflow" => (BinOp::Sub, false), "mul_with_overflow" => (BinOp::Mul, false), @@ -137,7 +161,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let l = self.read_immediate(args[0])?; let r = self.read_immediate(args[1])?; let is_add = intrinsic_name == "saturating_add"; - let (val, overflowed) = self.binary_op(if is_add { + let (val, overflowed, _ty) = self.overflowing_binary_op(if is_add { BinOp::Add } else { BinOp::Sub @@ -149,7 +173,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // term since the sign of the second term can be inferred from this and // the fact that the operation has overflowed (if either is 0 no // overflow can occur) - let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?; + let first_term: u128 = self.force_bits(l.to_scalar()?, l.layout.size)?; let first_term_positive = first_term & (1 << (num_bits-1)) == 0; if first_term_positive { // Negative overflow not possible since the positive first term @@ -184,10 +208,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "unchecked_shr" => BinOp::Shr, _ => bug!("Already checked for int ops") }; - let (val, overflowed) = self.binary_op(bin_op, l, r)?; + let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?; if overflowed { let layout = self.layout_of(substs.type_at(0))?; - let r_val = r.to_scalar()?.to_bits(layout.size)?; + let r_val = self.force_bits(r.to_scalar()?, layout.size)?; throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); } self.write_scalar(val, dest)?; @@ -196,8 +220,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) let layout = self.layout_of(substs.type_at(0))?; - let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?; - let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?; + let val = self.read_scalar(args[0])?.not_undef()?; + let val_bits = self.force_bits(val, layout.size)?; + let raw_shift = self.read_scalar(args[1])?.not_undef()?; + let raw_shift_bits = self.force_bits(raw_shift, layout.size)?; let width_bits = layout.size.bits() as u128; let shift_bits = raw_shift_bits % width_bits; let inv_shift_bits = (width_bits - shift_bits) % width_bits; diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index f207cfc6b3..1e765a4ed9 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -7,7 +7,7 @@ use rustc::ty::{ use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::hir::def_id::CrateNum; use std::fmt::Write; -use rustc::mir::interpret::{Allocation, ConstValue}; +use rustc::mir::interpret::Allocation; struct AbsolutePathPrinter<'tcx> { tcx: TyCtxt<'tcx>, @@ -213,22 +213,11 @@ impl Write for AbsolutePathPrinter<'_> { } } -/// Produces an absolute path representation of the given type. See also the documentation on -/// `std::any::type_name` -pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - let alloc = alloc_type_name(tcx, ty); - tcx.mk_const(ty::Const { - val: ConstValue::Slice { - data: alloc, - start: 0, - end: alloc.bytes.len(), - }, - ty: tcx.mk_static_str(), - }) -} - /// Directly returns an `Allocation` containing an absolute path representation of the given type. -pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation { +crate fn alloc_type_name<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx> +) -> &'tcx Allocation { let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes()); tcx.intern_const_alloc(alloc) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 33ffb1d320..bb74a50156 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -7,7 +7,7 @@ use std::hash::Hash; use rustc::hir::def_id::DefId; use rustc::mir; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt}; use super::{ Allocation, AllocId, InterpResult, Scalar, AllocationExtra, @@ -176,7 +176,7 @@ pub trait Machine<'mir, 'tcx>: Sized { bin_op: mir::BinOp, left: ImmTy<'tcx, Self::PointerTag>, right: ImmTy<'tcx, Self::PointerTag>, - ) -> InterpResult<'tcx, (Scalar, bool)>; + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)>; /// Heap allocations via the `box` keyword. fn box_alloc( diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index aef09df453..62b1760508 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -210,7 +210,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let new_ptr = self.allocate(new_size, new_align, kind); let old_size = match old_size_and_align { Some((size, _align)) => size, - None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64), + None => self.get(ptr.alloc_id)?.size, }; self.copy( ptr, @@ -271,20 +271,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { )) } if let Some((size, align)) = old_size_and_align { - if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align { - let bytes = Size::from_bytes(alloc.bytes.len() as u64); + if size != alloc.size || align != alloc.align { + let bytes = alloc.size; throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align)) } } // Let the machine take some extra action - let size = Size::from_bytes(alloc.bytes.len() as u64); + let size = alloc.size; AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?; // Don't forget to remember size and align of this now-dead allocation let old = self.dead_alloc_map.insert( ptr.alloc_id, - (Size::from_bytes(alloc.bytes.len() as u64), alloc.align) + (alloc.size, alloc.align) ); if old.is_some() { bug!("Nothing can be deallocated twice"); @@ -297,7 +297,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// and `align`. On success, returns `None` for zero-sized accesses (where /// nothing else is left to do) and a `Pointer` to use for the actual access otherwise. /// Crucially, if the input is a `Pointer`, we will test it for liveness - /// *even of* the size is 0. + /// *even if* the size is 0. /// /// Everyone accessing memory based on a `Scalar` should use this method to get the /// `Pointer` they need. And even if you already have a `Pointer`, call this method @@ -368,7 +368,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // It is sufficient to check this for the end pointer. The addition // checks for overflow. let end_ptr = ptr.offset(size, self)?; - end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; + end_ptr.check_inbounds_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { @@ -400,7 +400,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> bool { let (size, _align) = self.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) .expect("alloc info with MaybeDead cannot fail"); - ptr.check_in_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() + ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() } } @@ -555,7 +555,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // a) cause cycles in case `id` refers to a static // b) duplicate a static's allocation in miri if let Some((_, alloc)) = self.alloc_map.get(id) { - return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); + return Ok((alloc.size, alloc.align)); } // # Function pointers @@ -583,7 +583,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Memory(alloc)) => // Need to duplicate the logic here, because the global allocations have // different associated types than the interpreter-local ones. - Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)), + Ok((alloc.size, alloc.align)), Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"), // The rest must be dead. @@ -645,17 +645,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let prefix_len = msg.len(); let mut relocations = vec![]; - for i in 0..(alloc.bytes.len() as u64) { + for i in 0..alloc.size.bytes() { let i = Size::from_bytes(i); - if let Some(&(_, target_id)) = alloc.relocations.get(&i) { + if let Some(&(_, target_id)) = alloc.relocations().get(&i) { if allocs_seen.insert(target_id) { allocs_to_print.push_back(target_id); } relocations.push((i, target_id)); } - if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() { + if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() { // this `as usize` is fine, since `i` came from a `usize` - write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap(); + let i = i.bytes() as usize; + + // Checked definedness (and thus range) and relocations. This access also doesn't + // influence interpreter execution but is only for debugging. + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(i..i+1); + write!(msg, "{:02x} ", bytes[0]).unwrap(); } else { msg.push_str("__ "); } @@ -664,7 +669,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { trace!( "{}({} bytes, alignment {}){}", msg, - alloc.bytes.len(), + alloc.size.bytes(), alloc.align.bytes(), extra ); @@ -803,32 +808,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // since we don't want to keep any relocations at the target. // (`get_bytes_with_undef_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). - let relocations = { - let relocations = self.get(src.alloc_id)?.relocations(self, src, size); - if relocations.is_empty() { - // nothing to copy, ignore even the `length` loop - Vec::new() - } else { - let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); - for i in 0..length { - new_relocations.extend( - relocations - .iter() - .map(|&(offset, reloc)| { - // compute offset for current repetition - let dest_offset = dest.offset + (i * size); - ( - // shift offsets from source allocation to destination allocation - offset + dest_offset - src.offset, - reloc, - ) - }) - ); - } - - new_relocations - } - }; + let relocations = self.get(src.alloc_id)? + .prepare_relocation_copy(self, src, size, dest, length); let tcx = self.tcx.tcx; @@ -875,7 +856,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // copy definedness to the destination self.copy_undef_mask(src, dest, size, length)?; // copy the relocations to the destination - self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations); + self.get_mut(dest.alloc_id)?.mark_relocation_range(relocations); Ok(()) } @@ -894,65 +875,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // The bits have to be saved locally before writing to dest in case src and dest overlap. assert_eq!(size.bytes() as usize as u64, size.bytes()); - let undef_mask = &self.get(src.alloc_id)?.undef_mask; - - // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), - // a naive undef mask copying algorithm would repeatedly have to read the undef mask from - // the source and write it to the destination. Even if we optimized the memory accesses, - // we'd be doing all of this `repeat` times. - // Therefor we precompute a compressed version of the undef mask of the source value and - // then write it back `repeat` times without computing any more information from the source. - - // a precomputed cache for ranges of defined/undefined bits - // 0000010010001110 will become - // [5, 1, 2, 1, 3, 3, 1] - // where each element toggles the state - let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); - let first = undef_mask.get(src.offset); - let mut cur_len = 1; - let mut cur = first; - for i in 1..size.bytes() { - // FIXME: optimize to bitshift the current undef block's bits and read the top bit - if undef_mask.get(src.offset + Size::from_bytes(i)) == cur { - cur_len += 1; - } else { - ranges.push(cur_len); - cur_len = 1; - cur = !cur; - } - } + let src_alloc = self.get(src.alloc_id)?; + let compressed = src_alloc.compress_undef_range(src, size); // now fill in all the data let dest_allocation = self.get_mut(dest.alloc_id)?; - // an optimization where we can just overwrite an entire range of definedness bits if - // they are going to be uniformly `1` or `0`. - if ranges.is_empty() { - dest_allocation.undef_mask.set_range_inbounds( - dest.offset, - dest.offset + size * repeat, - first, - ); - return Ok(()) - } + dest_allocation.mark_compressed_undef_range(&compressed, dest, size, repeat); - // remember to fill in the trailing bits - ranges.push(cur_len); - - for mut j in 0..repeat { - j *= size.bytes(); - j += dest.offset.bytes(); - let mut cur = first; - for range in &ranges { - let old_j = j; - j += range; - dest_allocation.undef_mask.set_range_inbounds( - Size::from_bytes(old_j), - Size::from_bytes(j), - cur, - ); - cur = !cur; - } - } Ok(()) } diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 45d24347e4..0c61be283d 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -34,6 +34,6 @@ pub use self::visitor::{ValueVisitor, MutValueVisitor}; pub use self::validity::RefTracking; -pub(super) use self::intrinsics::type_name; - pub use self::intern::intern_const_alloc_recursive; + +crate use self::intrinsics::eval_nullary_intrinsic; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index f778eb1734..dd214c4a03 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -1,11 +1,11 @@ //! Functions concerning immediate values and operands, and reading from operands. //! All high-level functions to read from memory work on operands as sources. -use std::convert::TryInto; +use std::convert::{TryInto, TryFrom}; use rustc::{mir, ty}; use rustc::ty::layout::{ - self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx, + self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, PrimitiveExt, VariantIdx, }; use rustc::mir::interpret::{ @@ -108,7 +108,7 @@ impl<'tcx, Tag> Immediate { // as input for binary and cast operations. #[derive(Copy, Clone, Debug)] pub struct ImmTy<'tcx, Tag=()> { - pub imm: Immediate, + pub(crate) imm: Immediate, pub layout: TyLayout<'tcx>, } @@ -155,7 +155,7 @@ impl Operand { #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct OpTy<'tcx, Tag=()> { - op: Operand, + op: Operand, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, } @@ -187,13 +187,22 @@ impl<'tcx, Tag> From> for OpTy<'tcx, Tag> { } } -impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> -{ +impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { #[inline] pub fn from_scalar(val: Scalar, layout: TyLayout<'tcx>) -> Self { ImmTy { imm: val.into(), layout } } + #[inline] + pub fn from_uint(i: impl Into, layout: TyLayout<'tcx>) -> Self { + Self::from_scalar(Scalar::from_uint(i, layout.size), layout) + } + + #[inline] + pub fn from_int(i: impl Into, layout: TyLayout<'tcx>) -> Self { + Self::from_scalar(Scalar::from_int(i, layout.size), layout) + } + #[inline] pub fn to_bits(self) -> InterpResult<'tcx, u128> { self.to_scalar()?.to_bits(self.layout.size) @@ -246,7 +255,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(None); } - let ptr = match self.check_mplace_access(mplace, None)? { + let ptr = match self.check_mplace_access(mplace, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(Some(ImmTy { // zero-sized type imm: Scalar::zst().into(), @@ -461,39 +472,38 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // avoid allocations. pub(super) fn eval_place_to_op( &self, - mir_place: &mir::Place<'tcx>, + place: &mir::Place<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { use rustc::mir::PlaceBase; - mir_place.iterate(|place_base, place_projection| { - let mut op = match place_base { - PlaceBase::Local(mir::RETURN_PLACE) => - throw_unsup!(ReadFromReturnPointer), - PlaceBase::Local(local) => { - // Do not use the layout passed in as argument if the base we are looking at - // here is not the entire place. - // FIXME use place_projection.is_empty() when is available - let layout = if mir_place.projection.is_none() { - layout - } else { - None - }; - - self.access_local(self.frame(), *local, layout)? - } - PlaceBase::Static(place_static) => { - self.eval_static_to_mplace(place_static)?.into() - } - }; + let base_op = match &place.base { + PlaceBase::Local(mir::RETURN_PLACE) => + throw_unsup!(ReadFromReturnPointer), + PlaceBase::Local(local) => { + // Do not use the layout passed in as argument if the base we are looking at + // here is not the entire place. + // FIXME use place_projection.is_empty() when is available + let layout = if place.projection.is_empty() { + layout + } else { + None + }; - for proj in place_projection { - op = self.operand_projection(op, &proj.elem)? + self.access_local(self.frame(), *local, layout)? + } + PlaceBase::Static(place_static) => { + self.eval_static_to_mplace(&place_static)?.into() } + }; - trace!("eval_place_to_op: got {:?}", *op); - Ok(op) - }) + let op = place.projection.iter().try_fold( + base_op, + |op, elem| self.operand_projection(op, elem) + )?; + + trace!("eval_place_to_op: got {:?}", *op); + Ok(op) } /// Evaluate the operand, returning a place where you can then find the data. @@ -511,7 +521,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Move(ref place) => self.eval_place_to_op(place, layout)?, - Constant(ref constant) => self.eval_const_to_op(constant.literal, layout)?, + Constant(ref constant) => { + let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal); + self.eval_const_to_op(val, layout)? + } }; trace!("{:?}: {:?}", mir_op, *op); Ok(op) @@ -529,6 +542,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Used when the miri-engine runs into a constant and for extracting information from constants // in patterns via the `const_eval` module + /// The `val` and `layout` are assumed to already be in our interpreter + /// "universe" (param_env). crate fn eval_const_to_op( &self, val: &'tcx ty::Const<'tcx>, @@ -541,7 +556,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Early-return cases. match val.val { ConstValue::Param(_) => - // FIXME(oli-obk): try to monomorphize throw_inval!(TooGeneric), ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; @@ -554,7 +568,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Other cases need layout. let layout = from_known_layout(layout, || { - self.layout_of(self.monomorphize(val.ty)?) + self.layout_of(val.ty) })?; let op = match val.val { ConstValue::ByRef { alloc, offset } => { @@ -595,15 +609,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, (u128, VariantIdx)> { trace!("read_discriminant_value {:#?}", rval.layout); - let (discr_kind, discr_index) = match rval.layout.variants { + let (discr_layout, discr_kind, discr_index) = match rval.layout.variants { layout::Variants::Single { index } => { let discr_val = rval.layout.ty.discriminant_for_variant(*self.tcx, index).map_or( index.as_u32() as u128, |discr| discr.val); return Ok((discr_val, index)); } - layout::Variants::Multiple { ref discr_kind, discr_index, .. } => - (discr_kind, discr_index), + layout::Variants::Multiple { + discr: ref discr_layout, + ref discr_kind, + discr_index, + .. + } => + (discr_layout, discr_kind, discr_index), }; // read raw discriminant value @@ -614,14 +633,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // post-process Ok(match *discr_kind { layout::DiscriminantKind::Tag => { - let bits_discr = match raw_discr.to_bits(discr_val.layout.size) { - Ok(raw_discr) => raw_discr, - Err(_) => - throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag())), - }; + let bits_discr = raw_discr + .not_undef() + .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) + .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?; let real_discr = if discr_val.layout.ty.is_signed() { // going from layout tag type to typeck discriminant type - // requires first sign extending with the layout discriminant + // requires first sign extending with the discriminant layout let sexted = sign_extend(bits_discr, discr_val.layout.size) as i128; // and then zeroing with the typeck discriminant type let discr_ty = rval.layout.ty @@ -653,8 +671,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ref niche_variants, niche_start, } => { - let variants_start = niche_variants.start().as_u32() as u128; - let variants_end = niche_variants.end().as_u32() as u128; + let variants_start = niche_variants.start().as_u32(); + let variants_end = niche_variants.end().as_u32(); let raw_discr = raw_discr.not_undef().map_err(|_| { err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef)) })?; @@ -669,18 +687,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (dataful_variant.as_u32() as u128, dataful_variant) }, Ok(raw_discr) => { - let adjusted_discr = raw_discr.wrapping_sub(niche_start) - .wrapping_add(variants_start); - if variants_start <= adjusted_discr && adjusted_discr <= variants_end { - let index = adjusted_discr as usize; - assert_eq!(index as u128, adjusted_discr); - assert!(index < rval.layout.ty + // We need to use machine arithmetic to get the relative variant idx: + // variant_index_relative = discr_val - niche_start_val + let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?; + let discr_val = ImmTy::from_uint(raw_discr, discr_layout); + let niche_start_val = ImmTy::from_uint(niche_start, discr_layout); + let variant_index_relative_val = self.binary_op( + mir::BinOp::Sub, + discr_val, + niche_start_val, + )?; + let variant_index_relative = variant_index_relative_val + .to_scalar()? + .assert_bits(discr_val.layout.size); + // Check if this is in the range that indicates an actual discriminant. + if variant_index_relative <= u128::from(variants_end - variants_start) { + let variant_index_relative = u32::try_from(variant_index_relative) + .expect("we checked that this fits into a u32"); + // Then computing the absolute variant idx should not overflow any more. + let variant_index = variants_start + .checked_add(variant_index_relative) + .expect("oveflow computing absolute variant idx"); + assert!((variant_index as usize) < rval.layout.ty .ty_adt_def() .expect("tagged layout for non adt") .variants.len()); - (adjusted_discr, VariantIdx::from_usize(index)) + (u128::from(variant_index), VariantIdx::from_u32(variant_index)) } else { - (dataful_variant.as_u32() as u128, dataful_variant) + (u128::from(dataful_variant.as_u32()), dataful_variant) } }, } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index e638ebcc34..470cc9346e 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,5 +1,5 @@ use rustc::mir; -use rustc::ty::{self, layout::TyLayout}; +use rustc::ty::{self, Ty, layout::{TyLayout, LayoutOf}}; use syntax::ast::FloatTy; use rustc_apfloat::Float; use rustc::mir::interpret::{InterpResult, Scalar}; @@ -17,7 +17,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - let (val, overflowed) = self.binary_op(op, left, right)?; + let (val, overflowed, ty) = self.overflowing_binary_op(op, left, right)?; + debug_assert_eq!( + self.tcx.intern_tup(&[ty, self.tcx.types.bool]), + dest.layout.ty, + "type mismatch for result of {:?}", op, + ); let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); self.write_immediate(val, dest) } @@ -31,7 +36,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - let (val, _overflowed) = self.binary_op(op, left, right)?; + let (val, _overflowed, ty) = self.overflowing_binary_op(op, left, right)?; + assert_eq!(ty, dest.layout.ty, "type mismatch for result of {:?}", op); self.write_scalar(val, dest) } } @@ -42,7 +48,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: char, r: char, - ) -> (Scalar, bool) { + ) -> (Scalar, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -54,7 +60,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ge => l >= r, _ => bug!("Invalid operation on char: {:?}", bin_op), }; - return (Scalar::from_bool(res), false); + return (Scalar::from_bool(res), false, self.tcx.types.bool); } fn binary_bool_op( @@ -62,7 +68,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: bool, r: bool, - ) -> (Scalar, bool) { + ) -> (Scalar, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -77,32 +83,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => l ^ r, _ => bug!("Invalid operation on bool: {:?}", bin_op), }; - return (Scalar::from_bool(res), false); + return (Scalar::from_bool(res), false, self.tcx.types.bool); } fn binary_float_op>>( &self, bin_op: mir::BinOp, + ty: Ty<'tcx>, l: F, r: F, - ) -> (Scalar, bool) { + ) -> (Scalar, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; - let val = match bin_op { - Eq => Scalar::from_bool(l == r), - Ne => Scalar::from_bool(l != r), - Lt => Scalar::from_bool(l < r), - Le => Scalar::from_bool(l <= r), - Gt => Scalar::from_bool(l > r), - Ge => Scalar::from_bool(l >= r), - Add => (l + r).value.into(), - Sub => (l - r).value.into(), - Mul => (l * r).value.into(), - Div => (l / r).value.into(), - Rem => (l % r).value.into(), + let (val, ty) = match bin_op { + Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), + Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), + Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), + Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), + Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), + Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), + Add => ((l + r).value.into(), ty), + Sub => ((l - r).value.into(), ty), + Mul => ((l * r).value.into(), ty), + Div => ((l / r).value.into(), ty), + Rem => ((l % r).value.into(), ty), _ => bug!("invalid float op: `{:?}`", bin_op), }; - return (val, false); + return (val, false, ty); } fn binary_int_op( @@ -113,7 +120,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { left_layout: TyLayout<'tcx>, r: u128, right_layout: TyLayout<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { use rustc::mir::BinOp::*; // Shift ops can have an RHS with a different numeric type. @@ -142,7 +149,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo)); + return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty)); } // For the remaining ops, the types must be the same on both sides @@ -167,7 +174,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(op) = op { let l = self.sign_extend(l, left_layout) as i128; let r = self.sign_extend(r, right_layout) as i128; - return Ok((Scalar::from_bool(op(&l, &r)), false)); + return Ok((Scalar::from_bool(op(&l, &r)), false, self.tcx.types.bool)); } let op: Option (i128, bool)> = match bin_op { Div if r == 0 => throw_panic!(DivisionByZero), @@ -187,7 +194,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Rem | Div => { // int_min / -1 if r == -1 && l == (1 << (size.bits() - 1)) { - return Ok((Scalar::from_uint(l, size), true)); + return Ok((Scalar::from_uint(l, size), true, left_layout.ty)); } }, _ => {}, @@ -202,25 +209,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // this may be out-of-bounds for the result type, so we have to truncate ourselves let result = result as u128; let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo)); + return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty)); } } let size = left_layout.size; - // only ints left - let val = match bin_op { - Eq => Scalar::from_bool(l == r), - Ne => Scalar::from_bool(l != r), + let (val, ty) = match bin_op { + Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), + Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), - Lt => Scalar::from_bool(l < r), - Le => Scalar::from_bool(l <= r), - Gt => Scalar::from_bool(l > r), - Ge => Scalar::from_bool(l >= r), + Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), + Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), + Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), + Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), - BitOr => Scalar::from_uint(l | r, size), - BitAnd => Scalar::from_uint(l & r, size), - BitXor => Scalar::from_uint(l ^ r, size), + BitOr => (Scalar::from_uint(l | r, size), left_layout.ty), + BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty), + BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty), Add | Sub | Mul | Rem | Div => { debug_assert!(!left_layout.abi.is_signed()); @@ -236,7 +242,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let (result, oflo) = op(l, r); let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo || truncated != result)); + return Ok(( + Scalar::from_uint(truncated, size), + oflo || truncated != result, + left_layout.ty, + )); } _ => { @@ -250,17 +260,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; - Ok((val, false)) + Ok((val, false, ty)) } - /// Returns the result of the specified operation and whether it overflowed. - #[inline] - pub fn binary_op( + /// Returns the result of the specified operation, whether it overflowed, and + /// the result type. + pub fn overflowing_binary_op( &self, bin_op: mir::BinOp, left: ImmTy<'tcx, M::PointerTag>, right: ImmTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, *left, left.layout.ty, *right, right.layout.ty); @@ -279,11 +289,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::Float(fty) => { assert_eq!(left.layout.ty, right.layout.ty); + let ty = left.layout.ty; let left = left.to_scalar()?; let right = right.to_scalar()?; Ok(match fty { - FloatTy::F32 => self.binary_float_op(bin_op, left.to_f32()?, right.to_f32()?), - FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?), + FloatTy::F32 => + self.binary_float_op(bin_op, ty, left.to_f32()?, right.to_f32()?), + FloatTy::F64 => + self.binary_float_op(bin_op, ty, left.to_f64()?, right.to_f64()?), }) } _ if left.layout.ty.is_integral() => { @@ -312,11 +325,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + /// Typed version of `checked_binary_op`, returning an `ImmTy`. Also ignores overflows. + #[inline] + pub fn binary_op( + &self, + bin_op: mir::BinOp, + left: ImmTy<'tcx, M::PointerTag>, + right: ImmTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::PointerTag>> { + let (val, _overflow, ty) = self.overflowing_binary_op(bin_op, left, right)?; + Ok(ImmTy::from_scalar(val, self.layout_of(ty)?)) + } + pub fn unary_op( &self, un_op: mir::UnOp, val: ImmTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::PointerTag>> { use rustc::mir::UnOp::*; let layout = val.layout; @@ -330,7 +355,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Not => !val, _ => bug!("Invalid bool op {:?}", un_op) }; - Ok(Scalar::from_bool(res)) + Ok(ImmTy::from_scalar(Scalar::from_bool(res), self.layout_of(self.tcx.types.bool)?)) } ty::Float(fty) => { let res = match (un_op, fty) { @@ -338,7 +363,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), _ => bug!("Invalid float op {:?}", un_op) }; - Ok(res) + Ok(ImmTy::from_scalar(res, layout)) } _ => { assert!(layout.ty.is_integral()); @@ -351,7 +376,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; // res needs tuncating - Ok(Scalar::from_uint(self.truncate(res, layout), layout.size)) + Ok(ImmTy::from_uint(self.truncate(res, layout), layout)) } } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index f66c4adf76..c3660fb7a2 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -8,7 +8,9 @@ use std::hash::Hash; use rustc::mir; use rustc::mir::interpret::truncate; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::layout::{ + self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt +}; use rustc::ty::TypeFoldable; use super::{ @@ -45,7 +47,7 @@ pub enum Place { #[derive(Copy, Clone, Debug)] pub struct PlaceTy<'tcx, Tag=()> { - place: Place, + place: Place, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, } @@ -277,6 +279,10 @@ where { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. + /// + /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not + /// want to ever use the place for memory access! + /// Generally prefer `deref_operand`. pub fn ref_to_mplace( &self, val: ImmTy<'tcx, M::PointerTag>, @@ -304,7 +310,8 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); - self.ref_to_mplace(val) + let place = self.ref_to_mplace(val)?; + self.mplace_access_checked(place) } /// Check if the given place is good for memory access with the given @@ -327,6 +334,23 @@ where self.memory.check_ptr_access(place.ptr, size, place.align) } + /// Return the "access-checked" version of this `MPlace`, where for non-ZST + /// this is definitely a `Pointer`. + pub fn mplace_access_checked( + &self, + mut place: MPlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let (size, align) = self.size_and_align_of_mplace(place)? + .unwrap_or((place.layout.size, place.layout.align.abi)); + assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); + place.mplace.align = align; // maximally strict checking + // When dereferencing a pointer, it must be non-NULL, aligned, and live. + if let Some(ptr) = self.check_mplace_access(place, Some(size))? { + place.mplace.ptr = ptr.into(); + } + Ok(place) + } + /// Force `place.ptr` to a `Pointer`. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. pub fn force_mplace_ptr( @@ -563,19 +587,20 @@ where use rustc::mir::StaticKind; Ok(match place_static.kind { - StaticKind::Promoted(promoted) => { - let instance = self.frame().instance; + StaticKind::Promoted(promoted, promoted_substs) => { + let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs); + let instance = ty::Instance::new(place_static.def_id, substs); self.const_eval_raw(GlobalId { instance, promoted: Some(promoted), })? } - StaticKind::Static(def_id) => { + StaticKind::Static => { let ty = place_static.ty; assert!(!ty.needs_subst()); let layout = self.layout_of(ty)?; - let instance = ty::Instance::mono(*self.tcx, def_id); + let instance = ty::Instance::mono(*self.tcx, place_static.def_id); let cid = GlobalId { instance, promoted: None @@ -606,42 +631,43 @@ where /// place; for reading, a more efficient alternative is `eval_place_for_read`. pub fn eval_place( &mut self, - mir_place: &mir::Place<'tcx>, + place: &mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { use rustc::mir::PlaceBase; - mir_place.iterate(|place_base, place_projection| { - let mut place = match place_base { - PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place { - Some(return_place) => { - // We use our layout to verify our assumption; caller will validate - // their layout on return. - PlaceTy { - place: *return_place, - layout: self - .layout_of(self.monomorphize(self.frame().body.return_ty())?)?, - } + let mut place_ty = match &place.base { + PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place { + Some(return_place) => { + // We use our layout to verify our assumption; caller will validate + // their layout on return. + PlaceTy { + place: *return_place, + layout: self.layout_of( + self.subst_from_frame_and_normalize_erasing_regions( + self.frame().body.return_ty() + ) + )?, } - None => throw_unsup!(InvalidNullPointerUsage), - }, - PlaceBase::Local(local) => PlaceTy { - // This works even for dead/uninitialized locals; we check further when writing - place: Place::Local { - frame: self.cur_frame(), - local: *local, - }, - layout: self.layout_of_local(self.frame(), *local, None)?, + } + None => throw_unsup!(InvalidNullPointerUsage), + }, + PlaceBase::Local(local) => PlaceTy { + // This works even for dead/uninitialized locals; we check further when writing + place: Place::Local { + frame: self.cur_frame(), + local: *local, }, - PlaceBase::Static(place_static) => self.eval_static_to_mplace(place_static)?.into(), - }; + layout: self.layout_of_local(self.frame(), *local, None)?, + }, + PlaceBase::Static(place_static) => self.eval_static_to_mplace(&place_static)?.into(), + }; - for proj in place_projection { - place = self.place_projection(place, &proj.elem)? - } + for elem in place.projection.iter() { + place_ty = self.place_projection(place_ty, elem)? + } - self.dump_place(place.place); - Ok(place) - }) + self.dump_place(place_ty.place); + Ok(place_ty) } /// Write a scalar to a place @@ -750,7 +776,9 @@ where // to handle padding properly, which is only correct if we never look at this data with the // wrong type. - let ptr = match self.check_mplace_access(dest, None)? { + let ptr = match self.check_mplace_access(dest, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(()), // zero-sized access }; @@ -853,8 +881,10 @@ where }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - let src = self.check_mplace_access(src, Some(size))?; - let dest = self.check_mplace_access(dest, Some(size))?; + let src = self.check_mplace_access(src, Some(size)) + .expect("places should be checked on creation"); + let dest = self.check_mplace_access(dest, Some(size)) + .expect("places should be checked on creation"); let (src_ptr, dest_ptr) = match (src, dest) { (Some(src_ptr), Some(dest_ptr)) => (src_ptr, dest_ptr), (None, None) => return Ok(()), // zero-sized copy @@ -999,7 +1029,7 @@ where } layout::Variants::Multiple { discr_kind: layout::DiscriminantKind::Tag, - ref discr, + discr: ref discr_layout, discr_index, .. } => { @@ -1010,7 +1040,7 @@ where // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = discr.value.size(self); + let size = discr_layout.value.size(self); let discr_val = truncate(discr_val, size); let discr_dest = self.place_field(dest, discr_index as u64)?; @@ -1022,6 +1052,7 @@ where ref niche_variants, niche_start, }, + discr: ref discr_layout, discr_index, .. } => { @@ -1029,15 +1060,24 @@ where variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(), ); if variant_index != dataful_variant { - let niche_dest = - self.place_field(dest, discr_index as u64)?; - let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); - let niche_value = (niche_value as u128) - .wrapping_add(niche_start); - self.write_scalar( - Scalar::from_uint(niche_value, niche_dest.layout.size), - niche_dest + let variants_start = niche_variants.start().as_u32(); + let variant_index_relative = variant_index.as_u32() + .checked_sub(variants_start) + .expect("overflow computing relative variant idx"); + // We need to use machine arithmetic when taking into account `niche_start`: + // discr_val = variant_index_relative + niche_start_val + let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?; + let niche_start_val = ImmTy::from_uint(niche_start, discr_layout); + let variant_index_relative_val = + ImmTy::from_uint(variant_index_relative, discr_layout); + let discr_val = self.binary_op( + mir::BinOp::Add, + variant_index_relative_val, + niche_start_val, )?; + // Write result. + let niche_dest = self.place_field(dest, discr_index as u64)?; + self.write_immediate(*discr_val, niche_dest)?; } } } diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 47289064f4..2cac8bb0c5 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -15,7 +15,7 @@ use rustc::mir::interpret::{ }; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::Align; +use rustc::ty::layout::{Align, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -276,6 +276,7 @@ struct AllocationSnapshot<'a> { relocations: Relocations<(), AllocIdSnapshot<'a>>, undef_mask: &'a UndefMask, align: &'a Align, + size: &'a Size, mutability: &'a Mutability, } @@ -285,12 +286,28 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation type Item = AllocationSnapshot<'a>; fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self; + let Allocation { + size, + align, + mutability, + extra: (), + .. + } = self; + + let all_bytes = 0..self.len(); + // This 'inspect' is okay since following access respects undef and relocations. This does + // influence interpreter exeuction, but only to detect the error of cycles in evalution + // dependencies. + let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); + + let undef_mask = self.undef_mask(); + let relocations = self.relocations(); AllocationSnapshot { bytes, undef_mask, align, + size, mutability, relocations: relocations.snapshot(ctx), } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index d152e2b50f..affca10bf5 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -82,7 +82,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.memory.tcx.span = stmt.source_info.span; match stmt.kind { - Assign(ref place, ref rvalue) => self.eval_rvalue_into_place(rvalue, place)?, + Assign(box(ref place, ref rvalue)) => self.eval_rvalue_into_place(rvalue, place)?, SetDiscriminant { ref place, @@ -177,7 +177,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The operand always has the same type as the result. let val = self.read_immediate(self.eval_operand(operand, Some(dest.layout))?)?; let val = self.unary_op(un_op, val)?; - self.write_scalar(val, dest)?; + assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op); + self.write_immediate(*val, dest)?; } Aggregate(ref kind, ref operands) => { @@ -240,8 +241,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ref(_, _, ref place) => { let src = self.eval_place(place)?; - let val = self.force_allocation(src)?; - self.write_immediate(val.to_ref(), dest)?; + let place = self.force_allocation(src)?; + if place.layout.size.bytes() > 0 { + // definitely not a ZST + assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`"); + } + self.write_immediate(place.to_ref(), dest)?; } NullaryOp(mir::NullOp::Box, _) => { @@ -249,7 +254,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.monomorphize(ty)?; + let ty = self.subst_from_frame_and_normalize_erasing_regions(ty); let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "SizeOf nullary MIR operator called for unsized type"); diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 1d6b48e9da..8310ef02f9 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -7,7 +7,7 @@ use syntax::source_map::Span; use rustc_target::spec::abi::Abi; use super::{ - InterpResult, PointerArithmetic, Scalar, + InterpResult, PointerArithmetic, InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal, }; @@ -50,11 +50,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (index, &const_int) in values.iter().enumerate() { // Compare using binary_op, to also support pointer values - let const_int = Scalar::from_uint(const_int, discr.layout.size); - let (res, _) = self.binary_op(mir::BinOp::Eq, + let res = self.overflowing_binary_op(mir::BinOp::Eq, discr, - ImmTy::from_scalar(const_int, discr.layout), - )?; + ImmTy::from_uint(const_int, discr.layout), + )?.0; if res.to_bool()? { target_block = targets[index]; break; @@ -392,7 +391,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Don't forget to check the return type! if let Some(caller_ret) = dest { let callee_ret = self.eval_place( - &mir::Place::RETURN_PLACE + &mir::Place::return_place() )?; if !Self::check_argument_compat( rust_abi, diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index e55b0d0fb1..10b767ebba 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,5 +1,5 @@ -use rustc::ty::{self, Ty, Instance}; -use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::ty::{self, Ty, Instance, TypeFoldable}; +use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout}; use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,}; use super::{InterpCx, Machine, MemoryKind, FnVal}; @@ -20,6 +20,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (ty, poly_trait_ref) = self.tcx.erase_regions(&(ty, poly_trait_ref)); + // All vtables must be monomorphic, bail out otherwise. + if ty.needs_subst() || poly_trait_ref.needs_subst() { + throw_inval!(TooGeneric); + } + if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) { // This means we guarantee that there are no duplicate vtables, we will // always use the same vtable for the same (Type, Trait) combination. @@ -77,7 +82,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (i, method) in methods.iter().enumerate() { if let Some((def_id, substs)) = *method { // resolve for vtable: insert shims where needed - let substs = self.subst_and_normalize_erasing_regions(substs)?; let instance = ty::Instance::resolve_for_vtable( *self.tcx, self.param_env, @@ -140,11 +144,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let size = alloc.read_ptr_sized( self, vtable.offset(pointer_size, self)? - )?.to_bits(pointer_size)? as u64; + )?.not_undef()?; + let size = self.force_bits(size, pointer_size)? as u64; let align = alloc.read_ptr_sized( self, vtable.offset(pointer_size * 2, self)?, - )?.to_bits(pointer_size)? as u64; + )?.not_undef()?; + let align = self.force_bits(align, pointer_size)? as u64; + + if size >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("invalid vtable: \ + size is bigger than largest supported object"); + } Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 82d6d7db01..3e14ba3efc 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -1,3 +1,9 @@ +//! Check the validity invariant of a given value, and tell the user +//! where in the value it got violated. +//! In const context, this goes even further and tries to approximate const safety. +//! That's useful because it means other passes (e.g. promotion) can rely on `const`s +//! to be const-safe. + use std::fmt::Write; use std::ops::RangeInclusive; @@ -11,7 +17,7 @@ use std::hash::Hash; use super::{ GlobalAlloc, InterpResult, - OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, + Scalar, OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, }; macro_rules! throw_validation_failure { @@ -250,6 +256,47 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M self.path.truncate(path_len); Ok(()) } + + fn check_wide_ptr_meta( + &mut self, + meta: Option>, + pointee: TyLayout<'tcx>, + ) -> InterpResult<'tcx> { + let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + match tail.sty { + ty::Dynamic(..) => { + let vtable = meta.unwrap(); + try_validation!( + self.ecx.memory.check_ptr_access( + vtable, + 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align + self.ecx.tcx.data_layout.pointer_align.abi, + ), + "dangling or unaligned vtable pointer in wide pointer or too small vtable", + self.path + ); + try_validation!(self.ecx.read_drop_type_from_vtable(vtable), + "invalid drop fn in vtable", self.path); + try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), + "invalid size or align in vtable", self.path); + // FIXME: More checks for the vtable. + } + ty::Slice(..) | ty::Str => { + let _len = try_validation!(meta.unwrap().to_usize(self.ecx), + "non-integer slice length in wide pointer", self.path); + // We do not check that `len * elem_size <= isize::MAX`: + // that is only required for references, and there it falls out of the + // "dereferencable" check performed by Stacked Borrows. + } + ty::Foreign(..) => { + // Unsized, but not wide. + } + _ => + bug!("Unexpected unsized type tail: {:?}", tail), + } + + Ok(()) + } } impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> @@ -341,56 +388,34 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } ty::RawPtr(..) => { + // Check pointer part. if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: For consistency with integers, we do not // accept undef. let _ptr = try_validation!(value.to_scalar_ptr(), "undefined address in raw pointer", self.path); - let _meta = try_validation!(value.to_meta(), - "uninitialized data in raw fat pointer metadata", self.path); } else { // Remain consistent with `usize`: Accept anything. } + + // Check metadata. + let meta = try_validation!(value.to_meta(), + "uninitialized data in wide pointer metadata", self.path); + let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; + if layout.is_unsized() { + self.check_wide_ptr_meta(meta, layout)?; + } } _ if ty.is_box() || ty.is_region_ptr() => { - // Handle fat pointers. + // Handle wide pointers. // Check metadata early, for better diagnostics let ptr = try_validation!(value.to_scalar_ptr(), "undefined address in pointer", self.path); let meta = try_validation!(value.to_meta(), - "uninitialized data in fat pointer metadata", self.path); + "uninitialized data in wide pointer metadata", self.path); let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; if layout.is_unsized() { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty, - self.ecx.param_env); - match tail.sty { - ty::Dynamic(..) => { - let vtable = meta.unwrap(); - try_validation!( - self.ecx.memory.check_ptr_access( - vtable, - 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align - self.ecx.tcx.data_layout.pointer_align.abi, - ), - "dangling or unaligned vtable pointer or too small vtable", - self.path - ); - try_validation!(self.ecx.read_drop_type_from_vtable(vtable), - "invalid drop fn in vtable", self.path); - try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), - "invalid size or align in vtable", self.path); - // FIXME: More checks for the vtable. - } - ty::Slice(..) | ty::Str => { - try_validation!(meta.unwrap().to_usize(self.ecx), - "non-integer slice length in fat pointer", self.path); - } - ty::Foreign(..) => { - // Unsized, but not fat. - } - _ => - bug!("Unexpected unsized type tail: {:?}", tail), - } + self.check_wide_ptr_meta(meta, layout)?; } // Make sure this is dereferencable and all. let (size, align) = self.ecx.size_and_align_of(meta, layout)? diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index cccf7b9545..9a03719ab6 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,7 +14,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(const_fn)] #![feature(decl_macro)] #![feature(exhaustive_patterns)] -#![feature(rustc_diagnostic_macros)] #![feature(never_type)] #![feature(specialization)] #![feature(try_trait)] @@ -24,6 +23,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(try_blocks)] #![feature(mem_take)] #![feature(associated_type_bounds)] +#![feature(range_is_empty)] #![recursion_limit="256"] @@ -32,11 +32,11 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #[macro_use] extern crate rustc_data_structures; #[macro_use] extern crate syntax; -mod error_codes; +pub mod error_codes; mod borrow_check; mod build; -mod dataflow; +pub mod dataflow; mod hair; mod lints; mod shim; @@ -60,7 +60,4 @@ pub fn provide(providers: &mut Providers<'_>) { let (param_env, (value, field)) = param_env_and_value.into_parts(); const_eval::const_field(tcx, param_env, None, field, value) }; - providers.type_name = interpret::type_name; } - -__build_diagnostic_array! { librustc_mir, DIAGNOSTICS } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 12d763bb79..1f7efebfda 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -180,12 +180,12 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; -use rustc::mir::{self, Location, PlaceBase, Promoted, Static, StaticKind}; +use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; @@ -661,7 +661,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _context: mir::visit::PlaceContext, location: Location) { match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { debug!("visiting static {:?} @ {:?}", def_id, location); let tcx = self.tcx; @@ -670,8 +670,24 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(MonoItem::Static(*def_id)); } } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { - // FIXME: should we handle promoteds here instead of eagerly in collect_neighbours? + PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, substs), + def_id, + .. + }) => { + let param_env = ty::ParamEnv::reveal_all(); + let cid = GlobalId { + instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), + promoted: Some(*promoted), + }; + match self.tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(self.tcx, val, substs, self.output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => { + let span = self.tcx.promoted_mir(*def_id)[*promoted].span; + span_bug!(span, "collection encountered polymorphic constant") + }, + } } PlaceBase::Local(_) => { // Locals have no relevance for collector @@ -1202,7 +1218,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec { trace!("collecting {:?} with {:#?}", alloc_id, alloc); - for &((), inner) in alloc.relocations.values() { + for &((), inner) in alloc.relocations().values() { collect_miri(tcx, inner, output); } }, @@ -1222,6 +1238,7 @@ fn collect_neighbours<'tcx>( instance: Instance<'tcx>, output: &mut Vec>, ) { + debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); MirNeighborCollector { @@ -1230,22 +1247,6 @@ fn collect_neighbours<'tcx>( output, param_substs: instance.substs, }.visit_body(&body); - let param_env = ty::ParamEnv::reveal_all(); - for i in 0..body.promoted.len() { - use rustc_data_structures::indexed_vec::Idx; - let i = Promoted::new(i); - let cid = GlobalId { - instance, - promoted: Some(i), - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(ErrorHandled::Reported) => {}, - Err(ErrorHandled::TooGeneric) => span_bug!( - body.promoted[i].span, "collection encountered polymorphic constant", - ), - } - } } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { @@ -1268,7 +1269,7 @@ fn collect_const<'tcx>( collect_miri(tcx, ptr.alloc_id, output), ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { - for &((), id) in alloc.relocations.values() { + for &((), id) in alloc.relocations().values() { collect_miri(tcx, id, output); } } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index ad9db4e0aa..c193911247 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -777,7 +777,7 @@ where debug!("CodegenUnit {}:", cgu.name()); for (mono_item, linkage) in cgu.items() { - let symbol_name = mono_item.symbol_name(tcx).as_str(); + let symbol_name = mono_item.symbol_name(tcx).name.as_str(); let symbol_hash_start = symbol_name.rfind('h'); let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 33447eba74..6daca5e261 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -112,7 +112,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes(tcx, &mut result, instance, MirPhase::Const, &[ + run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &no_landing_pads::NoLandingPads, &remove_noop_landing_pads::RemoveNoopLandingPads, @@ -201,7 +201,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls_for_sig(&sig, span), IndexVec::new(), @@ -218,7 +217,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) // Function arguments should be retagged, and we make this one raw. body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Raw, dropee_ptr.clone()), + kind: StatementKind::Retag(RetagKind::Raw, box(dropee_ptr.clone())), }); } let patch = { @@ -309,7 +308,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span); - let dest = Place::RETURN_PLACE; + let dest = Place::return_place(); let src = Place::from(Local::new(1+0)).deref(); match self_ty.sty { @@ -369,7 +368,6 @@ impl CloneShimBuilder<'tcx> { SourceScopeData { span: self.span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, self.local_decls, IndexVec::new(), @@ -417,8 +415,10 @@ impl CloneShimBuilder<'tcx> { let rcvr = Place::from(Local::new(1+0)).deref(); let ret_statement = self.make_statement( StatementKind::Assign( - Place::RETURN_PLACE, - box Rvalue::Use(Operand::Copy(rcvr)) + box( + Place::return_place(), + Rvalue::Use(Operand::Copy(rcvr)) + ) ) ); self.block(vec![ret_statement], TerminatorKind::Return, false); @@ -445,7 +445,6 @@ impl CloneShimBuilder<'tcx> { let func_ty = tcx.mk_fn_def(self.def_id, substs); let func = Operand::Constant(box Constant { span: self.span, - ty: func_ty, user_ty: None, literal: ty::Const::zero_sized(tcx, func_ty), }); @@ -461,8 +460,10 @@ impl CloneShimBuilder<'tcx> { // `let ref_loc: &ty = &src;` let statement = self.make_statement( StatementKind::Assign( - ref_loc.clone(), - box Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src) + box( + ref_loc.clone(), + Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src) + ) ) ); @@ -489,8 +490,10 @@ impl CloneShimBuilder<'tcx> { let cond = self.make_place(Mutability::Mut, tcx.types.bool); let compute_cond = self.make_statement( StatementKind::Assign( - cond.clone(), - box Rvalue::BinaryOp(BinOp::Ne, Operand::Copy(end), Operand::Copy(beg)) + box( + cond.clone(), + Rvalue::BinaryOp(BinOp::Ne, Operand::Copy(end), Operand::Copy(beg)) + ) ) ); @@ -505,7 +508,6 @@ impl CloneShimBuilder<'tcx> { fn make_usize(&self, value: u64) -> Box> { box Constant { span: self.span, - ty: self.tcx.types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx, value), } @@ -525,14 +527,18 @@ impl CloneShimBuilder<'tcx> { let inits = vec![ self.make_statement( StatementKind::Assign( - Place::from(beg), - box Rvalue::Use(Operand::Constant(self.make_usize(0))) + box( + Place::from(beg), + Rvalue::Use(Operand::Constant(self.make_usize(0))) + ) ) ), self.make_statement( StatementKind::Assign( - end.clone(), - box Rvalue::Use(Operand::Constant(self.make_usize(len))) + box( + end.clone(), + Rvalue::Use(Operand::Constant(self.make_usize(len))) + ) ) ) ]; @@ -563,11 +569,13 @@ impl CloneShimBuilder<'tcx> { let statements = vec![ self.make_statement( StatementKind::Assign( - Place::from(beg), - box Rvalue::BinaryOp( - BinOp::Add, - Operand::Copy(Place::from(beg)), - Operand::Constant(self.make_usize(1)) + box( + Place::from(beg), + Rvalue::BinaryOp( + BinOp::Add, + Operand::Copy(Place::from(beg)), + Operand::Constant(self.make_usize(1)) + ) ) ) ) @@ -586,8 +594,10 @@ impl CloneShimBuilder<'tcx> { let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); let init = self.make_statement( StatementKind::Assign( - Place::from(beg), - box Rvalue::Use(Operand::Constant(self.make_usize(0))) + box( + Place::from(beg), + Rvalue::Use(Operand::Constant(self.make_usize(0))) + ) ) ); self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true); @@ -613,11 +623,13 @@ impl CloneShimBuilder<'tcx> { // `goto #6;` let statement = self.make_statement( StatementKind::Assign( - Place::from(beg), - box Rvalue::BinaryOp( - BinOp::Add, - Operand::Copy(Place::from(beg)), - Operand::Constant(self.make_usize(1)) + box( + Place::from(beg), + Rvalue::BinaryOp( + BinOp::Add, + Operand::Copy(Place::from(beg)), + Operand::Constant(self.make_usize(1)) + ) ) ) ); @@ -710,7 +722,7 @@ fn build_call_shim<'tcx>( Adjustment::DerefMove => { // fn(Self, ...) -> fn(*mut Self, ...) let arg_ty = local_decls[rcvr_arg].ty; - assert!(arg_ty.is_self()); + debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.types.self_param); local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty); Operand::Move(rcvr_l.deref()) @@ -731,8 +743,10 @@ fn build_call_shim<'tcx>( statements.push(Statement { source_info, kind: StatementKind::Assign( - Place::from(ref_rcvr), - box Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l) + box( + Place::from(ref_rcvr), + Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l) + ) ) }); Operand::Move(Place::from(ref_rcvr)) @@ -745,7 +759,6 @@ fn build_call_shim<'tcx>( let ty = tcx.type_of(def_id); (Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), @@ -778,7 +791,7 @@ fn build_call_shim<'tcx>( block(&mut blocks, statements, TerminatorKind::Call { func: callee, args, - destination: Some((Place::RETURN_PLACE, + destination: Some((Place::return_place(), BasicBlock::new(1))), cleanup: if let Adjustment::RefMut = rcvr_adjustment { Some(BasicBlock::new(3)) @@ -816,7 +829,6 @@ fn build_call_shim<'tcx>( SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), @@ -874,7 +886,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { debug!("build_ctor: variant_index={:?}", variant_index); let statements = expand_aggregate( - Place::RETURN_PLACE, + Place::return_place(), adt_def .variants[variant_index] .fields @@ -903,7 +915,6 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index c08c33bc6f..15ecc6c379 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -30,8 +30,8 @@ pub use self::AddCallGuards::*; * */ -impl MirPass for AddCallGuards { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddCallGuards { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 426e16698d..052631ddff 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -39,8 +39,8 @@ use crate::util; pub struct AddMovesForPackedDrops; -impl MirPass for AddMovesForPackedDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); add_moves_for_packed_drops(tcx, body, src.def_id()); } diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index d573423906..833c8b1646 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -17,12 +17,11 @@ pub struct AddRetag; fn is_stable( place: PlaceRef<'_, '_>, ) -> bool { - if let Some(proj) = &place.projection { - match proj.elem { + place.projection.iter().all(|elem| { + match elem { // Which place this evaluates to can change with any memory write, // so cannot assume this to be stable. - ProjectionElem::Deref => - false, + ProjectionElem::Deref => false, // Array indices are intersting, but MIR building generates a *fresh* // temporary for every array access, so the index cannot be changed as // a side-effect. @@ -31,20 +30,13 @@ fn is_stable( ProjectionElem::Field { .. } | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | - ProjectionElem::Downcast { .. } => - is_stable(PlaceRef { - base: place.base, - projection: &proj.base, - }), + ProjectionElem::Downcast { .. } => true, } - } else { - true - } + }) } -/// Determine whether this type may have a reference in it, recursing below compound types but -/// not below references. -fn may_have_reference<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool { +/// Determine whether this type may be a reference (or box), and thus needs retagging. +fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { match ty.sty { // Primitive types that are not references ty::Bool | ty::Char | @@ -55,22 +47,19 @@ fn may_have_reference<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool { // References ty::Ref(..) => true, ty::Adt(..) if ty.is_box() => true, - // Compound types - ty::Array(ty, ..) | ty::Slice(ty) => - may_have_reference(ty, tcx), - ty::Tuple(tys) => - tys.iter().any(|ty| may_have_reference(ty.expect_ty(), tcx)), - ty::Adt(adt, substs) => - adt.variants.iter().any(|v| v.fields.iter().any(|f| - may_have_reference(f.ty(tcx, substs), tcx) - )), + // Compound types are not references + ty::Array(..) | + ty::Slice(..) | + ty::Tuple(..) | + ty::Adt(..) => + false, // Conservative fallback _ => true, } } -impl MirPass for AddRetag { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddRetag { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } @@ -80,7 +69,7 @@ impl MirPass for AddRetag { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. is_stable(place.as_ref()) - && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx) + && may_be_reference(place.ty(&*local_decls, tcx).ty) }; // PART 1 @@ -100,7 +89,7 @@ impl MirPass for AddRetag { basic_blocks[START_BLOCK].statements.splice(0..0, places.into_iter().map(|place| Statement { source_info, - kind: StatementKind::Retag(RetagKind::FnEntry, place), + kind: StatementKind::Retag(RetagKind::FnEntry, box(place)), }) ); } @@ -136,7 +125,7 @@ impl MirPass for AddRetag { for (source_info, dest_place, dest_block) in returns { basic_blocks[dest_block].statements.insert(0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Default, dest_place), + kind: StatementKind::Retag(RetagKind::Default, box(dest_place)), }); } @@ -148,11 +137,11 @@ impl MirPass for AddRetag { for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { // If we are casting *from* a reference, we may have to retag-as-raw. - StatementKind::Assign(ref place, box Rvalue::Cast( + StatementKind::Assign(box(ref place, Rvalue::Cast( CastKind::Misc, ref src, dest_ty, - )) => { + ))) => { let src_ty = src.ty(&*local_decls, tcx); if src_ty.is_region_ptr() { // The only `Misc` casts on references are those creating raw pointers. @@ -166,7 +155,7 @@ impl MirPass for AddRetag { // Assignments of reference or ptr type are the ones where we may have // to update tags. This includes `x = &[mut] ...` and hence // we also retag after taking a reference! - StatementKind::Assign(ref place, box ref rvalue) if needs_retag(place) => { + StatementKind::Assign(box(ref place, ref rvalue)) if needs_retag(place) => { let kind = match rvalue { Rvalue::Ref(_, borrow_kind, _) if borrow_kind.allows_two_phase_borrow() @@ -184,7 +173,7 @@ impl MirPass for AddRetag { let source_info = block_data.statements[i].source_info; block_data.statements.insert(i+1, Statement { source_info, - kind: StatementKind::Retag(retag_kind, place), + kind: StatementKind::Retag(retag_kind, box(place)), }); } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d5c5267a11..61e32ca8de 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -200,127 +200,127 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, context: PlaceContext, _location: Location) { - place.iterate(|place_base, place_projections| { - match place_base { - PlaceBase::Local(..) => { - // Locals are safe. - } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { - bug!("unsafety checking should happen before promotion") - } - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { - if self.tcx.is_mutable_static(*def_id) { - self.require_unsafe("use of mutable static", - "mutable statics can be mutated by multiple threads: aliasing \ - violations or data races will cause undefined behavior", - UnsafetyViolationKind::General); - } else if self.tcx.is_foreign_item(*def_id) { - let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; - self.register_violations(&[UnsafetyViolation { - source_info, - description: InternedString::intern("use of extern static"), - details: InternedString::intern( - "extern statics are not controlled by the Rust type system: \ - invalid data, aliasing violations or data races will cause \ - undefined behavior"), - kind: UnsafetyViolationKind::ExternStatic(lint_root) - }], &[]); - } + match place.base { + PlaceBase::Local(..) => { + // Locals are safe. + } + PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => { + bug!("unsafety checking should happen before promotion") + } + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { + if self.tcx.is_mutable_static(def_id) { + self.require_unsafe("use of mutable static", + "mutable statics can be mutated by multiple threads: aliasing \ + violations or data races will cause undefined behavior", + UnsafetyViolationKind::General); + } else if self.tcx.is_foreign_item(def_id) { + let source_info = self.source_info; + let lint_root = + self.source_scope_local_data[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: InternedString::intern("use of extern static"), + details: InternedString::intern( + "extern statics are not controlled by the Rust type system: \ + invalid data, aliasing violations or data races will cause \ + undefined behavior"), + kind: UnsafetyViolationKind::ExternStatic(lint_root) + }], &[]); } } + } - for proj in place_projections { - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.body, self.param_env, place) { - let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; - self.register_violations(&[UnsafetyViolation { - source_info, - description: InternedString::intern("borrow of packed field"), - details: InternedString::intern( - "fields of packed structs might be misaligned: dereferencing a \ - misaligned pointer or even just creating a misaligned reference \ - is undefined behavior"), - kind: UnsafetyViolationKind::BorrowPacked(lint_root) - }], &[]); - } + for (i, elem) in place.projection.iter().enumerate() { + let proj_base = &place.projection[..i]; + + if context.is_borrow() { + if util::is_disaligned(self.tcx, self.body, self.param_env, place) { + let source_info = self.source_info; + let lint_root = + self.source_scope_local_data[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: InternedString::intern("borrow of packed field"), + details: InternedString::intern( + "fields of packed structs might be misaligned: dereferencing a \ + misaligned pointer or even just creating a misaligned reference \ + is undefined behavior"), + kind: UnsafetyViolationKind::BorrowPacked(lint_root) + }], &[]); } - let is_borrow_of_interior_mut = context.is_borrow() && - !Place::ty_from(&place.base, &proj.base, self.body, self.tcx) - .ty - .is_freeze(self.tcx, self.param_env, self.source_info.span); - // prevent - // * `&mut x.field` - // * `x.field = y;` - // * `&x.field` if `field`'s type has interior mutability - // because either of these would allow modifying the layout constrained field and - // insert values that violate the layout constraints. - if context.is_mutating_use() || is_borrow_of_interior_mut { - self.check_mut_borrowing_layout_constrained_field( - place, context.is_mutating_use(), - ); + } + let is_borrow_of_interior_mut = context.is_borrow() && + !Place::ty_from(&place.base, proj_base, self.body, self.tcx) + .ty + .is_freeze(self.tcx, self.param_env, self.source_info.span); + // prevent + // * `&mut x.field` + // * `x.field = y;` + // * `&x.field` if `field`'s type has interior mutability + // because either of these would allow modifying the layout constrained field and + // insert values that violate the layout constraints. + if context.is_mutating_use() || is_borrow_of_interior_mut { + self.check_mut_borrowing_layout_constrained_field( + place, context.is_mutating_use(), + ); + } + let old_source_info = self.source_info; + if let (PlaceBase::Local(local), []) = (&place.base, proj_base) { + if self.body.local_decls[*local].internal { + // Internal locals are used in the `move_val_init` desugaring. + // We want to check unsafety against the source info of the + // desugaring, rather than the source info of the RHS. + self.source_info = self.body.local_decls[*local].source_info; } - let old_source_info = self.source_info; - if let (PlaceBase::Local(local), None) = (&place.base, &proj.base) { - if self.body.local_decls[*local].internal { - // Internal locals are used in the `move_val_init` desugaring. - // We want to check unsafety against the source info of the - // desugaring, rather than the source info of the RHS. - self.source_info = self.body.local_decls[*local].source_info; - } + } + let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; + match base_ty.sty { + ty::RawPtr(..) => { + self.require_unsafe("dereference of raw pointer", + "raw pointers may be NULL, dangling or unaligned; they can violate \ + aliasing rules and cause data races: all of these are undefined \ + behavior", UnsafetyViolationKind::General) } - let base_ty = Place::ty_from(&place.base, &proj.base, self.body, self.tcx).ty; - match base_ty.sty { - ty::RawPtr(..) => { - self.require_unsafe("dereference of raw pointer", - "raw pointers may be NULL, dangling or unaligned; they can violate \ - aliasing rules and cause data races: all of these are undefined \ - behavior", UnsafetyViolationKind::General) - } - ty::Adt(adt, _) => { - if adt.is_union() { - if context == PlaceContext::MutatingUse(MutatingUseContext::Store) || - context == PlaceContext::MutatingUse(MutatingUseContext::Drop) || - context == PlaceContext::MutatingUse( - MutatingUseContext::AsmOutput - ) - { - let elem_ty = match proj.elem { - ProjectionElem::Field(_, ty) => ty, - _ => span_bug!( - self.source_info.span, - "non-field projection {:?} from union?", - place) - }; - if !elem_ty.is_copy_modulo_regions( - self.tcx, - self.param_env, + ty::Adt(adt, _) => { + if adt.is_union() { + if context == PlaceContext::MutatingUse(MutatingUseContext::Store) || + context == PlaceContext::MutatingUse(MutatingUseContext::Drop) || + context == PlaceContext::MutatingUse( + MutatingUseContext::AsmOutput + ) + { + let elem_ty = match elem { + ProjectionElem::Field(_, ty) => ty, + _ => span_bug!( self.source_info.span, - ) { - self.require_unsafe( - "assignment to non-`Copy` union field", - "the previous content of the field will be dropped, which \ - causes undefined behavior if the field was not properly \ - initialized", UnsafetyViolationKind::General) - } else { - // write to non-move union, safe - } + "non-field projection {:?} from union?", + place) + }; + if !elem_ty.is_copy_modulo_regions( + self.tcx, + self.param_env, + self.source_info.span, + ) { + self.require_unsafe( + "assignment to non-`Copy` union field", + "the previous content of the field will be dropped, which \ + causes undefined behavior if the field was not properly \ + initialized", UnsafetyViolationKind::GeneralAndConstFn) } else { - self.require_unsafe("access to union field", - "the field may not be properly initialized: using \ - uninitialized data will cause undefined behavior", - UnsafetyViolationKind::General) + // write to non-move union, safe } + } else { + self.require_unsafe("access to union field", + "the field may not be properly initialized: using \ + uninitialized data will cause undefined behavior", + UnsafetyViolationKind::GeneralAndConstFn) } } - _ => {} } - self.source_info = old_source_info; + _ => {} } - }); + self.source_info = old_source_info; + } } } @@ -407,12 +407,14 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, is_mut_use: bool, ) { - let mut projection = &place.projection; - while let Some(proj) = projection { - match proj.elem { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + + match elem { ProjectionElem::Field(..) => { let ty = - Place::ty_from(&place.base, &proj.base, &self.body.local_decls, self.tcx) + Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx) .ty; match ty.sty { ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) { @@ -447,7 +449,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } _ => {} } - projection = &proj.base; } } } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 6ee14160bb..ea173279aa 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -26,8 +26,8 @@ pub struct CleanupNonCodegenStatements; pub struct DeleteNonCodegenStatements; -impl MirPass for CleanupNonCodegenStatements { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut delete = DeleteNonCodegenStatements; delete.visit_body(body); } @@ -39,7 +39,7 @@ impl<'tcx> MutVisitor<'tcx> for DeleteNonCodegenStatements { location: Location) { match statement.kind { StatementKind::AscribeUserType(..) - | StatementKind::Assign(_, box Rvalue::Ref(_, BorrowKind::Shallow, _)) + | StatementKind::Assign(box(_, Rvalue::Ref(_, BorrowKind::Shallow, _))) | StatementKind::FakeRead(..) => statement.make_nop(), _ => (), } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 38d26d0ba5..614d5d2a4a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, - SourceScope, SourceScopeLocalData, LocalDecl, Promoted, + SourceScope, SourceScopeLocalData, LocalDecl, }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -19,7 +19,7 @@ use syntax_pos::{Span, DUMMY_SP}; use rustc::ty::subst::InternalSubsts; use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::layout::{ - LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size, + LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, }; use crate::interpret::{ @@ -27,14 +27,14 @@ use crate::interpret::{ ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState, }; use crate::const_eval::{ - CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx, + CompileTimeInterpreter, error_to_const_error, mk_eval_cx, }; use crate::transform::{MirPass, MirSource}; pub struct ConstProp; -impl MirPass for ConstProp { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for ConstProp { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { return; @@ -64,17 +64,12 @@ impl MirPass for ConstProp { &mut body.source_scope_local_data, ClearCrossCrate::Clear ); - let promoted = std::mem::replace( - &mut body.promoted, - IndexVec::new() - ); let dummy_body = &Body::new( body.basic_blocks().clone(), Default::default(), ClearCrossCrate::Clear, - Default::default(), None, body.local_decls.clone(), Default::default(), @@ -92,22 +87,17 @@ impl MirPass for ConstProp { body, dummy_body, source_scope_local_data, - promoted, tcx, source ); optimization_finder.visit_body(body); // put back the data we stole from `mir` - let (source_scope_local_data, promoted) = optimization_finder.release_stolen_data(); + let source_scope_local_data = optimization_finder.release_stolen_data(); std::mem::replace( &mut body.source_scope_local_data, source_scope_local_data ); - std::mem::replace( - &mut body.promoted, - promoted - ); trace!("ConstProp done for {:?}", source.def_id()); } @@ -124,7 +114,6 @@ struct ConstPropagator<'mir, 'tcx> { param_env: ParamEnv<'tcx>, source_scope_local_data: ClearCrossCrate>, local_decls: IndexVec>, - promoted: IndexVec>, } impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> { @@ -155,7 +144,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { body: &Body<'tcx>, dummy_body: &'mir Body<'tcx>, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, ) -> ConstPropagator<'mir, 'tcx> { @@ -184,17 +172,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_scope_local_data, //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it local_decls: body.local_decls.clone(), - promoted, } } - fn release_stolen_data( - self, - ) -> ( - ClearCrossCrate>, - IndexVec>, - ) { - (self.source_scope_local_data, self.promoted) + fn release_stolen_data(self) -> ClearCrossCrate> { + self.source_scope_local_data } fn get_const(&self, local: Local) -> Option> { @@ -255,9 +237,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = match f(self) { Ok(val) => Some(val), Err(error) => { - let diagnostic = error_to_const_error(&self.ecx, error); use rustc::mir::interpret::InterpError::*; - match diagnostic.error { + match error.kind { Exit(_) => bug!("the CTFE program cannot exit"), Unsupported(_) | UndefinedBehavior(_) @@ -266,6 +247,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Ignore these errors. } Panic(_) => { + let diagnostic = error_to_const_error(&self.ecx, error); diagnostic.report_as_lint( self.ecx.tcx, "this expression will panic at runtime", @@ -300,56 +282,53 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { trace!("eval_place(place={:?})", place); - place.iterate(|place_base, place_projection| { - let mut eval = match place_base { - PlaceBase::Local(loc) => self.get_const(*loc).clone()?, - PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => { - let generics = self.tcx.generics_of(self.source.def_id()); - if generics.requires_monomorphization(self.tcx) { - // FIXME: can't handle code with generics - return None; - } - let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); - let instance = Instance::new(self.source.def_id(), substs); - let cid = GlobalId { - instance, - promoted: Some(*promoted), - }; - // cannot use `const_eval` here, because that would require having the MIR - // for the current function available, but we're producing said MIR right now - let res = self.use_ecx(source_info, |this| { - let body = &this.promoted[*promoted]; - eval_promoted(this.tcx, cid, body, this.param_env) + let mut eval = match place.base { + PlaceBase::Local(loc) => self.get_const(loc).clone()?, + PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => { + let generics = self.tcx.generics_of(self.source.def_id()); + if generics.requires_monomorphization(self.tcx) { + // FIXME: can't handle code with generics + return None; + } + let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); + let instance = Instance::new(self.source.def_id(), substs); + let cid = GlobalId { + instance, + promoted: Some(promoted), + }; + let res = self.use_ecx(source_info, |this| { + this.ecx.const_eval_raw(cid) + })?; + trace!("evaluated promoted {:?} to {:?}", promoted, res); + res.into() + } + _ => return None, + }; + + for (i, elem) in place.projection.iter().enumerate() { + let proj_base = &place.projection[..i]; + + match elem { + ProjectionElem::Field(field, _) => { + trace!("field proj on {:?}", proj_base); + eval = self.use_ecx(source_info, |this| { + this.ecx.operand_field(eval, field.index() as u64) })?; - trace!("evaluated promoted {:?} to {:?}", promoted, res); - res.into() + }, + ProjectionElem::Deref => { + trace!("processing deref"); + eval = self.use_ecx(source_info, |this| { + this.ecx.deref_operand(eval) + })?.into(); } + // We could get more projections by using e.g., `operand_projection`, + // but we do not even have the stack frame set up properly so + // an `Index` projection would throw us off-track. _ => return None, - }; - - for proj in place_projection { - match proj.elem { - ProjectionElem::Field(field, _) => { - trace!("field proj on {:?}", proj.base); - eval = self.use_ecx(source_info, |this| { - this.ecx.operand_field(eval, field.index() as u64) - })?; - }, - ProjectionElem::Deref => { - trace!("processing deref"); - eval = self.use_ecx(source_info, |this| { - this.ecx.deref_operand(eval) - })?.into(); - } - // We could get more projections by using e.g., `operand_projection`, - // but we do not even have the stack frame set up properly so - // an `Index` projection would throw us off-track. - _ => return None, - } } + } - Some(eval) - }) + Some(eval) } fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { @@ -396,17 +375,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let ty::Slice(_) = mplace.layout.ty.sty { let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap(); - Some(ImmTy { - imm: Immediate::Scalar( - Scalar::from_uint( - len, - Size::from_bits( - self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64 - ) - ).into(), - ), - layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, - }.into()) + Some(ImmTy::from_uint( + len, + self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + ).into()) } else { trace!("not slice: {:?}", mplace.layout.ty.sty); None @@ -414,12 +386,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }, Rvalue::NullaryOp(NullOp::SizeOf, ty) => { type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some( - ImmTy { - imm: Immediate::Scalar( - Scalar::from_uint(n, self.tcx.data_layout.pointer_size).into() - ), - layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, - }.into() + ImmTy::from_uint( + n, + self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + ).into() )) } Rvalue::UnaryOp(op, ref arg) => { @@ -435,13 +405,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let arg = self.eval_operand(arg, source_info)?; + let oflo_check = self.tcx.sess.overflow_checks(); let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; match op { UnOp::Neg => { - // Need to do overflow check here: For actual CTFE, MIR - // generation emits code that does this before calling the op. - if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { + // We check overflow in debug mode already + // so should only check in release mode. + if !oflo_check + && prim.layout.ty.is_signed() + && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { throw_panic!(OverflowNeg) } } @@ -452,11 +425,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Now run the actual operation. this.ecx.unary_op(op, prim) })?; - let res = ImmTy { - imm: Immediate::Scalar(val.into()), - layout: place_layout, - }; - Some(res.into()) + Some(val.into()) } Rvalue::CheckedBinaryOp(op, ref left, ref right) | Rvalue::BinaryOp(op, ref left, ref right) => { @@ -510,8 +479,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { this.ecx.read_immediate(left) })?; trace!("const evaluating {:?} for {:?} and {:?}", op, left, right); - let (val, overflow) = self.use_ecx(source_info, |this| { - this.ecx.binary_op(op, l, r) + let (val, overflow, _ty) = self.use_ecx(source_info, |this| { + this.ecx.overflowing_binary_op(op, l, r) })?; let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue { Immediate::ScalarPair( @@ -519,7 +488,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Scalar::from_bool(overflow).into(), ) } else { - if overflow { + // We check overflow in debug mode already + // so should only check in release mode. + if !self.tcx.sess.overflow_checks() && overflow { let err = err_panic!(Overflow(op)).into(); let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; @@ -539,7 +510,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Operand::Constant(Box::new( Constant { span, - ty, user_ty: None, literal: self.tcx.mk_const(*ty::Const::from_scalar( self.tcx, @@ -695,7 +665,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { location: Location, ) { trace!("visit_statement: {:?}", statement); - if let StatementKind::Assign(ref place, ref mut rval) = statement.kind { + if let StatementKind::Assign(box(ref place, ref mut rval)) = statement.kind { let place_ty: Ty<'tcx> = place .ty(&self.local_decls, self.tcx) .ty; @@ -703,7 +673,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) { if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = *place { trace!("checking whether {:?} can be stored to {:?}", value, local); if self.can_const_prop[local] { diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 7c9eeb5a57..28f97f41b5 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -29,8 +29,8 @@ use crate::util::def_use::DefUseAnalysis; pub struct CopyPropagation; -impl MirPass for CopyPropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CopyPropagation { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { @@ -94,11 +94,13 @@ impl MirPass for CopyPropagation { // That use of the source must be an assignment. match statement.kind { StatementKind::Assign( - Place { - base: PlaceBase::Local(local), - projection: None, - }, - box Rvalue::Use(ref operand) + box( + Place { + base: PlaceBase::Local(local), + projection: box [], + }, + Rvalue::Use(ref operand) + ) ) if local == dest_local => { let maybe_action = match *operand { Operand::Copy(ref src_place) | @@ -148,24 +150,28 @@ fn eliminate_self_assignments( if let Some(stmt) = body[location.block].statements.get(location.statement_index) { match stmt.kind { StatementKind::Assign( - Place { - base: PlaceBase::Local(local), - projection: None, - }, - box Rvalue::Use(Operand::Copy(Place { - base: PlaceBase::Local(src_local), - projection: None, - })), + box( + Place { + base: PlaceBase::Local(local), + projection: box [], + }, + Rvalue::Use(Operand::Copy(Place { + base: PlaceBase::Local(src_local), + projection: box [], + })), + ) ) | StatementKind::Assign( - Place { - base: PlaceBase::Local(local), - projection: None, - }, - box Rvalue::Use(Operand::Move(Place { - base: PlaceBase::Local(src_local), - projection: None, - })), + box( + Place { + base: PlaceBase::Local(local), + projection: box [], + }, + Rvalue::Use(Operand::Move(Place { + base: PlaceBase::Local(src_local), + projection: box [], + })), + ) ) if local == dest_local && dest_local == src_local => {} _ => { continue; @@ -194,7 +200,7 @@ impl<'tcx> Action<'tcx> { // The source must be a local. let src_local = if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = *src_place { local } else { @@ -351,11 +357,11 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> { match *operand { Operand::Copy(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) | Operand::Move(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) if local == self.dest_local => {} _ => return, } diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 1b42a0dffb..c1224be632 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -5,15 +5,15 @@ use crate::util::expand_aggregate; pub struct Deaggregator; -impl MirPass for Deaggregator { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Deaggregator { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { bb.expand_statements(|stmt| { // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL). - if let StatementKind::Assign(_, ref rhs) = stmt.kind { - if let Rvalue::Aggregate(ref kind, _) = **rhs { + if let StatementKind::Assign(box(_, ref rhs)) = stmt.kind { + if let Rvalue::Aggregate(ref kind, _) = *rhs { // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. if let AggregateKind::Array(_) = **kind { return None; @@ -28,7 +28,7 @@ impl MirPass for Deaggregator { let stmt = stmt.replace_nop(); let source_info = stmt.source_info; let (lhs, kind, operands) = match stmt.kind { - StatementKind::Assign(lhs, box rvalue) => { + StatementKind::Assign(box(lhs, rvalue)) => { match rvalue { Rvalue::Aggregate(kind, operands) => (lhs, kind, operands), _ => bug!() diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index a6fb555f20..ed0eff943a 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -13,12 +13,12 @@ use crate::util as mir_util; pub struct Marker(pub &'static str); -impl MirPass for Marker { +impl<'tcx> MirPass<'tcx> for Marker { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(self.0) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 0a021d9b8f..a9c66b3c8c 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -20,8 +20,8 @@ use syntax_pos::Span; pub struct ElaborateDrops; -impl MirPass for ElaborateDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for ElaborateDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, body.span); let def_id = src.def_id(); @@ -236,47 +236,34 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { - match p { - &Projection { - elem: ProjectionElem::Field(idx, _), .. - } => idx == field, - _ => false - } + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + ProjectionElem::Field(idx, _) => *idx == field, + _ => false, }) } fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { - match p { - &Projection { - elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: false}, .. - } => offset == index, - &Projection { - elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true}, .. - } => size - offset == index, - _ => false + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false } => { + *offset == index + } + ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true } => { + size - offset == index } + _ => false, }) } fn deref_subpath(&self, path: Self::Path) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { - match p { - &Projection { elem: ProjectionElem::Deref, .. } => true, - _ => false - } + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| { + *e == ProjectionElem::Deref }) } fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { - match p { - &Projection { - elem: ProjectionElem::Downcast(_, idx), .. - } => idx == variant, - _ => false - } + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + ProjectionElem::Downcast(_, idx) => *idx == variant, + _ => false }) } @@ -465,7 +452,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported"); let assign = Statement { - kind: StatementKind::Assign(location.clone(), box Rvalue::Use(value.clone())), + kind: StatementKind::Assign(box(location.clone(), Rvalue::Use(value.clone()))), source_info: terminator.source_info }; @@ -527,7 +514,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, - ty: self.tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(self.tcx, val), }))) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 5a29ea21a7..21ca339eb9 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -49,8 +49,8 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; -impl MirPass for EraseRegions { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for EraseRegions { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { EraseRegionsVisitor::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 94bb70e10a..caf588af85 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -67,7 +67,7 @@ use crate::transform::{MirPass, MirSource}; use crate::transform::simplify; use crate::transform::no_landing_pads::no_landing_pads; use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation}; -use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location}; +use crate::dataflow::{do_dataflow, DebugFormatted, DataflowResultsCursor}; use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals, RequiresStorage}; use crate::util::dump_mir; use crate::util::liveness; @@ -107,10 +107,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor { if place.base == PlaceBase::Local(self_arg()) { replace_base(place, Place { base: PlaceBase::Local(self_arg()), - projection: Some(Box::new(Projection { - base: None, - elem: ProjectionElem::Deref, - })), + projection: Box::new([ProjectionElem::Deref]), }); } else { self.super_place(place, context, location); @@ -137,10 +134,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { if place.base == PlaceBase::Local(self_arg()) { replace_base(place, Place { base: PlaceBase::Local(self_arg()), - projection: Some(Box::new(Projection { - base: None, - elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty), - })), + projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]), }); } else { self.super_place(place, context, location); @@ -149,13 +143,12 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { } fn replace_base(place: &mut Place<'tcx>, new_base: Place<'tcx>) { - let mut projection = &mut place.projection; - while let Some(box proj) = projection { - projection = &mut proj.base; - } - place.base = new_base.base; - *projection = new_base.projection; + + let mut new_projection = new_base.projection.to_vec(); + new_projection.append(&mut place.projection.to_vec()); + + place.projection = new_projection.into_boxed_slice(); } fn self_arg() -> Local { @@ -210,13 +203,12 @@ impl TransformVisitor<'tcx> { fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> { let self_place = Place::from(self_arg()); let base = self_place.downcast_unnamed(variant_index); - let field = Projection { - base: base.projection, - elem: ProjectionElem::Field(Field::new(idx), ty), - }; + let mut projection = base.projection.to_vec(); + projection.push(ProjectionElem::Field(Field::new(idx), ty)); + Place { base: base.base, - projection: Some(Box::new(field)), + projection: projection.into_boxed_slice(), } } @@ -225,7 +217,10 @@ impl TransformVisitor<'tcx> { let self_place = Place::from(self_arg()); Statement { source_info, - kind: StatementKind::SetDiscriminant { place: self_place, variant_index: state_disc }, + kind: StatementKind::SetDiscriminant { + place: box self_place, + variant_index: state_disc, + }, } } @@ -238,7 +233,7 @@ impl TransformVisitor<'tcx> { let self_place = Place::from(self_arg()); let assign = Statement { source_info: source_info(body), - kind: StatementKind::Assign(temp.clone(), box Rvalue::Discriminant(self_place)), + kind: StatementKind::Assign(box(temp.clone(), Rvalue::Discriminant(self_place))), }; (assign, temp) } @@ -296,8 +291,12 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { // We must assign the value first in case it gets declared dead below data.statements.push(Statement { source_info, - kind: StatementKind::Assign(Place::RETURN_PLACE, - box self.make_state(state_idx, v)), + kind: StatementKind::Assign( + box( + Place::return_place(), + self.make_state(state_idx, v) + ) + ), }); let state = if let Some(resume) = resume { // Yield let state = 3 + self.suspension_points.len(); @@ -437,9 +436,10 @@ fn locals_live_across_suspend_points( // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. let storage_live_analysis = MaybeStorageLive::new(body); - let storage_live = + let storage_live_results = do_dataflow(tcx, body, def_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); + let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body); // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. @@ -449,17 +449,18 @@ fn locals_live_across_suspend_points( // Calculate the MIR locals which have been previously // borrowed (even if they are still active). let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body); - let borrowed_locals_result = + let borrowed_locals_results = do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); + let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body); // Calculate the MIR locals that we actually need to keep storage around // for. - let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result); - let requires_storage = + let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results); + let requires_storage_results = do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); - let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result); + let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body); // Calculate the liveness of MIR locals ignoring borrows. let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len()); @@ -485,10 +486,6 @@ fn locals_live_across_suspend_points( }; if !movable { - let borrowed_locals = state_for_location(loc, - &borrowed_locals_analysis, - &borrowed_locals_result, - body); // The `liveness` variable contains the liveness of MIR locals ignoring borrows. // This is correct for movable generators since borrows cannot live across // suspension points. However for immovable generators we need to account for @@ -499,22 +496,19 @@ fn locals_live_across_suspend_points( // If a borrow is converted to a raw reference, we must also assume that it lives // forever. Note that the final liveness is still bounded by the storage liveness // of the local, which happens using the `intersect` operation below. - liveness.outs[block].union(&borrowed_locals); + borrowed_locals_cursor.seek(loc); + liveness.outs[block].union(borrowed_locals_cursor.get()); } - let storage_liveness = state_for_location(loc, - &storage_live_analysis, - &storage_live, - body); + storage_live_cursor.seek(loc); + let storage_liveness = storage_live_cursor.get(); // Store the storage liveness for later use so we can restore the state // after a suspension point storage_liveness_map.insert(block, storage_liveness.clone()); - let mut storage_required = state_for_location(loc, - &requires_storage_analysis, - &requires_storage, - body); + requires_storage_cursor.seek(loc); + let mut storage_required = requires_storage_cursor.get().clone(); // Mark locals without storage statements as always requiring storage storage_required.union(&ignored.0); @@ -550,8 +544,7 @@ fn locals_live_across_suspend_points( body, &live_locals, &ignored, - requires_storage, - requires_storage_analysis); + requires_storage_results); LivenessInfo { live_locals, @@ -589,7 +582,6 @@ fn compute_storage_conflicts( stored_locals: &liveness::LiveVarSet, ignored: &StorageIgnored, requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>, - _requires_storage_analysis: RequiresStorage<'mir, 'tcx>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), ignored.0.domain_size()); assert_eq!(body.local_decls.len(), stored_locals.domain_size()); @@ -848,7 +840,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut kind: TerminatorKind::Drop { location: Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }, target, unwind @@ -937,7 +929,7 @@ fn create_generator_drop_shim<'tcx>( // Alias tracking must know we changed the type body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Raw, Place::from(self_arg())), + kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), }) } @@ -975,7 +967,6 @@ fn insert_panic_block<'tcx>( let term = TerminatorKind::Assert { cond: Operand::Constant(box Constant { span: body.span, - ty: tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(tcx, false), }), @@ -1116,8 +1107,8 @@ where }).collect() } -impl MirPass for StateTransform { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for StateTransform { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty } else { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 40cb1fbdc5..5ad026dc14 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -37,8 +37,8 @@ struct CallSite<'tcx> { location: SourceInfo, } -impl MirPass for Inline { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Inline { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { Inliner { tcx, source }.run_pass(body); } @@ -328,7 +328,7 @@ impl Inliner<'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::FnDef(def_id, _) = f.ty.sty { + if let ty::FnDef(def_id, _) = f.literal.ty.sty { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { @@ -394,7 +394,6 @@ impl Inliner<'tcx> { let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - let mut promoted_map = IndexVec::with_capacity(callee_body.promoted.len()); for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { @@ -420,32 +419,26 @@ impl Inliner<'tcx> { local_map.push(idx); } - promoted_map.extend( - callee_body.promoted.iter().cloned().map(|p| caller_body.promoted.push(p)) - ); - // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` // Place could result in two different locations if `f` // writes to `i`. To prevent this we need to create a temporary // borrow of the place and pass the destination as `*temp` instead. fn dest_needs_borrow(place: &Place<'_>) -> bool { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - match proj.elem { - ProjectionElem::Deref | - ProjectionElem::Index(_) => return true, - _ => {} - } + for elem in place.projection.iter() { + match elem { + ProjectionElem::Deref | + ProjectionElem::Index(_) => return true, + _ => {} } + } - match place_base { - // Static variables need a borrow because the callee - // might modify the same static. - PlaceBase::Static(_) => true, - _ => false - } - }) + match place.base { + // Static variables need a borrow because the callee + // might modify the same static. + PlaceBase::Static(_) => true, + _ => false + } } let dest = if dest_needs_borrow(&destination.0) { @@ -464,7 +457,7 @@ impl Inliner<'tcx> { let stmt = Statement { source_info: callsite.location, - kind: StatementKind::Assign(tmp.clone(), box dest) + kind: StatementKind::Assign(box(tmp.clone(), dest)) }; caller_body[callsite.bb] .statements.push(stmt); @@ -484,12 +477,10 @@ impl Inliner<'tcx> { args: &args, local_map, scope_map, - promoted_map, - _callsite: callsite, destination: dest, return_block, cleanup_block: cleanup, - in_cleanup_block: false + in_cleanup_block: false, }; @@ -598,7 +589,7 @@ impl Inliner<'tcx> { if let Operand::Move(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) = arg { if caller_body.local_kind(local) == LocalKind::Temp { // Reuse the operand if it's a temporary already @@ -617,7 +608,7 @@ impl Inliner<'tcx> { let stmt = Statement { source_info: callsite.location, - kind: StatementKind::Assign(Place::from(arg_tmp), box arg), + kind: StatementKind::Assign(box(Place::from(arg_tmp), arg)), }; caller_body[callsite.bb].statements.push(stmt); arg_tmp @@ -644,8 +635,6 @@ struct Integrator<'a, 'tcx> { args: &'a [Local], local_map: IndexVec, scope_map: IndexVec, - promoted_map: IndexVec, - _callsite: CallSite<'tcx>, destination: Place<'tcx>, return_block: BasicBlock, cleanup_block: Option, @@ -669,7 +658,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { match self.destination { Place { base: PlaceBase::Local(l), - projection: None, + projection: box [], } => { *local = l; return; @@ -693,22 +682,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { match place { Place { base: PlaceBase::Local(RETURN_PLACE), - projection: None, + projection: box [], } => { // Return pointer; update the place itself *place = self.destination.clone(); }, - Place { - base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), - .. - }), - projection: None, - } => { - if let Some(p) = self.promoted_map.get(*promoted).cloned() { - *promoted = p; - } - }, _ => self.super_place(place, _ctxt, _location) } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 5542926503..0e04e63af4 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -11,8 +11,8 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; -impl MirPass for InstCombine { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for InstCombine { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return @@ -43,12 +43,21 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { let new_place = match *rvalue { Rvalue::Ref(_, _, Place { ref mut base, - projection: Some(ref mut projection), - }) => Place { - // Replace with dummy - base: mem::replace(base, PlaceBase::Local(Local::new(0))), - projection: projection.base.take(), - }, + projection: ref mut projection @ box [.., _], + }) => { + if let box [proj_l @ .., proj_r] = projection { + let place = Place { + // Replace with dummy + base: mem::replace(base, PlaceBase::Local(Local::new(0))), + projection: proj_l.to_vec().into_boxed_slice(), + }; + *projection = vec![proj_r.clone()].into_boxed_slice(); + + place + } else { + unreachable!(); + } + } _ => bug!("Detected `&*` but didn't find `&*`!"), }; *rvalue = Rvalue::Use(Operand::Copy(new_place)) @@ -83,13 +92,11 @@ impl OptimizationFinder<'b, 'tcx> { impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { if let Rvalue::Ref(_, _, Place { - ref base, - projection: Some(ref projection), - }) = *rvalue { - if let ProjectionElem::Deref = projection.elem { - if Place::ty_from(&base, &projection.base, self.body, self.tcx).ty.is_region_ptr() { - self.optimizations.and_stars.insert(location); - } + base, + projection: box [proj_base @ .., ProjectionElem::Deref], + }) = rvalue { + if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() { + self.optimizations.and_stars.insert(location); } } @@ -97,8 +104,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { let place_ty = place.ty(&self.body.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.sty { let span = self.body.source_info(location).span; - let ty = self.tcx.types.usize; - let constant = Constant { span, ty, literal: len, user_ty: None }; + let constant = Constant { span, literal: len, user_ty: None }; self.optimizations.arrays_lengths.insert(location, constant); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 61d0b1f348..ac291c2996 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -137,60 +137,50 @@ pub fn default_name() -> Cow<'static, str> { /// A streamlined trait that you can implement to create a pass; the /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass { +pub trait MirPass<'tcx> { fn name(&self) -> Cow<'_, str> { default_name::() } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); } pub fn run_passes( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, instance: InstanceDef<'tcx>, + promoted: Option, mir_phase: MirPhase, - passes: &[&dyn MirPass], + passes: &[&dyn MirPass<'tcx>], ) { let phase_index = mir_phase.phase_index(); - let run_passes = |body: &mut Body<'tcx>, promoted| { - if body.phase >= mir_phase { - return; - } + if body.phase >= mir_phase { + return; + } - let source = MirSource { - instance, - promoted, - }; - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass| { - let run_hooks = |body: &_, index, is_after| { - dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), - &pass.name(), source, body, is_after); - }; - run_hooks(body, index, false); - pass.run_pass(tcx, source, body); - run_hooks(body, index, true); - - index += 1; + let source = MirSource { + instance, + promoted, + }; + let mut index = 0; + let mut run_pass = |pass: &dyn MirPass<'tcx>| { + let run_hooks = |body: &_, index, is_after| { + dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), + &pass.name(), source, body, is_after); }; + run_hooks(body, index, false); + pass.run_pass(tcx, source, body); + run_hooks(body, index, true); - for pass in passes { - run_pass(*pass); - } - - body.phase = mir_phase; + index += 1; }; - run_passes(body, None); - - for (index, promoted_body) in body.promoted.iter_enumerated_mut() { - run_passes(promoted_body, Some(index)); - - //Let's make sure we don't miss any nested instances - assert!(promoted_body.promoted.is_empty()) + for pass in passes { + run_pass(*pass); } + + body.phase = mir_phase; } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { @@ -198,7 +188,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { let _ = tcx.unsafety_check_result(def_id); let mut body = tcx.mir_built(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Const, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[ // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, @@ -207,7 +197,10 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { tcx.alloc_steal_mir(body) } -fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { +fn mir_validated( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> (&'tcx Steal>, &'tcx Steal>>) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(hir_id) { // Ensure that we compute the `mir_const_qualif` for constants at @@ -216,33 +209,23 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { } let mut body = tcx.mir_const(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Validated, &[ + let qualify_and_promote_pass = qualify_consts::QualifyAndPromoteConstants::default(); + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ // What we need to run borrowck etc. - &qualify_consts::QualifyAndPromoteConstants, + &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - tcx.alloc_steal_mir(body) + let promoted = qualify_and_promote_pass.promoted.into_inner(); + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } -fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { - if tcx.is_constructor(def_id) { - // There's no reason to run all of the MIR passes on constructors when - // we can just output the MIR we want directly. This also saves const - // qualification and borrow checking the trouble of special casing - // constructors. - return shim::build_adt_ctor(tcx, def_id); - } - - // (Mir-)Borrowck uses `mir_validated`, so we have to force it to - // execute before we can steal. - tcx.ensure().mir_borrowck(def_id); - - if tcx.use_ast_borrowck() { - tcx.ensure().borrowck(def_id); - } - - let mut body = tcx.mir_validated(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ +fn run_optimization_passes<'tcx>( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + def_id: DefId, + promoted: Option, +) { + run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads, &simplify_branches::SimplifyBranches::new("initial"), @@ -293,10 +276,43 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { &add_call_guards::CriticalCallEdges, &dump_mir::Marker("PreCodegen"), ]); +} + +fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { + if tcx.is_constructor(def_id) { + // There's no reason to run all of the MIR passes on constructors when + // we can just output the MIR we want directly. This also saves const + // qualification and borrow checking the trouble of special casing + // constructors. + return shim::build_adt_ctor(tcx, def_id); + } + + // (Mir-)Borrowck uses `mir_validated`, so we have to force it to + // execute before we can steal. + tcx.ensure().mir_borrowck(def_id); + + if tcx.use_ast_borrowck() { + tcx.ensure().borrowck(def_id); + } + + let (body, _) = tcx.mir_validated(def_id); + let mut body = body.steal(); + run_optimization_passes(tcx, &mut body, def_id, None); tcx.arena.alloc(body) } fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { - let body = tcx.optimized_mir(def_id); - &body.promoted + if tcx.is_constructor(def_id) { + return tcx.intern_promoted(IndexVec::new()); + } + + tcx.ensure().mir_borrowck(def_id); + let (_, promoted) = tcx.mir_validated(def_id); + let mut promoted = promoted.steal(); + + for (p, mut body) in promoted.iter_enumerated_mut() { + run_optimization_passes(tcx, &mut body, def_id, Some(p)); + } + + tcx.intern_promoted(promoted) } diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 841db80fc7..762bb5d448 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -8,8 +8,8 @@ use crate::transform::{MirPass, MirSource}; pub struct NoLandingPads; -impl MirPass for NoLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for NoLandingPads { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { no_landing_pads(tcx, body) } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3090b63a7e..7d1b96b8be 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -12,9 +12,11 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. +use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; +use rustc::ty::subst::InternalSubsts; use rustc::ty::TyCtxt; use syntax_pos::Span; @@ -185,7 +187,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { span, scope: OUTERMOST_SOURCE_SCOPE }, - kind: StatementKind::Assign(Place::from(dest), box rvalue) + kind: StatementKind::Assign(box(Place::from(dest), rvalue)) }); } @@ -220,10 +222,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // First, take the Rvalue or Call out of the source MIR, // or duplicate it, depending on keep_original. if loc.statement_index < no_stmts { - let (rvalue, source_info) = { + let (mut rvalue, source_info) = { let statement = &mut self.source[loc.block].statements[loc.statement_index]; let rhs = match statement.kind { - StatementKind::Assign(_, ref mut rhs) => rhs, + StatementKind::Assign(box(_, ref mut rhs)) => rhs, _ => { span_bug!(statement.source_info.span, "{:?} is not an assignment", statement); @@ -233,12 +235,11 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { (if self.keep_original { rhs.clone() } else { - let unit = box Rvalue::Aggregate(box AggregateKind::Tuple, vec![]); + let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]); mem::replace(rhs, unit) }, statement.source_info) }; - let mut rvalue = *rvalue; self.visit_rvalue(&mut rvalue, loc); self.assign(new_temp, rvalue, source_info.span); } else { @@ -293,19 +294,30 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate) { + fn promote_candidate( + mut self, + def_id: DefId, + candidate: Candidate, + next_promoted_id: usize, + ) -> Option> { let mut operand = { let promoted = &mut self.promoted; - let promoted_id = Promoted::new(self.source.promoted.len()); + let promoted_id = Promoted::new(next_promoted_id); + let tcx = self.tcx; let mut promoted_place = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted_id), - ty + kind: + StaticKind::Promoted( + promoted_id, + InternalSubsts::identity_for_item(tcx, def_id), + ), + ty, + def_id, }), - projection: None, + projection: box [], } }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); @@ -313,14 +325,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place)) => { + StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => { // Use the underlying local for this (necessarily interior) borrow. let ty = place.base.ty(local_decls).ty; let span = statement.source_info.span; Operand::Move(Place { - base: mem::replace(&mut place.base, promoted_place(ty, span).base), - projection: None, + base: mem::replace( + &mut place.base, + promoted_place(ty, span).base, + ), + projection: box [], }) } _ => bug!() @@ -329,10 +344,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Candidate::Repeat(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(_, box Rvalue::Repeat(ref mut operand, _)) => { + StatementKind::Assign(box(_, Rvalue::Repeat(ref mut operand, _))) => { let ty = operand.ty(local_decls, self.tcx); let span = statement.source_info.span; - mem::replace(operand, Operand::Copy(promoted_place(ty, span))) + mem::replace( + operand, + Operand::Copy(promoted_place(ty, span)) + ) } _ => bug!() } @@ -353,7 +371,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // a function requiring a constant argument and as that constant value // providing a value whose computation contains another call to a function // requiring a constant argument. - TerminatorKind::Goto { .. } => return, + TerminatorKind::Goto { .. } => return None, _ => bug!() } } @@ -368,7 +386,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, Rvalue::Use(operand), span); - self.source.promoted.push(self.promoted); + Some(self.promoted) } } @@ -385,23 +403,26 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { } pub fn promote_candidates<'tcx>( + def_id: DefId, body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, -) { +) -> IndexVec> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); + let mut promotions = IndexVec::new(); + for candidate in candidates.into_iter().rev() { match candidate { Candidate::Repeat(Location { block, statement_index }) | Candidate::Ref(Location { block, statement_index }) => { match body[block].statements[statement_index].kind { - StatementKind::Assign(Place { + StatementKind::Assign(box(Place { base: PlaceBase::Local(local), - projection: None, - }, _) => { + projection: box [], + }, _)) => { if temps[local] == TempState::PromotedOut { // Already promoted. continue; @@ -426,7 +447,6 @@ pub fn promote_candidates<'tcx>( // memory usage? body.source_scopes.clone(), body.source_scope_local_data.clone(), - IndexVec::new(), None, initial_locals, IndexVec::new(), @@ -440,7 +460,11 @@ pub fn promote_candidates<'tcx>( temps: &mut temps, keep_original: false }; - promoter.promote_candidate(candidate); + + //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice + if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) { + promotions.push(promoted); + } } // Eliminate assignments to, and drops of promoted temps. @@ -448,10 +472,10 @@ pub fn promote_candidates<'tcx>( for block in body.basic_blocks_mut() { block.statements.retain(|statement| { match statement.kind { - StatementKind::Assign(Place { + StatementKind::Assign(box(Place { base: PlaceBase::Local(index), - projection: None, - }, _) | + projection: box [], + }, _)) | StatementKind::StorageLive(index) | StatementKind::StorageDead(index) => { !promoted(index) @@ -463,7 +487,7 @@ pub fn promote_candidates<'tcx>( match terminator.kind { TerminatorKind::Drop { location: Place { base: PlaceBase::Local(index), - projection: None, + projection: box [], }, target, .. } => { if promoted(index) { terminator.kind = TerminatorKind::Goto { @@ -474,4 +498,6 @@ pub fn promote_candidates<'tcx>( _ => {} } } + + promotions } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dcfc80968f..795721f3b3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -25,10 +25,13 @@ use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; +use std::borrow::Cow; +use std::cell::Cell; use std::fmt; use std::ops::{Deref, Index, IndexMut}; use std::usize; +use rustc::hir::HirId; use crate::transform::{MirPass, MirSource}; use super::promote_consts::{self, Candidate, TempState}; @@ -184,26 +187,28 @@ trait Qualif { cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>, ) -> bool { - let proj = place.projection.as_ref().unwrap(); - - let base_qualif = Self::in_place(cx, PlaceRef { - base: place.base, - projection: &proj.base, - }); - let qualif = base_qualif && Self::mask_for_ty( - cx, - Place::ty_from(place.base, &proj.base, cx.body, cx.tcx) - .projection_ty(cx.tcx, &proj.elem) - .ty, - ); - match proj.elem { - ProjectionElem::Deref | - ProjectionElem::Subslice { .. } | - ProjectionElem::Field(..) | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Downcast(..) => qualif, - - ProjectionElem::Index(local) => qualif || Self::in_local(cx, local), + if let [proj_base @ .., elem] = place.projection { + let base_qualif = Self::in_place(cx, PlaceRef { + base: place.base, + projection: proj_base, + }); + let qualif = base_qualif && Self::mask_for_ty( + cx, + Place::ty_from(place.base, proj_base, cx.body, cx.tcx) + .projection_ty(cx.tcx, elem) + .ty, + ); + match elem { + ProjectionElem::Deref | + ProjectionElem::Subslice { .. } | + ProjectionElem::Field(..) | + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Downcast(..) => qualif, + + ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local), + } + } else { + bug!("This should be called if projection is not empty"); } } @@ -218,24 +223,24 @@ trait Qualif { match place { PlaceRef { base: PlaceBase::Local(local), - projection: None, + projection: [], } => Self::in_local(cx, *local), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), - projection: None, + projection: [], } => bug!("qualifying already promoted MIR"), PlaceRef { base: PlaceBase::Static(static_), - projection: None, + projection: [], } => { Self::in_static(cx, static_) }, PlaceRef { base: _, - projection: Some(_), + projection: [.., _], } => Self::in_projection(cx, place), } } @@ -249,7 +254,7 @@ trait Qualif { if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def_id).is_some() { - Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false) + Self::in_any_value_of_ty(cx, constant.literal.ty).unwrap_or(false) } else { let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id); @@ -258,7 +263,7 @@ trait Qualif { // Just in case the type is more specific than // the definition, e.g., impl associated const // with type parameters, take it into account. - qualif && Self::mask_for_ty(cx, constant.ty) + qualif && Self::mask_for_ty(cx, constant.literal.ty) } } else { false @@ -286,13 +291,13 @@ trait Qualif { Rvalue::Ref(_, _, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let Some(ref proj) = place.projection { - if let ProjectionElem::Deref = proj.elem { - let base_ty = Place::ty_from(&place.base, &proj.base, cx.body, cx.tcx).ty; + if let box [proj_base @ .., elem] = &place.projection { + if ProjectionElem::Deref == *elem { + let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty; if let ty::Ref(..) = base_ty.sty { return Self::in_place(cx, PlaceRef { base: &place.base, - projection: &proj.base, + projection: proj_base, }); } } @@ -433,13 +438,13 @@ impl Qualif for IsNotPromotable { fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool { match static_.kind { - StaticKind::Promoted(_) => unreachable!(), - StaticKind::Static(def_id) => { + StaticKind::Promoted(_, _) => unreachable!(), + StaticKind::Static => { // Only allow statics (not consts) to refer to other statics. let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut; !allowed || - cx.tcx.get_attrs(def_id).iter().any( + cx.tcx.get_attrs(static_.def_id).iter().any( |attr| attr.check_name(sym::thread_local) ) } @@ -450,30 +455,32 @@ impl Qualif for IsNotPromotable { cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>, ) -> bool { - let proj = place.projection.as_ref().unwrap(); - - match proj.elem { - ProjectionElem::Deref | - ProjectionElem::Downcast(..) => return true, - - ProjectionElem::ConstantIndex {..} | - ProjectionElem::Subslice {..} | - ProjectionElem::Index(_) => {} - - ProjectionElem::Field(..) => { - if cx.mode == Mode::NonConstFn { - let base_ty = Place::ty_from(place.base, &proj.base, cx.body, cx.tcx).ty; - if let Some(def) = base_ty.ty_adt_def() { - // No promotion of union field accesses. - if def.is_union() { - return true; + if let [proj_base @ .., elem] = place.projection { + match elem { + ProjectionElem::Deref | + ProjectionElem::Downcast(..) => return true, + + ProjectionElem::ConstantIndex {..} | + ProjectionElem::Subslice {..} | + ProjectionElem::Index(_) => {} + + ProjectionElem::Field(..) => { + if cx.mode == Mode::NonConstFn { + let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty; + if let Some(def) = base_ty.ty_adt_def() { + // No promotion of union field accesses. + if def.is_union() { + return true; + } } } } } - } - Self::in_projection_structurally(cx, place) + Self::in_projection_structurally(cx, place) + } else { + bug!("This should be called if projection is not empty"); + } } fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool { @@ -537,9 +544,9 @@ impl Qualif for IsNotPromotable { | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "unchecked_shl" | "unchecked_shr" | "rotate_left" @@ -803,23 +810,18 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { // We might have a candidate for promotion. let candidate = Candidate::Ref(location); // Start by traversing to the "base", with non-deref projections removed. - let mut place_projection = &place.projection; - while let Some(proj) = place_projection { - if proj.elem == ProjectionElem::Deref { - break; - } - place_projection = &proj.base; - } + let deref_proj = + place.projection.iter().rev().find(|&elem| *elem == ProjectionElem::Deref); debug!( "qualify_consts: promotion candidate: place={:?} {:?}", - place.base, place_projection + place.base, deref_proj ); // We can only promote interior borrows of promotable temps (non-temps // don't get promoted anyway). // (If we bailed out of the loop due to a `Deref` above, we will definitely // not enter the conditional here.) - if let (PlaceBase::Local(local), None) = (&place.base, place_projection) { + if let (PlaceBase::Local(local), None) = (&place.base, deref_proj) { if self.body.local_kind(*local) == LocalKind::Temp { debug!("qualify_consts: promotion candidate: local={:?}", local); // The borrowed place doesn't have `HasMutInterior` @@ -855,27 +857,27 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { _ => {}, } - let mut dest_projection = &dest.projection; + let mut dest_projection = &dest.projection[..]; let index = loop { match (&dest.base, dest_projection) { // We treat all locals equal in constants - (&PlaceBase::Local(index), None) => break index, + (&PlaceBase::Local(index), []) => break index, // projections are transparent for assignments // we qualify the entire destination at once, even if just a field would have // stricter qualification - (base, Some(proj)) => { + (base, [proj_base @ .., _]) => { // Catch more errors in the destination. `visit_place` also checks various // projection rules like union field access and raw pointer deref let context = PlaceContext::MutatingUse(MutatingUseContext::Store); self.visit_place_base(base, context, location); - self.visit_projection(base, proj, context, location); - dest_projection = &proj.base; + self.visit_projection(base, dest_projection, context, location); + dest_projection = proj_base; }, (&PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. - }), None) => bug!("promoteds don't exist yet during promotion"), - (&PlaceBase::Static(box Static{ kind: _, .. }), None) => { + }), []) => bug!("promoteds don't exist yet during promotion"), + (&PlaceBase::Static(box Static{ kind: _, .. }), []) => { // Catch more errors in the destination. `visit_place` also checks that we // do not try to access statics from constants or try to mutate statics let context = PlaceContext::MutatingUse(MutatingUseContext::Store); @@ -980,23 +982,25 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { for candidate in &self.promotion_candidates { match *candidate { Candidate::Repeat(Location { block: bb, statement_index: stmt_idx }) => { - if let StatementKind::Assign(_, box Rvalue::Repeat( + if let StatementKind::Assign(box(_, Rvalue::Repeat( Operand::Move(Place { base: PlaceBase::Local(index), - projection: None, + projection: box [], }), _ - )) = self.body[bb].statements[stmt_idx].kind { + ))) = self.body[bb].statements[stmt_idx].kind { promoted_temps.insert(index); } } Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => { if let StatementKind::Assign( - _, - box Rvalue::Ref(_, _, Place { - base: PlaceBase::Local(index), - projection: None, - }) + box( + _, + Rvalue::Ref(_, _, Place { + base: PlaceBase::Local(index), + projection: box [], + }) + ) ) = self.body[bb].statements[stmt_idx].kind { promoted_temps.insert(index); } @@ -1027,10 +1031,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { self.super_place_base(place_base, context, location); match place_base { PlaceBase::Local(_) => {} - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => { unreachable!() } - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { if self.tcx .get_attrs(*def_id) .iter() @@ -1081,7 +1085,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { fn visit_projection( &mut self, place_base: &PlaceBase<'tcx>, - proj: &Projection<'tcx>, + proj: &[PlaceElem<'tcx>], context: PlaceContext, location: Location, ) { @@ -1090,62 +1094,65 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { proj, context, location, ); self.super_projection(place_base, proj, context, location); - match proj.elem { - ProjectionElem::Deref => { - if context.is_mutating_use() { - // `not_const` errors out in const contexts - self.not_const() - } - let base_ty = Place::ty_from(place_base, &proj.base, self.body, self.tcx).ty; - match self.mode { - Mode::NonConstFn => {}, - _ => { - if let ty::RawPtr(_) = base_ty.sty { - if !self.tcx.features().const_raw_ptr_deref { - emit_feature_err( - &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref, - self.span, GateIssue::Language, - &format!( - "dereferencing raw pointers in {}s is unstable", - self.mode, - ), - ); - } - } - } - } - } - ProjectionElem::ConstantIndex {..} | - ProjectionElem::Subslice {..} | - ProjectionElem::Field(..) | - ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(place_base, &proj.base, self.body, self.tcx).ty; - if let Some(def) = base_ty.ty_adt_def() { - if def.is_union() { - match self.mode { - Mode::ConstFn => { - if !self.tcx.features().const_fn_union { + if let [proj_base @ .., elem] = proj { + match elem { + ProjectionElem::Deref => { + if context.is_mutating_use() { + // `not_const` errors out in const contexts + self.not_const() + } + let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; + match self.mode { + Mode::NonConstFn => {}, + _ => { + if let ty::RawPtr(_) = base_ty.sty { + if !self.tcx.features().const_raw_ptr_deref { emit_feature_err( - &self.tcx.sess.parse_sess, sym::const_fn_union, + &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref, self.span, GateIssue::Language, - "unions in const fn are unstable", + &format!( + "dereferencing raw pointers in {}s is unstable", + self.mode, + ), ); } - }, + } + } + } + } - | Mode::NonConstFn - | Mode::Static - | Mode::StaticMut - | Mode::Const - => {}, + ProjectionElem::ConstantIndex {..} | + ProjectionElem::Subslice {..} | + ProjectionElem::Field(..) | + ProjectionElem::Index(_) => { + let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; + if let Some(def) = base_ty.ty_adt_def() { + if def.is_union() { + match self.mode { + Mode::ConstFn => { + if !self.tcx.features().const_fn_union { + emit_feature_err( + &self.tcx.sess.parse_sess, sym::const_fn_union, + self.span, GateIssue::Language, + "unions in const fn are unstable", + ); + } + }, + + | Mode::NonConstFn + | Mode::Static + | Mode::StaticMut + | Mode::Const + => {}, + } } } } - } - ProjectionElem::Downcast(..) => { - self.not_const() + ProjectionElem::Downcast(..) => { + self.not_const() + } } } } @@ -1159,7 +1166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // Mark the consumed locals to indicate later drops are noops. if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = *place { self.cx.per_local[NeedsDrop].remove(local); } @@ -1176,11 +1183,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if let Rvalue::Ref(_, kind, ref place) = *rvalue { // Special-case reborrows. let mut reborrow_place = None; - if let Some(ref proj) = place.projection { - if let ProjectionElem::Deref = proj.elem { - let base_ty = Place::ty_from(&place.base, &proj.base, self.body, self.tcx).ty; + if let box [proj_base @ .., elem] = &place.projection { + if *elem == ProjectionElem::Deref { + let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.sty { - reborrow_place = Some(&proj.base); + reborrow_place = Some(proj_base); } } } @@ -1201,9 +1208,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { ), }; self.visit_place_base(&place.base, ctx, location); - if let Some(proj) = proj { - self.visit_projection(&place.base, proj, ctx, location); - } + self.visit_projection(&place.base, proj, ctx, location); } else { self.super_rvalue(rvalue, location); } @@ -1402,10 +1407,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } } ty::FnPtr(_) => { - if self.mode.requires_const_checking() { + let unleash_miri = self + .tcx + .sess + .opts + .debugging_opts + .unleash_the_miri_inside_of_you; + if self.mode.requires_const_checking() && !unleash_miri { let mut err = self.tcx.sess.struct_span_err( self.span, - &format!("function pointers are not allowed in const fn")); + "function pointers are not allowed in const fn" + ); err.emit(); } } @@ -1474,7 +1486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // conservatively, that drop elaboration will do. let needs_drop = if let Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], } = *place { if NeedsDrop::in_local(self, local) { Some(self.body.local_decls[local].source_info.span) @@ -1570,10 +1582,20 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { Checker::new(tcx, def_id, body, Mode::Const).check_const() } -pub struct QualifyAndPromoteConstants; +pub struct QualifyAndPromoteConstants<'tcx> { + pub promoted: Cell>>, +} + +impl<'tcx> Default for QualifyAndPromoteConstants<'tcx> { + fn default() -> Self { + QualifyAndPromoteConstants { + promoted: Cell::new(IndexVec::new()), + } + } +} -impl MirPass for QualifyAndPromoteConstants { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. if body.return_ty().references_error() { tcx.sess.delay_span_bug(body.span, "QualifyAndPromoteConstants: MIR had errors"); @@ -1585,51 +1607,24 @@ impl MirPass for QualifyAndPromoteConstants { } let def_id = src.def_id(); - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let mut const_promoted_temps = None; - let mode = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Closure => Mode::NonConstFn, - hir::BodyOwnerKind::Fn => { - if tcx.is_const_fn(def_id) { - Mode::ConstFn - } else { - Mode::NonConstFn - } - } - hir::BodyOwnerKind::Const => { - const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1); - Mode::Const - } - hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, - hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, - }; + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + + let mode = determine_mode(tcx, hir_id, def_id); debug!("run_pass: mode={:?}", mode); - if mode == Mode::NonConstFn || mode == Mode::ConstFn { + if let Mode::NonConstFn | Mode::ConstFn = mode { // This is ugly because Checker holds onto mir, // which can't be mutated until its scope ends. let (temps, candidates) = { let mut checker = Checker::new(tcx, def_id, body, mode); - if mode == Mode::ConstFn { + if let Mode::ConstFn = mode { if tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you { checker.check_const(); } else if tcx.is_min_const_fn(def_id) { - // enforce `min_const_fn` for stable const fns + // Enforce `min_const_fn` for stable `const fn`s. use super::qualify_min_const_fn::is_min_const_fn; if let Err((span, err)) = is_min_const_fn(tcx, def_id, body) { - let mut diag = struct_span_err!( - tcx.sess, - span, - E0723, - "{}", - err, - ); - diag.note("for more information, see issue \ - https://github.com/rust-lang/rust/issues/57563"); - diag.help( - "add `#![feature(const_fn)]` to the crate attributes to enable", - ); - diag.emit(); + error_min_const_fn_violation(tcx, span, err); } else { // this should not produce any errors, but better safe than sorry // FIXME(#53819) @@ -1649,106 +1644,123 @@ impl MirPass for QualifyAndPromoteConstants { }; // Do the actual promotion, now that we know what's viable. - promote_consts::promote_candidates(body, tcx, temps, candidates); + self.promoted.set( + promote_consts::promote_candidates(def_id, body, tcx, temps, candidates) + ); } else { - if !body.control_flow_destroyed.is_empty() { - let mut locals = body.vars_iter(); - if let Some(local) = locals.next() { - let span = body.local_decls[local].source_info.span; - let mut error = tcx.sess.struct_span_err( - span, - &format!( - "new features like let bindings are not permitted in {}s \ - which also use short circuiting operators", - mode, - ), - ); - for (span, kind) in body.control_flow_destroyed.iter() { - error.span_note( - *span, - &format!("use of {} here does not actually short circuit due to \ - the const evaluator presently not being able to do control flow. \ - See https://github.com/rust-lang/rust/issues/49146 for more \ - information.", kind), - ); - } - for local in locals { - let span = body.local_decls[local].source_info.span; - error.span_note( - span, - "more locals defined here", - ); - } - error.emit(); - } - } - let promoted_temps = if mode == Mode::Const { - // Already computed by `mir_const_qualif`. - const_promoted_temps.unwrap() - } else { - Checker::new(tcx, def_id, body, mode).check_const().1 + check_short_circuiting_in_const_local(tcx, body, mode); + + let promoted_temps = match mode { + Mode::Const => tcx.mir_const_qualif(def_id).1, + _ => Checker::new(tcx, def_id, body, mode).check_const().1, }; + remove_drop_and_storage_dead_on_promoted_locals(body, promoted_temps); + } - // In `const` and `static` everything without `StorageDead` - // is `'static`, we don't have to create promoted MIR fragments, - // just remove `Drop` and `StorageDead` on "promoted" locals. - debug!("run_pass: promoted_temps={:?}", promoted_temps); - for block in body.basic_blocks_mut() { - block.statements.retain(|statement| { - match statement.kind { - StatementKind::StorageDead(index) => { - !promoted_temps.contains(index) - } - _ => true - } - }); - let terminator = block.terminator_mut(); - match terminator.kind { - TerminatorKind::Drop { - location: Place { - base: PlaceBase::Local(index), - projection: None, - }, - target, - .. - } => { - if promoted_temps.contains(index) { - terminator.kind = TerminatorKind::Goto { - target, - }; - } - } - _ => {} - } - } + if mode == Mode::Static && !tcx.has_attr(def_id, sym::thread_local) { + // `static`s (not `static mut`s) which are not `#[thread_local]` must be `Sync`. + check_static_is_sync(tcx, body, hir_id); } + } +} - // Statics must be Sync. - if mode == Mode::Static { - // `#[thread_local]` statics don't have to be `Sync`. - for attr in &tcx.get_attrs(def_id)[..] { - if attr.check_name(sym::thread_local) { - return; - } +fn determine_mode(tcx: TyCtxt<'_>, hir_id: HirId, def_id: DefId) -> Mode { + match tcx.hir().body_owner_kind(hir_id) { + hir::BodyOwnerKind::Closure => Mode::NonConstFn, + hir::BodyOwnerKind::Fn if tcx.is_const_fn(def_id) => Mode::ConstFn, + hir::BodyOwnerKind::Fn => Mode::NonConstFn, + hir::BodyOwnerKind::Const => Mode::Const, + hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, + hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, + } +} + +fn error_min_const_fn_violation(tcx: TyCtxt<'_>, span: Span, msg: Cow<'_, str>) { + struct_span_err!(tcx.sess, span, E0723, "{}", msg) + .note("for more information, see issue https://github.com/rust-lang/rust/issues/57563") + .help("add `#![feature(const_fn)]` to the crate attributes to enable") + .emit(); +} + +fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, mode: Mode) { + if body.control_flow_destroyed.is_empty() { + return; + } + + let mut locals = body.vars_iter(); + if let Some(local) = locals.next() { + let span = body.local_decls[local].source_info.span; + let mut error = tcx.sess.struct_span_err( + span, + &format!( + "new features like let bindings are not permitted in {}s \ + which also use short circuiting operators", + mode, + ), + ); + for (span, kind) in body.control_flow_destroyed.iter() { + error.span_note( + *span, + &format!("use of {} here does not actually short circuit due to \ + the const evaluator presently not being able to do control flow. \ + See https://github.com/rust-lang/rust/issues/49146 for more \ + information.", kind), + ); + } + for local in locals { + let span = body.local_decls[local].source_info.span; + error.span_note(span, "more locals defined here"); + } + error.emit(); + } +} + +/// In `const` and `static` everything without `StorageDead` +/// is `'static`, we don't have to create promoted MIR fragments, +/// just remove `Drop` and `StorageDead` on "promoted" locals. +fn remove_drop_and_storage_dead_on_promoted_locals( + body: &mut Body<'tcx>, + promoted_temps: &BitSet, +) { + debug!("run_pass: promoted_temps={:?}", promoted_temps); + + for block in body.basic_blocks_mut() { + block.statements.retain(|statement| { + match statement.kind { + StatementKind::StorageDead(index) => !promoted_temps.contains(index), + _ => true } - let ty = body.return_ty(); - tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::empty(); - let cause = traits::ObligationCause::new(body.span, id, traits::SharedStatic); - let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_bound(&infcx, - param_env, - ty, - tcx.require_lang_item(lang_items::SyncTraitLangItem), - cause); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None, false); - } - }); + }); + let terminator = block.terminator_mut(); + match terminator.kind { + TerminatorKind::Drop { + location: Place { + base: PlaceBase::Local(index), + projection: box [], + }, + target, + .. + } if promoted_temps.contains(index) => { + terminator.kind = TerminatorKind::Goto { target }; + } + _ => {} } } } +fn check_static_is_sync(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, hir_id: HirId) { + let ty = body.return_ty(); + tcx.infer_ctxt().enter(|infcx| { + let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); + let mut fulfillment_cx = traits::FulfillmentContext::new(); + let sync_def_id = tcx.require_lang_item(lang_items::SyncTraitLangItem, Some(body.span)); + fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause); + if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&err, None, false); + } + }); +} + fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b84bc31ec2..be83c823d4 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -5,6 +5,8 @@ use rustc::ty::{self, Predicate, Ty, TyCtxt, adjustment::{PointerCast}}; use rustc_target::spec::abi; use std::borrow::Cow; use syntax_pos::Span; +use syntax::symbol::{sym, Symbol}; +use syntax::attr; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -67,9 +69,9 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - )?; for bb in body.basic_blocks() { - check_terminator(tcx, body, bb.terminator())?; + check_terminator(tcx, body, def_id, bb.terminator())?; for stmt in &bb.statements { - check_statement(tcx, body, stmt)?; + check_statement(tcx, body, def_id, stmt)?; } } Ok(()) @@ -121,16 +123,17 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc fn check_rvalue( tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &Body<'tcx>, + def_id: DefId, rvalue: &Rvalue<'tcx>, span: Span, ) -> McfResult { match rvalue { Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { - check_place(place, span) + check_place(tcx, place, span, def_id, body) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { use rustc::ty::cast::CastTy; @@ -144,11 +147,11 @@ fn check_rvalue( (CastTy::RPtr(_), CastTy::Float) => bug!(), (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), - _ => check_operand(operand, span), + _ => check_operand(tcx, operand, span, def_id, body), } } Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) | Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), _, _) | @@ -162,8 +165,8 @@ fn check_rvalue( )), // binops are fine on integers Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - check_operand(lhs, span)?; - check_operand(rhs, span)?; + check_operand(tcx, lhs, span, def_id, body)?; + check_operand(tcx, rhs, span, def_id, body)?; let ty = lhs.ty(body, tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) @@ -182,7 +185,7 @@ fn check_rvalue( Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } else { Err(( span, @@ -192,7 +195,7 @@ fn check_rvalue( } Rvalue::Aggregate(_, operands) => { for operand in operands { - check_operand(operand, span)?; + check_operand(tcx, operand, span, def_id, body)?; } Ok(()) } @@ -201,21 +204,22 @@ fn check_rvalue( fn check_statement( tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &Body<'tcx>, + def_id: DefId, statement: &Statement<'tcx>, ) -> McfResult { let span = statement.source_info.span; match &statement.kind { - StatementKind::Assign(place, rval) => { - check_place(place, span)?; - check_rvalue(tcx, body, rval, span) + StatementKind::Assign(box(place, rval)) => { + check_place(tcx, place, span, def_id, body)?; + check_rvalue(tcx, body, def_id, rval, span) } StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => { Err((span, "loops and conditional expressions are not stable in const fn".into())) } - StatementKind::FakeRead(_, place) => check_place(place, span), + StatementKind::FakeRead(_, place) => check_place(tcx, place, span, def_id, body), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), @@ -234,48 +238,75 @@ fn check_statement( } fn check_operand( + tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, + def_id: DefId, + body: &Body<'tcx> ) -> McfResult { match operand { Operand::Move(place) | Operand::Copy(place) => { - check_place(place, span) + check_place(tcx, place, span, def_id, body) } Operand::Constant(_) => Ok(()), } } fn check_place( + tcx: TyCtxt<'tcx>, place: &Place<'tcx>, span: Span, + def_id: DefId, + body: &Body<'tcx> ) -> McfResult { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - match proj.elem { - ProjectionElem::Downcast(..) => { - return Err((span, "`match` or `if let` in `const fn` is unstable".into())); + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + match elem { + ProjectionElem::Downcast(..) => { + return Err((span, "`match` or `if let` in `const fn` is unstable".into())); + } + ProjectionElem::Field(..) => { + let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty; + if let Some(def) = base_ty.ty_adt_def() { + // No union field accesses in `const fn` + if def.is_union() { + if !feature_allowed(tcx, def_id, sym::const_fn_union) { + return Err((span, "accessing union fields is unstable".into())); + } + } } - ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::Deref - | ProjectionElem::Field(..) - | ProjectionElem::Index(_) => {} } + ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Deref + | ProjectionElem::Index(_) => {} } + } - match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. }) => { - Err((span, "cannot access `static` items in const fn".into())) - } - PlaceBase::Local(_) - | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => Ok(()), + match place.base { + PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => { + Err((span, "cannot access `static` items in const fn".into())) } - }) + PlaceBase::Local(_) + | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()), + } +} + +/// Returns whether `allow_internal_unstable(..., , ...)` is present. +fn feature_allowed( + tcx: TyCtxt<'tcx>, + def_id: DefId, + feature_gate: Symbol, +) -> bool { + attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) + .map_or(false, |mut features| features.any(|name| name == feature_gate)) } fn check_terminator( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, + def_id: DefId, terminator: &Terminator<'tcx>, ) -> McfResult { let span = terminator.source_info.span; @@ -285,11 +316,11 @@ fn check_terminator( | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => { - check_place(location, span) + check_place(tcx, location, span, def_id, body) } TerminatorKind::DropAndReplace { location, value, .. } => { - check_place(location, span)?; - check_operand(value, span) + check_place(tcx, location, span, def_id, body)?; + check_operand(tcx, value, span, def_id, body) }, TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( @@ -341,10 +372,10 @@ fn check_terminator( )), } - check_operand(func, span)?; + check_operand(tcx, func, span, def_id, body)?; for arg in args { - check_operand(arg, span)?; + check_operand(tcx, arg, span, def_id, body)?; } Ok(()) } else { @@ -358,7 +389,7 @@ fn check_terminator( msg: _, target: _, cleanup: _, - } => check_operand(cond, span), + } => check_operand(tcx, cond, span, def_id, body), TerminatorKind::FalseUnwind { .. } => { Err((span, "loops are not allowed in const fn".into())) @@ -379,9 +410,9 @@ fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { | "add_with_overflow" // ~> .overflowing_add | "sub_with_overflow" // ~> .overflowing_sub | "mul_with_overflow" // ~> .overflowing_mul - | "overflowing_add" // ~> .wrapping_add - | "overflowing_sub" // ~> .wrapping_sub - | "overflowing_mul" // ~> .wrapping_mul + | "wrapping_add" // ~> .wrapping_add + | "wrapping_sub" // ~> .wrapping_sub + | "wrapping_mul" // ~> .wrapping_mul | "saturating_add" // ~> .saturating_add | "saturating_sub" // ~> .saturating_sub | "unchecked_shl" // ~> .wrapping_shl diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index adba9097d1..70b11944e2 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -18,8 +18,8 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) RemoveNoopLandingPads.remove_nop_landing_pads(body) } -impl MirPass for RemoveNoopLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { remove_noop_landing_pads(tcx, body); } } @@ -41,10 +41,10 @@ impl RemoveNoopLandingPads { // These are all nops in a landing pad } - StatementKind::Assign(Place { + StatementKind::Assign(box(Place { base: PlaceBase::Local(_), - projection: None, - }, box Rvalue::Use(_)) => { + projection: box [], + }, Rvalue::Use(_))) => { // Writing to a local (e.g., a drop flag) does not // turn a landing pad to a non-nop } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 7fe8480c81..68fa082d29 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -23,8 +23,8 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; -impl MirPass for SanityCheck { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SanityCheck { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -120,11 +120,11 @@ fn each_block<'tcx, O>( let peek_arg_place = match args[0] { mir::Operand::Copy(ref place @ mir::Place { base: mir::PlaceBase::Local(_), - projection: None, + projection: box [], }) | mir::Operand::Move(ref place @ mir::Place { base: mir::PlaceBase::Local(_), - projection: None, + projection: box [], }) => Some(place), _ => None, }; @@ -150,7 +150,7 @@ fn each_block<'tcx, O>( for (j, stmt) in statements.iter().enumerate() { debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt); let (place, rvalue) = match stmt.kind { - mir::StatementKind::Assign(ref place, ref rvalue) => { + mir::StatementKind::Assign(box(ref place, ref rvalue)) => { (place, rvalue) } mir::StatementKind::FakeRead(..) | @@ -166,7 +166,7 @@ fn each_block<'tcx, O>( }; if place == peek_arg_place { - if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = **rvalue { + if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = *rvalue { // Okay, our search is over. match move_data.rev_lookup.find(peeking_at_place.as_ref()) { LookupResult::Exact(peek_mpi) => { @@ -224,7 +224,7 @@ fn is_rustc_peek<'a, 'tcx>( if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { if let mir::Operand::Constant(ref func) = *oper { - if let ty::FnDef(def_id, _) = func.ty.sty { + if let ty::FnDef(def_id, _) = func.literal.ty.sty { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic && name == sym::rustc_peek { diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2eed9d453f..d4599ee08a 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -52,12 +52,12 @@ pub fn simplify_cfg(body: &mut Body<'_>) { body.basic_blocks_mut().raw.shrink_to_fit(); } -impl MirPass for SimplifyCfg { +impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); simplify_cfg(body); } @@ -292,8 +292,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; -impl MirPass for SimplifyLocals { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()) }; marker.visit_body(body); // Return pointer and arguments are always live diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 9ffa3db4c2..0a509666d3 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -14,12 +14,12 @@ impl SimplifyBranches { } } -impl MirPass for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyBranches { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(src.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 60489e7fa3..34ad5cb5dc 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -36,8 +36,8 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; -impl MirPass for UniformArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { @@ -61,14 +61,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { rvalue: &Rvalue<'tcx>, location: Location) { if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue { - if let Some(ref proj) = src_place.projection { + if let box [proj_base @ .., elem] = &src_place.projection { if let ProjectionElem::ConstantIndex{offset: _, min_length: _, - from_end: false} = proj.elem { + from_end: false} = elem { // no need to transformation } else { let place_ty = - Place::ty_from(&src_place.base, &proj.base, self.body, self.tcx).ty; + Place::ty_from(&src_place.base, proj_base, self.body, self.tcx).ty; if let ty::Array(item_ty, const_size) = place_ty.sty { if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) { assert!(size <= u32::max_value() as u64, @@ -78,7 +78,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { location, dst_place, &src_place.base, - proj, + &src_place.projection, item_ty, size as u32, ); @@ -97,73 +97,76 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { location: Location, dst_place: &Place<'tcx>, base: &PlaceBase<'tcx>, - proj: &Projection<'tcx>, + proj: &[PlaceElem<'tcx>], item_ty: &'tcx ty::TyS<'tcx>, size: u32) { - match proj.elem { - // uniforms statements like_10 = move _2[:-1]; - ProjectionElem::Subslice{from, to} => { - self.patch.make_nop(location); - let temps : Vec<_> = (from..(size-to)).map(|i| { - let temp = self.patch.new_temp(item_ty, self.body.source_info(location).span); - self.patch.add_statement(location, StatementKind::StorageLive(temp)); + if let [proj_base @ .., elem] = proj { + match elem { + // uniforms statements like_10 = move _2[:-1]; + ProjectionElem::Subslice{from, to} => { + self.patch.make_nop(location); + let temps : Vec<_> = (*from..(size-*to)).map(|i| { + let temp = + self.patch.new_temp(item_ty, self.body.source_info(location).span); + self.patch.add_statement(location, StatementKind::StorageLive(temp)); + + let mut projection = proj_base.to_vec(); + projection.push(ProjectionElem::ConstantIndex { + offset: i, + min_length: size, + from_end: false, + }); + self.patch.add_assign(location, + Place::from(temp), + Rvalue::Use( + Operand::Move( + Place { + base: base.clone(), + projection: projection.into_boxed_slice(), + } + ) + ) + ); + temp + }).collect(); + self.patch.add_assign( + location, + dst_place.clone(), + Rvalue::Aggregate( + box AggregateKind::Array(item_ty), + temps.iter().map( + |x| Operand::Move(Place::from(*x)) + ).collect() + ) + ); + for temp in temps { + self.patch.add_statement(location, StatementKind::StorageDead(temp)); + } + } + // uniforms statements like _11 = move _2[-1 of 1]; + ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} => { + self.patch.make_nop(location); + + let mut projection = proj_base.to_vec(); + projection.push(ProjectionElem::ConstantIndex { + offset: size - offset, + min_length: size, + from_end: false, + }); self.patch.add_assign(location, - Place::from(temp), + dst_place.clone(), Rvalue::Use( Operand::Move( Place { base: base.clone(), - projection: Some(box Projection { - base: proj.base.clone(), - elem: ProjectionElem::ConstantIndex { - offset: i, - min_length: size, - from_end: false, - } - }), + projection: projection.into_boxed_slice(), } ) ) ); - temp - }).collect(); - self.patch.add_assign( - location, - dst_place.clone(), - Rvalue::Aggregate( - box AggregateKind::Array(item_ty), - temps.iter().map( - |x| Operand::Move(Place::from(*x)) - ).collect() - ) - ); - for temp in temps { - self.patch.add_statement(location, StatementKind::StorageDead(temp)); } + _ => {} } - // uniforms statements like _11 = move _2[-1 of 1]; - ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} => { - self.patch.make_nop(location); - self.patch.add_assign(location, - dst_place.clone(), - Rvalue::Use( - Operand::Move( - Place { - base: base.clone(), - projection: Some(box Projection { - base: proj.base.clone(), - elem: ProjectionElem::ConstantIndex { - offset: size - offset, - min_length: size, - from_end: false, - }, - }), - } - ) - ) - ); - } - _ => {} } } } @@ -184,8 +187,8 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { pub struct RestoreSubsliceArrayMoveOut; -impl MirPass for RestoreSubsliceArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { @@ -197,12 +200,12 @@ impl MirPass for RestoreSubsliceArrayMoveOut { for candidate in &visitor.candidates { let statement = &body[candidate.block].statements[candidate.statement_index]; - if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind { - if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval { + if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind { + if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval { let items : Vec<_> = items.iter().map(|item| { if let Operand::Move(Place { base: PlaceBase::Local(local), - projection: None, + projection: box [], }) = item { let local_use = &visitor.locals_use[*local]; let opt_index_and_place = @@ -269,16 +272,17 @@ impl RestoreSubsliceArrayMoveOut { } patch.make_nop(candidate); let size = opt_size.unwrap() as u32; - patch.add_assign(candidate, - dst_place.clone(), - Rvalue::Use( - Operand::Move( - Place { - base: src_place.base.clone(), - projection: Some(box Projection { - base: src_place.projection.clone(), - elem: ProjectionElem::Subslice{ - from: min, to: size - max - 1}})}))); + + let mut projection = src_place.projection.to_vec(); + projection.push(ProjectionElem::Subslice { from: min, to: size - max - 1 }); + patch.add_assign( + candidate, + dst_place.clone(), + Rvalue::Use(Operand::Move(Place { + base: src_place.base.clone(), + projection: projection.into_boxed_slice(), + })), + ); } } @@ -289,23 +293,34 @@ impl RestoreSubsliceArrayMoveOut { if block.statements.len() > location.statement_index { let statement = &block.statements[location.statement_index]; if let StatementKind::Assign( - Place { - base: PlaceBase::Local(_), - projection: None, - }, - box Rvalue::Use(Operand::Move(Place { - base, - projection: Some(box Projection { - base: proj_base, - elem: ProjectionElem::ConstantIndex { + box( + Place { + base: PlaceBase::Local(_), + projection: box [], + }, + Rvalue::Use(Operand::Move(Place { + base: _, + projection: box [.., ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false - } - }), - }))) = &statement.kind { - return Some((*offset, PlaceRef { - base, - projection: proj_base, - })) + }], + })), + ) + ) = &statement.kind { + // FIXME remove once we can use slices patterns + if let StatementKind::Assign( + box( + _, + Rvalue::Use(Operand::Move(Place { + base, + projection: box [proj_base @ .., _], + })), + ) + ) = &statement.kind { + return Some((*offset, PlaceRef { + base, + projection: proj_base, + })) + } } } } diff --git a/src/librustc_mir/util/aggregate.rs b/src/librustc_mir/util/aggregate.rs index 98e70671ab..b3565d40b8 100644 --- a/src/librustc_mir/util/aggregate.rs +++ b/src/librustc_mir/util/aggregate.rs @@ -24,7 +24,7 @@ pub fn expand_aggregate<'tcx>( if adt_def.is_enum() { set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { - place: lhs.clone(), + place: box(lhs.clone()), variant_index, }, source_info, @@ -39,7 +39,7 @@ pub fn expand_aggregate<'tcx>( let variant_index = VariantIdx::new(0); set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { - place: lhs.clone(), + place: box(lhs.clone()), variant_index, }, source_info, @@ -70,7 +70,7 @@ pub fn expand_aggregate<'tcx>( }; Statement { source_info, - kind: StatementKind::Assign(lhs_field, box Rvalue::Use(op)), + kind: StatementKind::Assign(box(lhs_field, Rvalue::Use(op))), } }).chain(set_discriminant) } diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index b8ef77da02..a75c1af04f 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -38,14 +38,15 @@ fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: &Place<' where L: HasLocalDecls<'tcx>, { - let mut place_projection = &place.projection; + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; - while let Some(proj) = place_projection { - match proj.elem { + match elem { // encountered a Deref, which is ABI-aligned ProjectionElem::Deref => break, ProjectionElem::Field(..) => { - let ty = Place::ty_from(&place.base, &proj.base, local_decls, tcx).ty; + let ty = Place::ty_from(&place.base, proj_base, local_decls, tcx).ty; match ty.sty { ty::Adt(def, _) if def.repr.packed() => { return true @@ -55,7 +56,6 @@ where } _ => {} } - place_projection = &proj.base; } false diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 3359d1b3bb..cf9ef55c17 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0381, - "{} of possibly uninitialized variable: `{}`", + "{} of possibly-uninitialized variable: `{}`", verb, desc, ) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 52fd645e38..52ad97bbde 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -586,10 +586,7 @@ where BorrowKind::Mut { allow_two_phase_borrow: false }, Place { base: PlaceBase::Local(cur), - projection: Some(Box::new(Projection { - base: None, - elem: ProjectionElem::Deref, - })), + projection: Box::new([ProjectionElem::Deref]), } ), Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one)) @@ -897,7 +894,10 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); + let free_func = tcx.require_lang_item( + lang_items::BoxFreeFnLangItem, + Some(self.source_info.span) + ); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); @@ -970,7 +970,6 @@ where fn constant_usize(&self, val: u16) -> Operand<'tcx> { Operand::Constant(box Constant { span: self.source_info.span, - ty: self.tcx().types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx(), val.into()), }) @@ -979,7 +978,7 @@ where fn assign(&self, lhs: &Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> { Statement { source_info: self.source_info, - kind: StatementKind::Assign(lhs.clone(), box rhs) + kind: StatementKind::Assign(box(lhs.clone(), rhs)) } } } diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index eb457dacf8..2ea9924af7 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -120,7 +120,7 @@ impl<'tcx> MirPatch<'tcx> { } pub fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) { - self.add_statement(loc, StatementKind::Assign(place, box rv)); + self.add_statement(loc, StatementKind::Assign(box(place, rv))); } pub fn make_nop(&mut self, loc: Location) { diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 68880fc345..c35c9e4da9 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -227,12 +227,12 @@ pub(crate) fn create_dump_file( pass_name: &str, disambiguator: &dyn Display, source: MirSource<'tcx>, -) -> io::Result { +) -> io::Result> { let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, source); if let Some(parent) = file_path.parent() { fs::create_dir_all(parent)?; } - fs::File::create(&file_path) + Ok(io::BufWriter::new(fs::File::create(&file_path)?)) } /// Write out a human-readable textual representation for the given MIR. @@ -397,10 +397,9 @@ impl ExtraComments<'tcx> { impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - let Constant { span, ty, user_ty, literal } = constant; + let Constant { span, user_ty, literal } = constant; self.push("mir::Constant"); self.push(&format!("+ span: {:?}", span)); - self.push(&format!("+ ty: {:?}", ty)); if let Some(user_ty) = user_ty { self.push(&format!("+ user_ty: {:?}", user_ty)); } diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index 1c66b0a9cd..a81786ee36 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -4,6 +4,10 @@ use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { + println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); + if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { + return; + } if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { build_helper::restore_library_path(); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 3c31bcef32..5b78727fdd 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -602,7 +602,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Enum(ref def, _) => { for variant in &def.variants { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.invalid_visibility(&field.vis, None); } } @@ -813,8 +813,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_poly_trait_ref(self, t, m); } - fn visit_variant_data(&mut self, s: &'a VariantData, _: Ident, - _: &'a Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &'a VariantData) { self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s)) } @@ -824,7 +823,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |this| visit::walk_enum_def(this, enum_definition, generics, item_id)) } - fn visit_mac(&mut self, mac: &Spanned) { + fn visit_mac(&mut self, mac: &Mac) { // when a new macro kind is added but the author forgets to set it up for expansion // because that's the only part that won't cause a compiler error self.session.diagnostic() diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index cd33943e77..af07c790e2 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -1,6 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { +syntax::register_diagnostics! { /* E0014: r##" Constants can only be initialized by a constant value or, in a future @@ -131,7 +129,7 @@ be taken. Erroneous code example: ```compile_fail,E0268 fn some_func() { - break; // error: `break` outside of loop + break; // error: `break` outside of a loop } ``` @@ -320,10 +318,8 @@ async fn foo() {} ``` Switch to the Rust 2018 edition to use `async fn`. -"## -} - -register_diagnostics! { +"##, +; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 8fba3256ec..a5924efefc 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -94,9 +94,9 @@ impl<'k> StatCollector<'k> { } impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { - fn visit_arg(&mut self, arg: &'v hir::Arg) { - self.record("Arg", Id::Node(arg.hir_id), arg); - hir_visit::walk_arg(self, arg) + fn visit_param(&mut self, param: &'v hir::Param) { + self.record("Param", Id::Node(param.hir_id), param); + hir_visit::walk_param(self, param) } fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> { @@ -334,12 +334,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_struct_field(self, s) } - fn visit_variant(&mut self, - v: &'v ast::Variant, - g: &'v ast::Generics, - item_id: NodeId) { + fn visit_variant(&mut self, v: &'v ast::Variant) { self.record("Variant", Id::None, v); - ast_visit::walk_variant(self, v, g, item_id) + ast_visit::walk_variant(self, v) } fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime) { diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 5614b570b9..a5a8315a1e 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,8 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(bind_by_move_pattern_guards)] -#![feature(rustc_diagnostic_macros)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![recursion_limit="256"] @@ -18,7 +17,7 @@ extern crate rustc; use rustc::ty::query::Providers; -mod error_codes; +pub mod error_codes; pub mod ast_validation; pub mod rvalue_promotion; @@ -26,8 +25,6 @@ pub mod hir_stats; pub mod layout_test; pub mod loops; -__build_diagnostic_array! { librustc_passes, DIAGNOSTICS } - pub fn provide(providers: &mut Providers<'_>) { rvalue_promotion::provide(providers); loops::provide(providers); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index afe4c78dcf..dbfbec32a6 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -7,7 +7,7 @@ use rustc::ty::TyCtxt; use rustc::hir::def_id::DefId; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::{self, Node, Destination}; +use rustc::hir::{self, Node, Destination, GeneratorMovability}; use syntax::struct_span_err; use syntax_pos::Span; use errors::Applicability; @@ -16,7 +16,8 @@ use errors::Applicability; enum Context { Normal, Loop(hir::LoopSource), - Closure, + Closure(Span), + AsyncClosure(Span), LabeledBlock, AnonConst, } @@ -57,9 +58,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Loop(ref b, _, source) => { self.with_context(Loop(source), |v| v.visit_block(&b)); } - hir::ExprKind::Closure(_, ref function_decl, b, _, _) => { + hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => { + let cx = if let Some(GeneratorMovability::Static) = movability { + AsyncClosure(span) + } else { + Closure(span) + }; self.visit_fn_decl(&function_decl); - self.with_context(Closure, |v| v.visit_nested_body(b)); + self.with_context(cx, |v| v.visit_nested_body(b)); } hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(&b)); @@ -164,18 +170,22 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { } fn require_break_cx(&self, name: &str, span: Span) { - match self.cx { - LabeledBlock | Loop(_) => {} - Closure => { - struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) - .span_label(span, "cannot break inside of a closure") + let err_inside_of = |article, ty, closure_span| { + struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty) + .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty)) + .span_label(closure_span, &format!("enclosing {}", ty)) .emit(); - } + }; + + match self.cx { + LabeledBlock | Loop(_) => {}, + Closure(closure_span) => err_inside_of("a", "closure", closure_span), + AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span), Normal | AnonConst => { - struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) - .span_label(span, "cannot break outside of a loop") + struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name) + .span_label(span, format!("cannot `{}` outside of a loop", name)) .emit(); - } + }, } } diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml index 7486281c1e..84a743ed1a 100644 --- a/src/librustc_plugin/Cargo.toml +++ b/src/librustc_plugin/Cargo.toml @@ -1,12 +1,12 @@ [package] authors = ["The Rust Project Developers"] -name = "rustc_plugin" +name = "rustc_plugin_impl" version = "0.0.0" build = false edition = "2018" [lib] -name = "rustc_plugin" +name = "rustc_plugin_impl" path = "lib.rs" doctest = false diff --git a/src/librustc_plugin/deprecated/Cargo.toml b/src/librustc_plugin/deprecated/Cargo.toml new file mode 100644 index 0000000000..cc75f7b9ab --- /dev/null +++ b/src/librustc_plugin/deprecated/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_plugin" +version = "0.0.0" +build = false +edition = "2018" + +[lib] +name = "rustc_plugin" +path = "lib.rs" +doctest = false + +[dependencies] +rustc_plugin_impl = { path = ".." } diff --git a/src/librustc_plugin/deprecated/lib.rs b/src/librustc_plugin/deprecated/lib.rs new file mode 100644 index 0000000000..1d0afe84c2 --- /dev/null +++ b/src/librustc_plugin/deprecated/lib.rs @@ -0,0 +1,8 @@ +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(staged_api)] +#![unstable(feature = "rustc_private", issue = "27812")] +#![rustc_deprecated(since = "1.38.0", reason = "\ + import this through `rustc_driver::plugin` instead to make TLS work correctly. \ + See https://github.com/rust-lang/rust/issues/62717")] + +pub use rustc_plugin_impl::*; diff --git a/src/librustc_plugin/error_codes.rs b/src/librustc_plugin/error_codes.rs index b5f6a8d905..7b3f01c0ee 100644 --- a/src/librustc_plugin/error_codes.rs +++ b/src/librustc_plugin/error_codes.rs @@ -1,9 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { - -} - -register_diagnostics! { - E0498 // malformed plugin attribute +syntax::register_diagnostics! { +; + E0498, // malformed plugin attribute } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 25a7a8cdeb..4e1a47c503 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -16,12 +16,11 @@ //! #![feature(plugin_registrar)] //! #![feature(rustc_private)] //! -//! extern crate rustc_plugin; //! extern crate rustc_driver; //! extern crate syntax; //! extern crate syntax_pos; //! -//! use rustc_plugin::Registry; +//! use rustc_driver::plugin::Registry; //! use syntax::ext::base::{ExtCtxt, MacResult}; //! use syntax_pos::Span; //! use syntax::tokenstream::TokenTree; @@ -55,15 +54,12 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] pub use registry::Registry; -mod error_codes; +pub mod error_codes; pub mod registry; pub mod load; pub mod build; - -__build_diagnostic_array! { librustc_plugin, DIAGNOSTICS } diff --git a/src/librustc_privacy/error_codes.rs b/src/librustc_privacy/error_codes.rs index 70a799d426..67066466f1 100644 --- a/src/librustc_privacy/error_codes.rs +++ b/src/librustc_privacy/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0445: r##" A private trait was used on a public type parameter bound. Erroneous code @@ -154,8 +154,5 @@ let f = Bar::Foo::new(); // ok! ``` "##, -} - -register_diagnostics! { // E0450, moved into resolve } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 673762ee4c..1e61f78c35 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -2,7 +2,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] @@ -31,7 +30,7 @@ use syntax_pos::Span; use std::{cmp, fmt, mem}; use std::marker::PhantomData; -mod error_codes; +pub mod error_codes; //////////////////////////////////////////////////////////////////////////////// /// Generic infrastructure used to implement specific visitors below. @@ -508,11 +507,7 @@ impl EmbargoVisitor<'tcx> { } } - fn update_macro_reachable_mod( - &mut self, - reachable_mod: hir::HirId, - defining_mod: DefId, - ) { + fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) { let module_def_id = self.tcx.hir().local_def_id(reachable_mod); let module = self.tcx.hir().get_module(module_def_id).0; for item_id in &module.item_ids { @@ -524,19 +519,13 @@ impl EmbargoVisitor<'tcx> { self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); } } - if let Some(exports) = self.tcx.module_exports(module_def_id) { for export in exports { if export.vis.is_accessible_from(defining_mod, self.tcx) { if let Res::Def(def_kind, def_id) = export.res { let vis = def_id_visibility(self.tcx, def_id).0; if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { - self.update_macro_reachable_def( - hir_id, - def_kind, - vis, - defining_mod, - ); + self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); } } } @@ -687,11 +676,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { match item.node { hir::ItemKind::Enum(ref def, _) => { for variant in &def.variants { - let variant_level = self.update(variant.node.id, item_level); - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + let variant_level = self.update(variant.id, item_level); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { self.update(ctor_hir_id, item_level); } - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.update(field.hir_id, variant_level); } } @@ -810,9 +799,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.hir_id, item_level).generics().predicates(); } for variant in &def.variants { - let variant_level = self.get(variant.node.id); + let variant_level = self.get(variant.id); if variant_level.is_some() { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.reach(field.hir_id, variant_level).ty(); } // Corner case: if the variant is reachable, but its @@ -892,10 +881,14 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.tcx.hir().local_def_id(md.hir_id) ).unwrap(); let mut module_id = self.tcx.hir().as_local_hir_id(macro_module_def_id).unwrap(); + if !self.tcx.hir().is_hir_id_module(module_id) { + // `module_id` doesn't correspond to a `mod`, return early (#63164). + return; + } let level = if md.vis.node.is_pub() { self.get(module_id) } else { None }; let new_level = self.update(md.hir_id, level); if new_level.is_none() { - return + return; } loop { @@ -1075,8 +1068,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); for field in fields { - let use_ctxt = field.node.ident.span; - let index = self.tcx.field_index(field.node.hir_id, self.tables); + let use_ctxt = field.ident.span; + let index = self.tcx.field_index(field.hir_id, self.tables); self.check_field(use_ctxt, field.span, adt, &variant.fields[index]); } } @@ -1647,7 +1640,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - if self.access_levels.is_reachable(v.node.id) { + if self.access_levels.is_reachable(v.id) { self.in_variant = true; intravisit::walk_variant(self, v, g, item_id); self.in_variant = false; @@ -1898,7 +1891,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> self.check(item.hir_id, item_visibility).generics().predicates(); for variant in &def.variants { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.check(field.hir_id, item_visibility).ty(); } } @@ -2041,5 +2034,3 @@ fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) { }; krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } - -__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5dd7bc3054..11dcf5b4b0 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1,9 +1,11 @@ -//! Reduced graph building. +//! After we obtain a fresh AST fragment from a macro, code in this module helps to integrate +//! that fragment into the module structures that are already partially built. //! -//! Here we build the "reduced graph": the graph of the module tree without -//! any imports resolved. +//! Items from the fragment are placed into modules, +//! unexpanded macros in the fragment are visited and registered. +//! Imports are also considered items and placed into modules here, but not resolved yet. -use crate::macros::{InvocationData, LegacyBinding, LegacyScope}; +use crate::macros::{LegacyBinding, LegacyScope}; use crate::resolve_imports::ImportDirective; use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}; @@ -14,6 +16,7 @@ use crate::{ResolutionError, Determinacy, PathResult, CrateLint}; use rustc::bug; use rustc::hir::def::{self, *}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::map::DefCollector; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -28,8 +31,9 @@ use syntax::ast::{Name, Ident}; use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; -use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; +use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind}; use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::expand::AstFragment; use syntax::ext::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; @@ -67,7 +71,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) { } } -pub(crate) struct IsMacroExport; +struct IsMacroExport; impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { @@ -84,7 +88,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport impl<'a> Resolver<'a> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - pub fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) + crate fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) where T: ToNameBinding<'a>, { let binding = def.to_name_binding(self.arenas); @@ -93,7 +97,7 @@ impl<'a> Resolver<'a> { } } - pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { + crate fn get_module(&mut self, def_id: DefId) -> Module<'a> { if def_id.krate == LOCAL_CRATE { return self.module_map[&def_id] } @@ -119,10 +123,11 @@ impl<'a> Resolver<'a> { module } - pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { + crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { let def_id = match self.macro_defs.get(&expn_id) { Some(def_id) => *def_id, - None => return self.graph_root, + None => return self.ast_transform_scopes.get(&expn_id) + .unwrap_or(&self.graph_root), }; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] @@ -146,33 +151,55 @@ impl<'a> Resolver<'a> { return Some(ext.clone()); } - let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(macro_def) => macro_def, - LoadedMacro::ProcMacro(ext) => return Some(ext), - }; + let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) { + LoadedMacro::MacroDef(item) => + self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)), + LoadedMacro::ProcMacro(ext) => ext, + }); - let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate)); self.macro_map.insert(def_id, ext.clone()); Some(ext) } - /// Ensures that the reduced graph rooted at the given external module - /// is built, building it if it is not. - pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { - if module.populated.get() { return } - let def_id = module.def_id().unwrap(); + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. + crate fn build_reduced_graph( + &mut self, + fragment: &AstFragment, + extra_placeholders: &[NodeId], + parent_scope: ParentScope<'a>, + ) -> LegacyScope<'a> { + let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); + fragment.visit_with(&mut def_collector); + for placeholder in extra_placeholders { + def_collector.visit_macro_invoc(*placeholder); + } + + let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; + fragment.visit_with(&mut visitor); + for placeholder in extra_placeholders { + visitor.parent_scope.legacy = visitor.visit_invoc(*placeholder); + } + + visitor.parent_scope.legacy + } + + crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { + let def_id = module.def_id().expect("unpopulated module without a def-id"); for child in self.cstore.item_children_untracked(def_id, self.session) { let child = child.map_id(|_| panic!("unexpected id")); - BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self } - .build_reduced_graph_for_external_crate_res(module, child); + BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } + .build_reduced_graph_for_external_crate_res(child); } - module.populated.set(true) } } -pub struct BuildReducedGraphVisitor<'a, 'b> { - pub r: &'b mut Resolver<'a>, - pub parent_scope: ParentScope<'a>, +struct BuildReducedGraphVisitor<'a, 'b> { + r: &'b mut Resolver<'a>, + parent_scope: ParentScope<'a>, +} + +impl<'a> AsMut> for BuildReducedGraphVisitor<'a, '_> { + fn as_mut(&mut self) -> &mut Resolver<'a> { self.r } } impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { @@ -300,10 +327,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { root_id: NodeId, vis: ty::Visibility, ) { - let parent_scope = &self.parent_scope; - let current_module = parent_scope.module; + let current_module = self.parent_scope.module; let directive = self.r.arenas.alloc_import_directive(ImportDirective { - parent_scope: parent_scope.clone(), + parent_scope: self.parent_scope, module_path, imported_module: Cell::new(None), subclass, @@ -554,7 +580,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, item: &Item) { + fn build_reduced_graph_for_item(&mut self, item: &'b Item) { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; @@ -593,15 +619,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; - self.r.populate_module_if_necessary(module); - let used = self.process_legacy_macro_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); let directive = self.r.arenas.alloc_import_directive(ImportDirective { root_id: item.id, id: item.id, - parent_scope: self.parent_scope.clone(), + parent_scope: self.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::ExternCrate { source: orig_name, @@ -692,22 +716,17 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } - ItemKind::Enum(ref enum_definition, _) => { - let module_kind = ModuleKind::Def( - DefKind::Enum, - self.r.definitions.local_def_id(item.id), - ident.name, - ); + ItemKind::Enum(_, _) => { + let def_id = self.r.definitions.local_def_id(item.id); + self.r.variant_vis.insert(def_id, vis); + let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name); let module = self.r.new_module(parent, module_kind, parent.normal_ancestor_id, expansion, item.span); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); - - for variant in &(*enum_definition).variants { - self.build_reduced_graph_for_variant(variant, module, vis, expansion); - } + self.parent_scope.module = module; } ItemKind::TraitAlias(..) => { @@ -792,40 +811,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - // Constructs the reduced graph for one variant. Variants exist in the - // type and value namespaces. - fn build_reduced_graph_for_variant(&mut self, - variant: &Variant, - parent: Module<'a>, - vis: ty::Visibility, - expn_id: ExpnId) { - let ident = variant.node.ident; - - // Define a name in the type namespace. - let def_id = self.r.definitions.local_def_id(variant.node.id); - let res = Res::Def(DefKind::Variant, def_id); - self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id)); - - // If the variant is marked as non_exhaustive then lower the visibility to within the - // crate. - let mut ctor_vis = vis; - let has_non_exhaustive = attr::contains_name(&variant.node.attrs, sym::non_exhaustive); - if has_non_exhaustive && vis == ty::Visibility::Public { - ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); - } - - // Define a constructor name in the value namespace. - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id); - let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id); - let ctor_kind = CtorKind::from_ast(&variant.node.data); - let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); - } - /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { let (res, ns) = match item.node { @@ -861,20 +846,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res( - &mut self, - parent: Module<'a>, - child: Export, - ) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { + let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; // FIXME: We shouldn't create the gensym here, it should come from metadata, // but metadata cannot encode gensyms currently, so we create it here. // This is only a guess, two equivalent idents may incorrectly get different gensyms here. let ident = ident.gensym_if_underscore(); let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene + // Record primary definitions. match res { Res::Def(kind @ DefKind::Mod, def_id) - | Res::Def(kind @ DefKind::Enum, def_id) => { + | Res::Def(kind @ DefKind::Enum, def_id) + | Res::Def(kind @ DefKind::Trait, def_id) => { let module = self.r.new_module(parent, ModuleKind::Def(kind, def_id, ident.name), def_id, @@ -882,70 +866,55 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { span); self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Res::Def(DefKind::Variant, _) + Res::Def(DefKind::Struct, _) + | Res::Def(DefKind::Union, _) + | Res::Def(DefKind::Variant, _) | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::ForeignTy, _) | Res::Def(DefKind::OpaqueTy, _) | Res::Def(DefKind::TraitAlias, _) + | Res::Def(DefKind::AssocTy, _) + | Res::Def(DefKind::AssocOpaqueTy, _) | Res::PrimTy(..) - | Res::ToolMod => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - } + | Res::ToolMod => + self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)), Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::Method, _) | Res::Def(DefKind::Static, _) | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - } - Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - - if let Some(struct_def_id) = - self.r.cstore.def_key(def_id).parent - .map(|index| DefId { krate: def_id.krate, index: index }) { - self.r.struct_constructors.insert(struct_def_id, (res, vis)); - } - } - Res::Def(DefKind::Trait, def_id) => { - let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name); - let module = self.r.new_module(parent, - module_kind, - parent.normal_ancestor_id, - expansion, - span); - self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - - for child in self.r.cstore.item_children_untracked(def_id, self.r.session) { - let res = child.res.map_id(|_| panic!("unexpected id")); - let ns = if let Res::Def(DefKind::AssocTy, _) = res { - TypeNS - } else { ValueNS }; - self.r.define(module, child.ident, ns, - (res, ty::Visibility::Public, DUMMY_SP, expansion)); - - if self.r.cstore.associated_item_cloned_untracked(child.res.def_id()) - .method_has_self_argument { - self.r.has_self.insert(res.def_id()); - } - } - module.populated.set(true); - } + | Res::Def(DefKind::AssocConst, _) + | Res::Def(DefKind::Ctor(..), _) => + self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::Macro(..), _) + | Res::NonMacroAttr(..) => + self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _) + | Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err => + bug!("unexpected resolution: {:?}", res) + } + // Record some extra data for better diagnostics. + match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - - // Record field names for error reporting. let field_names = self.r.cstore.struct_field_names_untracked(def_id); self.insert_field_names(def_id, field_names); } - Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)); + Res::Def(DefKind::Method, def_id) => { + if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + self.r.has_self.insert(def_id); + } + } + Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { + let parent = self.r.cstore.def_key(def_id).parent; + if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { + self.r.struct_constructors.insert(struct_def_id, (res, vis)); + } } - _ => bug!("unexpected resolution: {:?}", res) + _ => {} } } fn legacy_import_macro(&mut self, - name: Name, + name: ast::Name, binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { @@ -997,7 +966,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { |this: &Self, span| this.r.arenas.alloc_import_directive(ImportDirective { root_id: item.id, id: item.id, - parent_scope: this.parent_scope.clone(), + parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::MacroUse, use_span_with_attributes: item.span_with_attributes(), @@ -1014,9 +983,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if let Some(span) = import_all { let directive = macro_use_directive(self, span); self.r.potentially_unused_imports.push(directive); - module.for_each_child(|ident, ns, binding| if ns == MacroNS { - let imported_binding = self.r.import(binding, directive); - self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); + module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS { + let imported_binding = this.r.import(binding, directive); + this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); }); } else { for ident in single_imports.iter().cloned() { @@ -1066,20 +1035,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> { + fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { let invoc_id = id.placeholder_to_expn_id(); - self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id); + self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); - let invocation_data = self.r.arenas.alloc_invocation_data(InvocationData { - module: self.parent_scope.module, - parent_legacy_scope: self.parent_scope.legacy, - output_legacy_scope: Cell::new(None), - }); - let old_invocation_data = self.r.invocations.insert(invoc_id, invocation_data); - assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation"); + let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); + assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); - invocation_data + LegacyScope::Invocation(invoc_id) } fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { @@ -1102,7 +1066,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let expansion = parent_scope.expansion; let (ext, ident, span, is_legacy) = match &item.node { ItemKind::MacroDef(def) => { - let ext = self.r.compile_macro(item, self.r.session.edition()); + let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition())); (ext, item.ident, item.span, def.legacy) } ItemKind::Fn(..) => match Self::proc_macro_stub(item) { @@ -1180,13 +1144,12 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { return } ItemKind::Mac(..) => { - self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(item.id)); + self.parent_scope.legacy = self.visit_invoc(item.id); return } ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), _ => false, }; - let orig_current_module = self.parent_scope.module; let orig_current_legacy_scope = self.parent_scope.legacy; self.build_reduced_graph_for_item(item); @@ -1199,7 +1162,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { if let ast::StmtKind::Mac(..) = stmt.node { - self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id)); + self.parent_scope.legacy = self.visit_invoc(stmt.id); } else { visit::walk_stmt(self, stmt); } @@ -1250,9 +1213,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let expansion = self.parent_scope.expansion; self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); - self.parent_scope.module = parent.parent.unwrap(); // nearest normal ancestor visit::walk_trait_item(self, item); - self.parent_scope.module = parent; } fn visit_token(&mut self, t: Token) { @@ -1267,10 +1228,96 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_attribute(&mut self, attr: &'b ast::Attribute) { if !attr.is_sugared_doc && is_builtin_attr(attr) { - self.parent_scope.module.builtin_attrs.borrow_mut().push(( - attr.path.segments[0].ident, self.parent_scope.clone() - )); + self.r.builtin_attrs.push((attr.path.segments[0].ident, self.parent_scope)); } visit::walk_attribute(self, attr); } + + fn visit_arm(&mut self, arm: &'b ast::Arm) { + if arm.is_placeholder { + self.visit_invoc(arm.id); + } else { + visit::walk_arm(self, arm); + } + } + + fn visit_field(&mut self, f: &'b ast::Field) { + if f.is_placeholder { + self.visit_invoc(f.id); + } else { + visit::walk_field(self, f); + } + } + + fn visit_field_pattern(&mut self, fp: &'b ast::FieldPat) { + if fp.is_placeholder { + self.visit_invoc(fp.id); + } else { + visit::walk_field_pattern(self, fp); + } + } + + fn visit_generic_param(&mut self, param: &'b ast::GenericParam) { + if param.is_placeholder { + self.visit_invoc(param.id); + } else { + visit::walk_generic_param(self, param); + } + } + + fn visit_param(&mut self, p: &'b ast::Param) { + if p.is_placeholder { + self.visit_invoc(p.id); + } else { + visit::walk_param(self, p); + } + } + + fn visit_struct_field(&mut self, sf: &'b ast::StructField) { + if sf.is_placeholder { + self.visit_invoc(sf.id); + } else { + visit::walk_struct_field(self, sf); + } + } + + // Constructs the reduced graph for one variant. Variants exist in the + // type and value namespaces. + fn visit_variant(&mut self, variant: &'b ast::Variant) { + if variant.is_placeholder { + self.visit_invoc(variant.id); + return; + } + + let parent = self.parent_scope.module; + let vis = self.r.variant_vis[&parent.def_id().expect("enum without def-id")]; + let expn_id = self.parent_scope.expansion; + let ident = variant.ident; + + // Define a name in the type namespace. + let def_id = self.r.definitions.local_def_id(variant.id); + let res = Res::Def(DefKind::Variant, def_id); + self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id)); + + // If the variant is marked as non_exhaustive then lower the visibility to within the + // crate. + let mut ctor_vis = vis; + let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive); + if has_non_exhaustive && vis == ty::Visibility::Public { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + } + + // Define a constructor name in the value namespace. + // Braced variants, unlike structs, generate unusable names in + // value namespace, they are reserved for possible future use. + // It's ok to use the variant's id as a ctor id since an + // error will be reported on any use of such resolution anyway. + let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id); + let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id); + let ctor_kind = CtorKind::from_ast(&variant.data); + let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); + self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); + + visit::walk_variant(self, variant); + } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 96d44b4b4c..0d85be83e1 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -26,6 +26,8 @@ use crate::Resolver; use crate::resolve_imports::ImportDirectiveSubclass; +use errors::pluralise; + use rustc::util::nodemap::NodeMap; use rustc::{lint, ty}; use rustc_data_structures::fx::FxHashSet; @@ -295,7 +297,7 @@ impl Resolver<'_> { }).collect::>(); span_snippets.sort(); let msg = format!("unused import{}{}", - if len > 1 { "s" } else { "" }, + pluralise!(len), if !span_snippets.is_empty() { format!(": {}", span_snippets.join(", ")) } else { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1de67edb95..c479912b4e 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -73,20 +73,23 @@ crate fn add_typo_suggestion( false } -crate fn add_module_candidates( - module: Module<'_>, names: &mut Vec, filter_fn: &impl Fn(Res) -> bool -) { - for (&(ident, _), resolution) in module.resolutions.borrow().iter() { - if let Some(binding) = resolution.borrow().binding { - let res = binding.res(); - if filter_fn(res) { - names.push(TypoSuggestion::from_res(ident.name, res)); +impl<'a> Resolver<'a> { + crate fn add_module_candidates( + &mut self, + module: Module<'a>, + names: &mut Vec, + filter_fn: &impl Fn(Res) -> bool, + ) { + for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() { + if let Some(binding) = resolution.borrow().binding { + let res = binding.res(); + if filter_fn(res) { + names.push(TypoSuggestion::from_res(ident.name, res)); + } } } } -} -impl<'a> Resolver<'a> { /// Combines an error with provided span and emits it. /// /// This takes the error provided, combines it with the span and any additional spans inside the @@ -166,12 +169,14 @@ impl<'a> Resolver<'a> { err } ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => { - let mut err = struct_span_err!(self.session, - span, - E0403, - "the name `{}` is already used for a generic \ - parameter in this list of generic parameters", - name); + let mut err = struct_span_err!( + self.session, + span, + E0403, + "the name `{}` is already used for a generic \ + parameter in this item's generic parameters", + name, + ); err.span_label(span, "already used"); err.span_label(first_use_span, format!("first use of `{}`", name)); err @@ -376,9 +381,9 @@ impl<'a> Resolver<'a> { Scope::DeriveHelpers => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { - for derive in &parent_scope.derives { + for derive in parent_scope.derives { let parent_scope = - &ParentScope { derives: Vec::new(), ..*parent_scope }; + &ParentScope { derives: &[], ..*parent_scope }; if let Ok((Some(ext), _)) = this.resolve_macro_path( derive, Some(MacroKind::Derive), parent_scope, false, false ) { @@ -402,10 +407,10 @@ impl<'a> Resolver<'a> { Scope::CrateRoot => { let root_ident = Ident::new(kw::PathRoot, ident.span); let root_module = this.resolve_crate_root(root_ident); - add_module_candidates(root_module, &mut suggestions, filter_fn); + this.add_module_candidates(root_module, &mut suggestions, filter_fn); } Scope::Module(module) => { - add_module_candidates(module, &mut suggestions, filter_fn); + this.add_module_candidates(module, &mut suggestions, filter_fn); } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| { @@ -453,9 +458,9 @@ impl<'a> Resolver<'a> { Scope::StdLibPrelude => { if let Some(prelude) = this.prelude { let mut tmp_suggestions = Vec::new(); - add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); + this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); suggestions.extend(tmp_suggestions.into_iter().filter(|s| { - use_prelude || this.is_builtin_macro(s.res.opt_def_id()) + use_prelude || this.is_builtin_macro(s.res) })); } } @@ -509,11 +514,9 @@ impl<'a> Resolver<'a> { while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { - self.populate_module_if_necessary(in_module); - // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). - in_module.for_each_child_stable(|ident, ns, name_binding| { + in_module.for_each_child_stable(self, |this, ident, ns, name_binding| { // avoid imports entirely if name_binding.is_import() && !name_binding.is_extern_crate() { return; } // avoid non-importable candidates as well @@ -547,7 +550,7 @@ impl<'a> Resolver<'a> { // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { let did = match res { - Res::Def(DefKind::Ctor(..), did) => self.parent(did), + Res::Def(DefKind::Ctor(..), did) => this.parent(did), _ => res.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); @@ -595,20 +598,26 @@ impl<'a> Resolver<'a> { where FilterFn: Fn(Res) -> bool { let mut suggestions = self.lookup_import_candidates_from_module( - lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn + lookup_ident, namespace, self.graph_root, Ident::with_dummy_span(kw::Crate), &filter_fn ); if lookup_ident.span.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); for (ident, _) in extern_prelude_names.into_iter() { + if ident.span.from_expansion() { + // Idents are adjusted to the root context before being + // resolved in the extern prelude, so reporting this to the + // user is no help. This skips the injected + // `extern crate std` in the 2018 edition, which would + // otherwise cause duplicate suggestions. + continue; + } if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name, ident.span) { let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX, }); - self.populate_module_if_necessary(&crate_root); - suggestions.extend(self.lookup_import_candidates_from_module( lookup_ident, namespace, crate_root, ident, &filter_fn)); } @@ -805,7 +814,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// at the root of the crate instead of the module where it is defined /// ``` pub(crate) fn check_for_module_export_macro( - &self, + &mut self, directive: &'b ImportDirective<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, @@ -826,7 +835,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return None; } - let resolutions = crate_module.resolutions.borrow(); + let resolutions = self.r.resolutions(crate_module).borrow(); let resolution = resolutions.get(&(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index e01f53786e..adbff67cc8 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1,9 +1,7 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - // Error messages for EXXXX errors. Each message should start and end with a // new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and // use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +syntax::register_diagnostics! { E0128: r##" Type parameter defaults can only use parameters that occur before them. @@ -526,15 +524,25 @@ Some type parameters have the same name. Erroneous code example: ```compile_fail,E0403 -fn foo(s: T, u: T) {} // error: the name `T` is already used for a type - // parameter in this type parameter list +fn f(s: T, u: T) {} // error: the name `T` is already used for a generic + // parameter in this item's generic parameters ``` Please verify that none of the type parameters are misspelled, and rename any clashing parameters. Example: ``` -fn foo(s: T, u: Y) {} // ok! +fn f(s: T, u: Y) {} // ok! +``` + +Type parameters in an associated item also cannot shadow parameters from the +containing item: + +```compile_fail,E0403 +trait Foo { + fn do_something(&self) -> T; + fn do_something_else(&self, bar: T); +} ``` "##, @@ -1652,10 +1660,7 @@ fn const_id() -> T { // error: const parameter } ``` "##, - -} - -register_diagnostics! { +; // E0153, unused error code // E0157, unused error code // E0257, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 358eaae11e..aae283b745 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1,8 +1,15 @@ +//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros. +//! It runs when the crate is fully expanded and its module structure is fully built. +//! So it just walks through the crate and resolves all the expressions, types, etc. +//! +//! If you wonder why there's no `early.rs`, that's because it's split into three files - +//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`. + use GenericParameters::*; use RibKind::*; use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; -use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult}; +use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use log::debug; @@ -11,7 +18,7 @@ use rustc::hir::def::{self, PartialRes, DefKind, CtorKind, PerNS}; use rustc::hir::def::Namespace::{self, *}; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::TraitCandidate; -use rustc::util::nodemap::FxHashMap; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; use syntax::{unwrap_or, walk_list}; use syntax::ast::*; @@ -28,8 +35,10 @@ mod diagnostics; type Res = def::Res; +type IdentMap = FxHashMap; + /// Map from the name in a pattern to its binding mode. -type BindingMap = FxHashMap; +type BindingMap = IdentMap; #[derive(Copy, Clone, Debug)] struct BindingInfo { @@ -66,6 +75,16 @@ impl PatternSource { } } +/// Denotes whether the context for the set of already bound bindings is a `Product` +/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`. +/// See those functions for more information. +enum PatBoundCtx { + /// A product pattern context, e.g., `Variant(a, b)`. + Product, + /// An or-pattern context, e.g., `p_0 | ... | p_n`. + Or, +} + /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -104,6 +123,24 @@ crate enum RibKind<'a> { TyParamAsConstParamTy, } +impl RibKind<'_> { + // Whether this rib kind contains generic parameters, as opposed to local + // variables. + crate fn contains_params(&self) -> bool { + match self { + NormalRibKind + | FnItemRibKind + | ConstantItemRibKind + | ModuleRibKind(_) + | MacroDefinition(_) => false, + AssocItemRibKind + | ItemRibKind + | ForwardTyParamBanRibKind + | TyParamAsConstParamTy => true, + } + } +} + /// A single local scope. /// /// A rib represents a scope names can live in. Note that these appear in many places, not just @@ -118,7 +155,7 @@ crate enum RibKind<'a> { /// resolving, the name is looked up from inside out. #[derive(Debug)] crate struct Rib<'a, R = Res> { - pub bindings: FxHashMap, + pub bindings: IdentMap, pub kind: RibKind<'a>, } @@ -261,18 +298,18 @@ impl<'a> PathSource<'a> { } fn error_code(self, has_unexpected_resolution: bool) -> &'static str { - __diagnostic_used!(E0404); - __diagnostic_used!(E0405); - __diagnostic_used!(E0412); - __diagnostic_used!(E0422); - __diagnostic_used!(E0423); - __diagnostic_used!(E0425); - __diagnostic_used!(E0531); - __diagnostic_used!(E0532); - __diagnostic_used!(E0573); - __diagnostic_used!(E0574); - __diagnostic_used!(E0575); - __diagnostic_used!(E0576); + syntax::diagnostic_used!(E0404); + syntax::diagnostic_used!(E0405); + syntax::diagnostic_used!(E0412); + syntax::diagnostic_used!(E0422); + syntax::diagnostic_used!(E0423); + syntax::diagnostic_used!(E0425); + syntax::diagnostic_used!(E0531); + syntax::diagnostic_used!(E0532); + syntax::diagnostic_used!(E0573); + syntax::diagnostic_used!(E0574); + syntax::diagnostic_used!(E0575); + syntax::diagnostic_used!(E0576); match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => "E0404", (PathSource::Trait(_), false) => "E0405", @@ -352,7 +389,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } TyKind::ImplicitSelf => { - let self_ty = Ident::with_empty_ctxt(kw::SelfUpper); + let self_ty = Ident::with_dummy_span(kw::SelfUpper); let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); @@ -381,50 +418,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { visit::walk_foreign_item(this, foreign_item); }); } - fn visit_fn(&mut self, - function_kind: FnKind<'tcx>, - declaration: &'tcx FnDecl, - _: Span, - _: NodeId) - { + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { debug!("(resolving function) entering function"); - let rib_kind = match function_kind { + let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. - self.ribs[ValueNS].push(Rib::new(rib_kind)); - - // Create a label rib for the function. - self.label_ribs.push(Rib::new(rib_kind)); - - // Add each argument to the rib. - let mut bindings_list = FxHashMap::default(); - for argument in &declaration.inputs { - self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); - - self.visit_ty(&argument.ty); - - debug!("(resolving function) recorded argument"); - } - visit::walk_fn_ret_ty(self, &declaration.output); - - // Resolve the function body, potentially inside the body of an async closure - match function_kind { - FnKind::ItemFn(.., body) | - FnKind::Method(.., body) => { - self.visit_block(body); - } - FnKind::Closure(body) => { - self.visit_expr(body); - } - }; - - debug!("(resolving function) leaving function"); - - self.label_ribs.pop(); - self.ribs[ValueNS].pop(); + self.with_rib(ValueNS, rib_kind, |this| { + // Create a label rib for the function. + this.with_label_rib(rib_kind, |this| { + // Add each argument to the rib. + this.resolve_params(&declaration.inputs); + + visit::walk_fn_ret_ty(this, &declaration.output); + + // Resolve the function body, potentially inside the body of an async closure + match fn_kind { + FnKind::ItemFn(.., body) | + FnKind::Method(.., body) => this.visit_block(body), + FnKind::Closure(body) => this.visit_expr(body), + }; + + debug!("(resolving function) leaving function"); + }) + }); } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -442,7 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { GenericParamKind::Type { ref default, .. } => { found_default |= default.is_some(); if found_default { - Some((Ident::with_empty_ctxt(param.ident.name), Res::Err)) + Some((Ident::with_dummy_span(param.ident.name), Res::Err)) } else { None } @@ -459,7 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { false } }) - .map(|param| (Ident::with_empty_ctxt(param.ident.name), Res::Err))); + .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); for param in &generics.params { match param.kind { @@ -476,7 +495,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name)); + default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } GenericParamKind::Const { ref ty } => { self.ribs[TypeNS].push(const_ty_param_ban_rib); @@ -501,15 +520,16 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. - let parent_scope = resolver.dummy_parent_scope(); let graph_root = resolver.graph_root; + let parent_scope = ParentScope::module(graph_root); + let start_rib_kind = ModuleRibKind(graph_root); LateResolutionVisitor { r: resolver, parent_scope, ribs: PerNS { - value_ns: vec![Rib::new(ModuleRibKind(graph_root))], - type_ns: vec![Rib::new(ModuleRibKind(graph_root))], - macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], + value_ns: vec![Rib::new(start_rib_kind)], + type_ns: vec![Rib::new(start_rib_kind)], + macro_ns: vec![Rib::new(start_rib_kind)], }, label_ribs: Vec::new(), current_trait_ref: None, @@ -563,24 +583,32 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // generate a fake "implementation scope" containing all the // implementations thus found, for compatibility with old resolve pass. - fn with_scope(&mut self, id: NodeId, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`). + fn with_rib( + &mut self, + ns: Namespace, + kind: RibKind<'a>, + work: impl FnOnce(&mut Self) -> T, + ) -> T { + self.ribs[ns].push(Rib::new(kind)); + let ret = work(self); + self.ribs[ns].pop(); + ret + } + + fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { let id = self.r.definitions.local_def_id(id); let module = self.r.module_map.get(&id).cloned(); // clones a reference if let Some(module) = module { // Move down in the graph. let orig_module = replace(&mut self.parent_scope.module, module); - self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); - self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); - - self.r.finalize_current_module_macro_resolutions(module); - let ret = f(self); - - self.parent_scope.module = orig_module; - self.ribs[ValueNS].pop(); - self.ribs[TypeNS].pop(); - ret + self.with_rib(ValueNS, ModuleRibKind(module), |this| { + this.with_rib(TypeNS, ModuleRibKind(module), |this| { + let ret = f(this); + this.parent_scope.module = orig_module; + ret + }) + }) } else { f(self) } @@ -784,7 +812,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) + where F: FnOnce(&mut Self) { debug!("with_generic_param_rib"); match generic_params { @@ -792,6 +820,19 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut function_type_rib = Rib::new(rib_kind); let mut function_value_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap::default(); + // We also can't shadow bindings from the parent item + if let AssocItemRibKind = rib_kind { + let mut add_bindings_for_ns = |ns| { + let parent_rib = self.ribs[ns].iter() + .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false }) + .expect("associated item outside of an item"); + seen_bindings.extend( + parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)), + ); + }; + add_bindings_for_ns(ValueNS); + add_bindings_for_ns(TypeNS); + } for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} @@ -857,38 +898,24 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } - fn with_label_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - self.label_ribs.push(Rib::new(NormalRibKind)); + fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { + self.label_ribs.push(Rib::new(kind)); f(self); self.label_ribs.pop(); } - fn with_item_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - self.ribs[ValueNS].push(Rib::new(ItemRibKind)); - self.ribs[TypeNS].push(Rib::new(ItemRibKind)); - f(self); - self.ribs[TypeNS].pop(); - self.ribs[ValueNS].pop(); + fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) { + self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f)) } - fn with_constant_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { + fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) { debug!("with_constant_rib"); - self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); - self.label_ribs.push(Rib::new(ConstantItemRibKind)); - f(self); - self.label_ribs.pop(); - self.ribs[ValueNS].pop(); + self.with_rib(ValueNS, ConstantItemRibKind, |this| { + this.with_label_rib(ConstantItemRibKind, f); + }); } - fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_current_self_type(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { // Handle nested impls (inside fn bodies) let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); let result = f(self); @@ -896,9 +923,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { result } - fn with_current_self_item(&mut self, self_item: &Item, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_current_self_item(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { let previous_value = replace(&mut self.current_self_item, Some(self_item.id)); let result = f(self); self.current_self_item = previous_value; @@ -906,9 +931,11 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412. - fn with_trait_items(&mut self, trait_items: &Vec, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_trait_items( + &mut self, + trait_items: &Vec, + f: impl FnOnce(&mut Self) -> T, + ) -> T { let trait_assoc_types = replace( &mut self.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.node { @@ -922,9 +949,11 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). - fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>, Option) -> T - { + fn with_optional_trait_ref( + &mut self, + opt_trait_ref: Option<&TraitRef>, + f: impl FnOnce(&mut Self, Option) -> T + ) -> T { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { @@ -959,27 +988,18 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { result } - fn with_self_rib(&mut self, self_res: Res, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { + fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { let mut self_type_rib = Rib::new(NormalRibKind); // Plain insert (no renaming, since types are not currently hygienic) - self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); - self.ribs[TypeNS].push(self_type_rib); + self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); + self.ribs[ns].push(self_type_rib); f(self); - self.ribs[TypeNS].pop(); + self.ribs[ns].pop(); } - fn with_self_struct_ctor_rib(&mut self, impl_id: DefId, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - let self_res = Res::SelfCtor(impl_id); - let mut self_type_rib = Rib::new(NormalRibKind); - self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); - self.ribs[ValueNS].push(self_type_rib); - f(self); - self.ribs[ValueNS].pop(); + fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) { + self.with_self_rib_ns(TypeNS, self_res, f) } fn resolve_implementation(&mut self, @@ -1007,8 +1027,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.visit_generics(generics); // Resolve the items within the impl. this.with_current_self_type(self_type, |this| { - this.with_self_struct_ctor_rib(item_def_id, |this| { - debug!("resolve_implementation with_self_struct_ctor_rib"); + this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { + debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); for impl_item in impl_items { // We also need a new scope for the impl item type parameters. let generic_params = HasGenericParams(&impl_item.generics, @@ -1098,6 +1118,15 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } + fn resolve_params(&mut self, params: &[Param]) { + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + for Param { pat, ty, .. } in params { + self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); + self.visit_ty(ty); + debug!("(resolving function / closure) recorded parameter"); + } + } + fn resolve_local(&mut self, local: &Local) { // Resolve the type. walk_list!(self, visit_ty, &local.ty); @@ -1106,72 +1135,93 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { walk_list!(self, visit_expr, &local.init); // Resolve the pattern. - self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap::default()); + self.resolve_pattern_top(&local.pat, PatternSource::Let); } - // build a map from pattern identifiers to binding-info's. - // this is done hygienically. This could arise for a macro - // that expands into an or-pattern where one 'x' was from the - // user and one 'x' came from the macro. + /// build a map from pattern identifiers to binding-info's. + /// this is done hygienically. This could arise for a macro + /// that expands into an or-pattern where one 'x' was from the + /// user and one 'x' came from the macro. fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { let mut binding_map = FxHashMap::default(); pat.walk(&mut |pat| { - if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { - if sub_pat.is_some() || match self.r.partial_res_map.get(&pat.id) - .map(|res| res.base_res()) { - Some(Res::Local(..)) => true, - _ => false, - } { - let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; - binding_map.insert(ident, binding_info); + match pat.node { + PatKind::Ident(binding_mode, ident, ref sub_pat) + if sub_pat.is_some() || self.is_base_res_local(pat.id) => + { + binding_map.insert(ident, BindingInfo { span: ident.span, binding_mode }); } + PatKind::Or(ref ps) => { + // Check the consistency of this or-pattern and + // then add all bindings to the larger map. + for bm in self.check_consistent_bindings(ps) { + binding_map.extend(bm); + } + return false; + } + _ => {} } + true }); binding_map } - // Checks that all of the arms in an or-pattern have exactly the - // same set of bindings, with the same binding modes for each. - fn check_consistent_bindings(&mut self, pats: &[P]) { + fn is_base_res_local(&self, nid: NodeId) -> bool { + match self.r.partial_res_map.get(&nid).map(|res| res.base_res()) { + Some(Res::Local(..)) => true, + _ => false, + } + } + + /// Checks that all of the arms in an or-pattern have exactly the + /// same set of bindings, with the same binding modes for each. + fn check_consistent_bindings(&mut self, pats: &[P]) -> Vec { let mut missing_vars = FxHashMap::default(); let mut inconsistent_vars = FxHashMap::default(); - for pat_outer in pats.iter() { - let map_outer = self.binding_mode_map(&pat_outer); - - for pat_inner in pats.iter().filter(|pat| pat.id != pat_outer.id) { - let map_inner = self.binding_mode_map(&pat_inner); - - for (&key_inner, &binding_inner) in map_inner.iter() { - match map_outer.get(&key_inner) { - None => { // missing binding - let binding_error = missing_vars - .entry(key_inner.name) - .or_insert(BindingError { - name: key_inner.name, - origin: BTreeSet::new(), - target: BTreeSet::new(), - could_be_path: - key_inner.name.as_str().starts_with(char::is_uppercase) - }); - binding_error.origin.insert(binding_inner.span); - binding_error.target.insert(pat_outer.span); - } - Some(binding_outer) => { // check consistent binding - if binding_outer.binding_mode != binding_inner.binding_mode { - inconsistent_vars - .entry(key_inner.name) - .or_insert((binding_inner.span, binding_outer.span)); - } + // 1) Compute the binding maps of all arms. + let maps = pats.iter() + .map(|pat| self.binding_mode_map(pat)) + .collect::>(); + + // 2) Record any missing bindings or binding mode inconsistencies. + for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) { + // Check against all arms except for the same pattern which is always self-consistent. + let inners = pats.iter().enumerate() + .filter(|(_, pat)| pat.id != pat_outer.id) + .flat_map(|(idx, _)| maps[idx].iter()) + .map(|(key, binding)| (key.name, map_outer.get(&key), binding)); + + for (name, info, &binding_inner) in inners { + match info { + None => { // The inner binding is missing in the outer. + let binding_error = missing_vars + .entry(name) + .or_insert_with(|| BindingError { + name, + origin: BTreeSet::new(), + target: BTreeSet::new(), + could_be_path: name.as_str().starts_with(char::is_uppercase), + }); + binding_error.origin.insert(binding_inner.span); + binding_error.target.insert(pat_outer.span); + } + Some(binding_outer) => { + if binding_outer.binding_mode != binding_inner.binding_mode { + // The binding modes in the outer and inner bindings differ. + inconsistent_vars + .entry(name) + .or_insert((binding_inner.span, binding_outer.span)); } } } } } + // 3) Report all missing variables we found. let mut missing_vars = missing_vars.iter_mut().collect::>(); missing_vars.sort(); for (name, mut v) in missing_vars { @@ -1183,213 +1233,245 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ResolutionError::VariableNotBoundInPattern(v)); } + // 4) Report all inconsistencies in binding modes we found. let mut inconsistent_vars = inconsistent_vars.iter().collect::>(); inconsistent_vars.sort(); for (name, v) in inconsistent_vars { self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1)); } - } - fn resolve_arm(&mut self, arm: &Arm) { - self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - - self.resolve_pats(&arm.pats, PatternSource::Match); - - if let Some(ref expr) = arm.guard { - self.visit_expr(expr) - } - self.visit_expr(&arm.body); - - self.ribs[ValueNS].pop(); + // 5) Finally bubble up all the binding maps. + maps } - /// Arising from `source`, resolve a sequence of patterns (top level or-patterns). - fn resolve_pats(&mut self, pats: &[P], source: PatternSource) { - let mut bindings_list = FxHashMap::default(); - for pat in pats { - self.resolve_pattern(pat, source, &mut bindings_list); - } - // This has to happen *after* we determine which pat_idents are variants - if pats.len() > 1 { - self.check_consistent_bindings(pats); - } + /// Check the consistency of the outermost or-patterns. + fn check_consistent_bindings_top(&mut self, pat: &Pat) { + pat.walk(&mut |pat| match pat.node { + PatKind::Or(ref ps) => { + self.check_consistent_bindings(ps); + false + }, + _ => true, + }) } - fn resolve_block(&mut self, block: &Block) { - debug!("(resolving block) entering block"); - // Move down in the graph, if there's an anonymous module rooted here. - let orig_module = self.parent_scope.module; - let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference - - let mut num_macro_definition_ribs = 0; - if let Some(anonymous_module) = anonymous_module { - debug!("(resolving block) found anonymous module, moving down"); - self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); - self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); - self.parent_scope.module = anonymous_module; - self.r.finalize_current_module_macro_resolutions(anonymous_module); - } else { - self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - } - - // Descend into the block. - for stmt in &block.stmts { - if let StmtKind::Item(ref item) = stmt.node { - if let ItemKind::MacroDef(..) = item.node { - num_macro_definition_ribs += 1; - let res = self.r.definitions.local_def_id(item.id); - self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); - self.label_ribs.push(Rib::new(MacroDefinition(res))); - } - } - - self.visit_stmt(stmt); - } - - // Move back up. - self.parent_scope.module = orig_module; - for _ in 0 .. num_macro_definition_ribs { - self.ribs[ValueNS].pop(); - self.label_ribs.pop(); - } - self.ribs[ValueNS].pop(); - if anonymous_module.is_some() { - self.ribs[TypeNS].pop(); - } - debug!("(resolving block) leaving block"); + fn resolve_arm(&mut self, arm: &Arm) { + self.with_rib(ValueNS, NormalRibKind, |this| { + this.resolve_pattern_top(&arm.pat, PatternSource::Match); + walk_list!(this, visit_expr, &arm.guard); + this.visit_expr(&arm.body); + }); } - fn fresh_binding(&mut self, - ident: Ident, - pat_id: NodeId, - outer_pat_id: NodeId, - pat_src: PatternSource, - bindings: &mut FxHashMap) - -> Res { - // Add the binding to the local ribs, if it - // doesn't already exist in the bindings map. (We - // must not add it if it's in the bindings map - // because that breaks the assumptions later - // passes make about or-patterns.) - let ident = ident.modern_and_legacy(); - let mut res = Res::Local(pat_id); - match bindings.get(&ident).cloned() { - Some(id) if id == outer_pat_id => { - // `Variant(a, a)`, error - self.r.report_error( - ident.span, - ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( - &ident.as_str()) - ); - } - Some(..) if pat_src == PatternSource::FnParam => { - // `fn f(a: u8, a: u8)`, error - self.r.report_error( - ident.span, - ResolutionError::IdentifierBoundMoreThanOnceInParameterList( - &ident.as_str()) - ); - } - Some(..) if pat_src == PatternSource::Match || - pat_src == PatternSource::Let => { - // `Variant1(a) | Variant2(a)`, ok - // Reuse definition from the first `a`. - res = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident]; - } - Some(..) => { - span_bug!(ident.span, "two bindings with the same name from \ - unexpected pattern source {:?}", pat_src); - } - None => { - // A completely fresh binding, add to the lists if it's valid. - if ident.name != kw::Invalid { - bindings.insert(ident, outer_pat_id); - self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, res); - } - } - } + /// Arising from `source`, resolve a top level pattern. + fn resolve_pattern_top(&mut self, pat: &Pat, pat_src: PatternSource) { + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + self.resolve_pattern(pat, pat_src, &mut bindings); + } - res + fn resolve_pattern( + &mut self, + pat: &Pat, + pat_src: PatternSource, + bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, + ) { + self.resolve_pattern_inner(pat, pat_src, bindings); + // This has to happen *after* we determine which pat_idents are variants: + self.check_consistent_bindings_top(pat); + visit::walk_pat(self, pat); } - fn resolve_pattern(&mut self, - pat: &Pat, - pat_src: PatternSource, - // Maps idents to the node ID for the - // outermost pattern that binds them. - bindings: &mut FxHashMap) { + /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. + /// + /// ### `bindings` + /// + /// A stack of sets of bindings accumulated. + /// + /// In each set, `PatBoundCtx::Product` denotes that a found binding in it should + /// be interpreted as re-binding an already bound binding. This results in an error. + /// Meanwhile, `PatBound::Or` denotes that a found binding in the set should result + /// in reusing this binding rather than creating a fresh one. + /// + /// When called at the top level, the stack must have a single element + /// with `PatBound::Product`. Otherwise, pushing to the stack happens as + /// or-patterns (`p_0 | ... | p_n`) are encountered and the context needs + /// to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`. + /// When each `p_i` has been dealt with, the top set is merged with its parent. + /// When a whole or-pattern has been dealt with, the thing happens. + /// + /// See the implementation and `fresh_binding` for more details. + fn resolve_pattern_inner( + &mut self, + pat: &Pat, + pat_src: PatternSource, + bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, + ) { // Visit all direct subpatterns of this pattern. - let outer_pat_id = pat.id; pat.walk(&mut |pat| { debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node); match pat.node { - PatKind::Ident(bmode, ident, ref opt_pat) => { - // First try to resolve the identifier as some existing - // entity, then fall back to a fresh binding. - let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, - None, pat.span) - .and_then(LexicalScopeBinding::item); - let res = binding.map(NameBinding::res).and_then(|res| { - let is_syntactic_ambiguity = opt_pat.is_none() && - bmode == BindingMode::ByValue(Mutability::Immutable); - match res { - Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | - Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => { - // Disambiguate in favor of a unit struct/variant - // or constant pattern. - self.r.record_use(ident, ValueNS, binding.unwrap(), false); - Some(res) - } - Res::Def(DefKind::Ctor(..), _) - | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::Static, _) => { - // This is unambiguously a fresh binding, either syntactically - // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves - // to something unusable as a pattern (e.g., constructor function), - // but we still conservatively report an error, see - // issues/33118#issuecomment-233962221 for one reason why. - self.r.report_error( - ident.span, - ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), ident.name, binding.unwrap()) - ); - None - } - Res::Def(DefKind::Fn, _) | Res::Err => { - // These entities are explicitly allowed - // to be shadowed by fresh bindings. - None - } - res => { - span_bug!(ident.span, "unexpected resolution for an \ - identifier in pattern: {:?}", res); - } - } - }).unwrap_or_else(|| { - self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings) - }); - + PatKind::Ident(bmode, ident, ref sub) => { + // First try to resolve the identifier as some existing entity, + // then fall back to a fresh binding. + let has_sub = sub.is_some(); + let res = self.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) + .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); self.r.record_partial_res(pat.id, PartialRes::new(res)); } - PatKind::TupleStruct(ref path, ..) => { self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct); } - PatKind::Path(ref qself, ref path) => { self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat); } - PatKind::Struct(ref path, ..) => { self.smart_resolve_path(pat.id, None, path, PathSource::Struct); } - + PatKind::Or(ref ps) => { + // Add a new set of bindings to the stack. `Or` here records that when a + // binding already exists in this set, it should not result in an error because + // `V1(a) | V2(a)` must be allowed and are checked for consistency later. + bindings.push((PatBoundCtx::Or, Default::default())); + for p in ps { + // Now we need to switch back to a product context so that each + // part of the or-pattern internally rejects already bound names. + // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad. + bindings.push((PatBoundCtx::Product, Default::default())); + self.resolve_pattern_inner(p, pat_src, bindings); + // Move up the non-overlapping bindings to the or-pattern. + // Existing bindings just get "merged". + let collected = bindings.pop().unwrap().1; + bindings.last_mut().unwrap().1.extend(collected); + } + // This or-pattern itself can itself be part of a product, + // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`. + // Both cases bind `a` again in a product pattern and must be rejected. + let collected = bindings.pop().unwrap().1; + bindings.last_mut().unwrap().1.extend(collected); + + // Prevent visiting `ps` as we've already done so above. + return false; + } _ => {} } true }); + } - visit::walk_pat(self, pat); + fn fresh_binding( + &mut self, + ident: Ident, + pat_id: NodeId, + pat_src: PatternSource, + bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, + ) -> Res { + // Add the binding to the local ribs, if it doesn't already exist in the bindings map. + // (We must not add it if it's in the bindings map because that breaks the assumptions + // later passes make about or-patterns.) + let ident = ident.modern_and_legacy(); + + // Walk outwards the stack of products / or-patterns and + // find out if the identifier has been bound in any of these. + let mut already_bound_and = false; + let mut already_bound_or = false; + for (is_sum, set) in bindings.iter_mut().rev() { + match (is_sum, set.get(&ident).cloned()) { + // Already bound in a product pattern, e.g. `(a, a)` which is not allowed. + (PatBoundCtx::Product, Some(..)) => already_bound_and = true, + // Already bound in an or-pattern, e.g. `V1(a) | V2(a)`. + // This is *required* for consistency which is checked later. + (PatBoundCtx::Or, Some(..)) => already_bound_or = true, + // Not already bound here. + _ => {} + } + } + + if already_bound_and { + // Overlap in a product pattern somewhere; report an error. + use ResolutionError::*; + let error = match pat_src { + // `fn f(a: u8, a: u8)`: + PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList, + // `Variant(a, a)`: + _ => IdentifierBoundMoreThanOnceInSamePattern, + }; + self.r.report_error(ident.span, error(&ident.as_str())); + } + + // Record as bound if it's valid: + let ident_valid = ident.name != kw::Invalid; + if ident_valid { + bindings.last_mut().unwrap().1.insert(ident); + } + + if already_bound_or { + // `Variant1(a) | Variant2(a)`, ok + // Reuse definition from the first `a`. + self.innermost_rib_bindings(ValueNS)[&ident] + } else { + let res = Res::Local(pat_id); + if ident_valid { + // A completely fresh binding add to the set if it's valid. + self.innermost_rib_bindings(ValueNS).insert(ident, res); + } + res + } + } + + fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap { + &mut self.ribs[ns].last_mut().unwrap().bindings + } + + fn try_resolve_as_non_binding( + &mut self, + pat_src: PatternSource, + pat: &Pat, + bm: BindingMode, + ident: Ident, + has_sub: bool, + ) -> Option { + let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?; + let res = binding.res(); + + // An immutable (no `mut`) by-value (no `ref`) binding pattern without + // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could + // also be interpreted as a path to e.g. a constant, variant, etc. + let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable); + + match res { + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | + Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => { + // Disambiguate in favor of a unit struct/variant or constant pattern. + self.r.record_use(ident, ValueNS, binding, false); + Some(res) + } + Res::Def(DefKind::Ctor(..), _) + | Res::Def(DefKind::Const, _) + | Res::Def(DefKind::Static, _) => { + // This is unambiguously a fresh binding, either syntactically + // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves + // to something unusable as a pattern (e.g., constructor function), + // but we still conservatively report an error, see + // issues/33118#issuecomment-233962221 for one reason why. + self.r.report_error( + ident.span, + ResolutionError::BindingShadowsSomethingUnacceptable( + pat_src.descr(), + ident.name, + binding, + ), + ); + None + } + Res::Def(DefKind::Fn, _) | Res::Err => { + // These entities are explicitly allowed to be shadowed by fresh bindings. + None + } + res => { + span_bug!(ident.span, "unexpected resolution for an \ + identifier in pattern: {:?}", res); + } + } } // High-level and context dependent path resolution routine. @@ -1476,7 +1558,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.r.trait_map.insert(id, traits); } - let mut std_path = vec![Segment::from_ident(Ident::with_empty_ctxt(sym::std))]; + let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))]; std_path.extend(path); if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) { let cl = CrateLint::No; @@ -1507,7 +1589,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn self_type_is_available(&mut self, span: Span) -> bool { let binding = self.resolve_ident_in_lexical_scope( - Ident::with_empty_ctxt(kw::SelfUpper), + Ident::with_dummy_span(kw::SelfUpper), TypeNS, None, span, @@ -1687,12 +1769,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { Some(result) } - fn with_resolved_label(&mut self, label: Option

` (where P is one \ + of the previous types except `Self`)"; + fn check_method_receiver<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, method_sig: &hir::MethodSig, method: &ty::AssocItem, self_ty: Ty<'tcx>, ) { - const HELP_FOR_SELF_TYPE: &str = - "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ - `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ - of the previous types except `Self`)"; // Check that the method has a valid receiver type, given the type `Self`. - debug!("check_method_receiver({:?}, self_ty={:?})", - method, self_ty); + debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty); if !method.method_has_self_argument { return; @@ -806,12 +805,7 @@ fn check_method_receiver<'fcx, 'tcx>( if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type of `self` must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } else { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) { @@ -831,17 +825,22 @@ fn check_method_receiver<'fcx, 'tcx>( .emit(); } else { // Report error; would not have worked with `arbitrary_self_types`. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } } } +fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { + fcx.tcx.sess.diagnostic().mut_span_err( + span, + &format!("invalid `self` parameter type: {:?}", receiver_ty) + ).note("type of `self` must be `Self` or a type that dereferences to it") + .help(HELP_FOR_SELF_TYPE) + .code(DiagnosticId::Error("E0307".into())) + .emit(); +} + /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more @@ -998,34 +997,6 @@ fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) { err.emit(); } -fn reject_shadowing_parameters(tcx: TyCtxt<'_>, def_id: DefId) { - let generics = tcx.generics_of(def_id); - let parent = tcx.generics_of(generics.parent.unwrap()); - let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind { - GenericParamDefKind::Lifetime => None, - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - Some((param.name, param.def_id)) - } - }).collect(); - - for method_param in &generics.params { - // Shadowing is checked in `resolve_lifetime`. - if let GenericParamDefKind::Lifetime = method_param.kind { - continue - } - if impl_params.contains_key(&method_param.name) { - // Tighten up the span to focus on only the shadowing type. - let type_span = tcx.def_span(method_param.def_id); - - // The expectation here is that the original trait declaration is - // local so it should be okay to just unwrap everything. - let trait_def_id = impl_params[&method_param.name]; - let trait_decl_span = tcx.def_span(trait_def_id); - error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]); - } - } -} - /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { @@ -1119,7 +1090,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec> { enum_def.variants.iter() - .map(|variant| self.non_enum_variant(&variant.node.data)) + .map(|variant| self.non_enum_variant(&variant.data)) .collect() } @@ -1152,12 +1123,3 @@ fn error_392( err.span_label(span, "unused parameter"); err } - -fn error_194(tcx: TyCtxt<'_>, span: Span, trait_decl_span: Span, name: &str) { - struct_span_err!(tcx.sess, span, E0194, - "type parameter `{}` shadows another type parameter of the same name", - name) - .span_label(span, "shadows another type parameter") - .span_label(trait_decl_span, format!("first `{}` declared here", name)) - .emit(); -} diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 67a8ecaf1d..27ff2e6f5d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -3,7 +3,6 @@ // substitutions. use crate::check::FnCtxt; -use errors::DiagnosticBuilder; use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -39,8 +38,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs); let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs); - for arg in &body.arguments { - wbcx.visit_node_id(arg.pat.span, arg.hir_id); + for param in &body.params { + wbcx.visit_node_id(param.pat.span, param.hir_id); } // Type only exists for constants and statics, not functions. match self.tcx.hir().body_owner_kind(item_id) { @@ -59,6 +58,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_free_region_map(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); + wbcx.visit_generator_interior_types(); let used_trait_imports = mem::replace( &mut self.tables.borrow_mut().used_trait_imports, @@ -245,8 +245,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { match e.node { hir::ExprKind::Closure(_, _, body, _, _) => { let body = self.fcx.tcx.hir().body(body); - for arg in &body.arguments { - self.visit_node_id(e.span, arg.hir_id); + for param in &body.params { + self.visit_node_id(e.span, param.hir_id); } self.visit_body(body); @@ -283,7 +283,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } hir::PatKind::Struct(_, ref fields, _) => { for field in fields { - self.visit_field_id(field.node.hir_id); + self.visit_field_id(field.hir_id); } } _ => {} @@ -407,7 +407,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if !errors_buffer.is_empty() { errors_buffer.sort_by_key(|diag| diag.span.primary_span()); for diag in errors_buffer.drain(..) { - DiagnosticBuilder::new_diagnostic(self.tcx().sess.diagnostic(), diag).emit(); + self.tcx().sess.diagnostic().emit_diagnostic(&diag); } } } @@ -431,6 +431,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + fn visit_generator_interior_types(&mut self) { + let fcx_tables = self.fcx.tables.borrow(); + debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); + self.tables.generator_interior_types = fcx_tables.generator_interior_types.clone(); + } + fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index fb79a85ea2..e7c2126cfd 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -67,6 +67,14 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } + ty::Bool => { + self.check_primitive_impl(def_id, + lang_items.bool_impl(), + None, + "bool", + "bool", + item.span); + } ty::Char => { self.check_primitive_impl(def_id, lang_items.char_impl(), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0f0568907c..d2e9203779 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,7 +35,6 @@ use rustc_target::spec::abi; use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; -use syntax::source_map::Spanned; use syntax::feature_gate; use syntax::symbol::{InternedString, kw, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; @@ -520,17 +519,21 @@ fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) { tcx.predicates_of(def_id); } -fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: &[hir::Variant]) { +fn convert_enum_variant_types( + tcx: TyCtxt<'_>, + def_id: DefId, + variants: &[hir::Variant] +) { let def = tcx.adt_def(def_id); let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); - let mut prev_discr = None::>; + let mut prev_discr = None::>; // fill the discriminant values and field types for variant in variants { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); prev_discr = Some( - if let Some(ref e) = variant.node.disr_expr { + if let Some(ref e) = variant.disr_expr { let expr_did = tcx.hir().local_def_id(e.hir_id); def.eval_explicit_discr(tcx, expr_did) } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { @@ -546,14 +549,14 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: format!("overflowed on value after {}", prev_discr.unwrap()), ).note(&format!( "explicitly set `{} = {}` if that is desired outcome", - variant.node.ident, wrapped_discr + variant.ident, wrapped_discr )) .emit(); None }.unwrap_or(wrapped_discr), ); - for f in variant.node.data.fields() { + for f in variant.data.fields() { let def_id = tcx.hir().local_def_id(f.hir_id); tcx.generics_of(def_id); tcx.type_of(def_id); @@ -562,7 +565,7 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: // Convert the ctor, if any. This also registers the variant as // an item. - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { convert_variant_ctor(tcx, ctor_hir_id); } } @@ -641,11 +644,11 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { let variants = def.variants .iter() .map(|v| { - let variant_did = Some(tcx.hir().local_def_id(v.node.id)); - let ctor_did = v.node.data.ctor_hir_id() + let variant_did = Some(tcx.hir().local_def_id(v.id)); + let ctor_did = v.data.ctor_hir_id() .map(|hir_id| tcx.hir().local_def_id(hir_id)); - let discr = if let Some(ref e) = v.node.disr_expr { + let discr = if let Some(ref e) = v.disr_expr { distance_from_explicit = 0; ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.hir_id)) } else { @@ -653,8 +656,8 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { }; distance_from_explicit += 1; - convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr, - &v.node.data, AdtKind::Enum, def_id) + convert_variant(tcx, variant_did, ctor_did, v.ident, discr, + &v.data, AdtKind::Enum, def_id) }) .collect(); @@ -713,7 +716,7 @@ fn super_predicates_of( let icx = ItemCtxt::new(tcx, trait_def_id); // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. - let self_param_ty = tcx.mk_self_type(); + let self_param_ty = tcx.types.self_param; let superbounds1 = AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); @@ -897,6 +900,20 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id)) } + // FIXME(#43408) enable this in all cases when we get lazy normalization. + Node::AnonConst(&anon_const) => { + // HACK(eddyb) this provides the correct generics when the workaround + // for a const parameter `AnonConst` is being used elsewhere, as then + // there won't be the kind of cyclic dependency blocking #43408. + let expr = &tcx.hir().body(anon_const.body).value; + let icx = ItemCtxt::new(tcx, def_id); + if AstConv::const_param_def_id(&icx, expr).is_some() { + let parent_id = tcx.hir().get_parent_item(hir_id); + Some(tcx.hir().local_def_id(parent_id)) + } else { + None + } + } Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(..), .. @@ -1011,13 +1028,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { synthetic, .. } => { - if param.name.ident().name == kw::SelfUpper { - span_bug!( - param.span, - "`Self` should not be the name of a regular parameter" - ); - } - if !allow_defaults && default.is_some() { if !tcx.features().default_type_parameter_fallback { tcx.lint_hir( @@ -1041,13 +1051,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { } } GenericParamKind::Const { .. } => { - if param.name.ident().name == kw::SelfUpper { - span_bug!( - param.span, - "`Self` should not be the name of a regular parameter", - ); - } - ty::GenericParamDefKind::Const } _ => return None, @@ -1314,10 +1317,9 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option tcx.mk_foreign(def_id), }, - Node::Ctor(&ref def) | Node::Variant(&Spanned { - node: hir::VariantKind { data: ref def, .. }, - .. - }) => match *def { + Node::Ctor(&ref def) | Node::Variant( + hir::Variant { data: ref def, .. } + ) => match *def { VariantData::Unit(..) | VariantData::Struct(..) => { tcx.type_of(tcx.hir().get_parent_did(hir_id)) } @@ -1363,12 +1365,8 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { @@ -1569,7 +1567,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { &format!( "defining opaque type use restricts opaque \ type by using the generic parameter `{}` twice", - p.name + p, ), ); return; @@ -1809,10 +1807,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } - Ctor(data) | Variant(Spanned { - node: hir::VariantKind { data, .. }, - .. - }) if data.ctor_hir_id().is_some() => { + Ctor(data) | Variant( + hir::Variant { data, .. } + ) if data.ctor_hir_id().is_some() => { let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id)); let inputs = data.fields() .iter() diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 79a04b9423..dd44f86717 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -20,10 +20,10 @@ impl From for Parameter { } /// Returns the set of parameters constrained by the impl header. -pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, - impl_trait_ref: Option>) - -> FxHashSet -{ +pub fn parameters_for_impl<'tcx>( + impl_self_ty: Ty<'tcx>, + impl_trait_ref: Option>, +) -> FxHashSet { let vec = match impl_trait_ref { Some(tr) => parameters_for(&tr, false), None => parameters_for(&impl_self_ty, false), @@ -36,12 +36,10 @@ pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, /// uniquely determined by `t` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. -pub fn parameters_for<'tcx, T>(t: &T, - include_nonconstraining: bool) - -> Vec - where T: TypeFoldable<'tcx> -{ - +pub fn parameters_for<'tcx>( + t: &impl TypeFoldable<'tcx>, + include_nonconstraining: bool, +) -> Vec { let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining, diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 90118a9f19..e11dcfafb8 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1,6 +1,6 @@ // ignore-tidy-filelength -register_long_diagnostics! { +syntax::register_diagnostics! { E0023: r##" A pattern used to match against an enum variant must provide a sub-pattern for @@ -212,7 +212,7 @@ match string { E0033: r##" This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the -size of trait implementors isn't fixed, this type has no compile-time size. +size of trait implementers isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. @@ -1718,22 +1718,6 @@ Since we know for certain that `Wrapper` implements `Clone`, there's no reason to also specify it in a `where` clause. "##, -E0194: r##" -A type parameter was declared which shadows an existing one. An example of this -error: - -```compile_fail,E0194 -trait Foo { - fn do_something(&self) -> T; - fn do_something_else(&self, bar: T); -} -``` - -In this example, the trait `Foo` and the trait method `do_something_else` both -define a type parameter `T`. This is not allowed: if the method wishes to -define a type parameter, it must use a different name for it. -"##, - E0195: r##" Your method's lifetime parameters do not match the trait declaration. Erroneous code example: @@ -2441,6 +2425,87 @@ struct Bar { x: Foo } ``` "##, +E0307: r##" +This error indicates that the `self` parameter in a method has an invalid +"reciever type". + +Methods take a special first parameter, of which there are three variants: +`self`, `&self`, and `&mut self`. These are syntactic sugar for +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. + +``` +# struct Foo; +trait Trait { + fn foo(&self); +// ^^^^^ `self` here is a reference to the receiver object +} + +impl Trait for Foo { + fn foo(&self) {} +// ^^^^^ the receiver type is `&Foo` +} +``` + +The type `Self` acts as an alias to the type of the current trait +implementer, or "receiver type". Besides the already mentioned `Self`, +`&Self` and `&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). Note that `Self` can +also be the underlying implementing type, like `Foo` in the following +example: + +``` +# struct Foo; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(self: &Foo) {} +} +``` + +E0307 will be emitted by the compiler when using an invalid reciver type, +like in the following example: + +```compile_fail,E0307 +# struct Foo; +# struct Bar; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(self: &Bar) {} +} +``` + +The nightly feature [Arbintrary self types][AST] extends the accepted +set of receiver types to also include any type that can dereference to +`Self`: + +``` +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +// Because you can dereference `Bar` into `Foo`... +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn foo(self: Bar) {} +// ^^^^^^^^^ ...it can be used as the receiver type +} +``` + +[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html +"##, + E0321: r##" A cross-crate opt-out trait was implemented on something which wasn't a struct or enum type. Erroneous code example: @@ -4767,7 +4832,6 @@ E0733: r##" Recursion in an `async fn` requires boxing. For example, this will not compile: ```edition2018,compile_fail,E0733 -#![feature(async_await)] async fn foo(n: usize) { if n > 0 { foo(n - 1).await; @@ -4779,12 +4843,11 @@ To achieve async recursion, the `async fn` needs to be desugared such that the `Future` is explicit in the return type: ```edition2018,compile_fail,E0720 -# #![feature(async_await)] use std::future::Future; -fn foo_desugered(n: usize) -> impl Future { +fn foo_desugared(n: usize) -> impl Future { async move { if n > 0 { - foo_desugered(n - 1).await; + foo_desugared(n - 1).await; } } } @@ -4793,7 +4856,6 @@ fn foo_desugered(n: usize) -> impl Future { Finally, the future is wrapped in a pinned box: ```edition2018 -# #![feature(async_await)] use std::future::Future; use std::pin::Pin; fn foo_recursive(n: usize) -> Pin>> { @@ -4808,10 +4870,7 @@ fn foo_recursive(n: usize) -> Pin>> { The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, - -} // (end of detailed error messages) - -register_diagnostics! { +; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 // E0068, @@ -4837,6 +4896,7 @@ register_diagnostics! { // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object +// E0194, // merged into E0403 // E0196, // cannot determine a type for this closure E0203, // type parameter has more than one relaxed default bound, // and only one is supported @@ -4867,16 +4927,16 @@ register_diagnostics! { // E0245, // not a trait // E0246, // invalid recursive type // E0247, -// E0248, // value used as a type, now reported earlier during resolution as E0412 +// E0248, // value used as a type, now reported earlier during resolution + // as E0412 // E0249, - E0307, // invalid method `self` type // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe E0377, // the trait `CoerceUnsized` may only be implemented for a coercion // between structures with the same definition // E0558, // replaced with a generic attribute input check E0533, // `{}` does not name a unit variant, unit struct or a constant -// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15 +// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` E0587, // type has conflicting packed and align representation hints @@ -4885,8 +4945,8 @@ register_diagnostics! { // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0627, // yield statement outside of generator literal - E0632, // cannot provide explicit type parameters when `impl Trait` is used in - // argument position. + E0632, // cannot provide explicit type parameters when `impl Trait` is used + // in argument position. E0634, // type has conflicting packed representaton hints E0640, // infer outlives requirements E0641, // cannot cast to/from a pointer with an unknown kind diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index fcfd9adef5..bc0f17c3bf 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -12,7 +12,7 @@ use crate::constrained_generic_params as cgp; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::ty::query::Providers; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -99,6 +99,15 @@ fn enforce_impl_params_are_constrained( ) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); + if impl_self_ty.references_error() { + // Don't complain about unconstrained type params when self ty isn't known due to errors. + // (#36836) + tcx.sess.delay_span_bug( + tcx.def_span(impl_def_id), + "potentially unconstrained type parameters weren't evaluated", + ); + return; + } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9d9a9d9b55..959483e443 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -65,7 +65,6 @@ This API is completely unstable and subject to change. #![feature(exhaustive_patterns)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(never_type)] #![feature(inner_deref)] @@ -78,9 +77,7 @@ This API is completely unstable and subject to change. #[macro_use] extern crate rustc; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. -mod error_codes; +pub mod error_codes; mod astconv; mod check; @@ -389,5 +386,3 @@ pub fn hir_trait_to_predicates<'tcx>( bounds } - -__build_diagnostic_array! { librustc_typeck, DIAGNOSTICS } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 6b288347ad..644d723ded 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -3,7 +3,6 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{Kind, Subst, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::fold::TypeFoldable; use rustc::util::nodemap::FxHashMap; use super::explicit::ExplicitPredicatesMap; @@ -178,11 +177,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( // let _: () = substs.region_at(0); check_explicit_predicates( tcx, - &def.did, + def.did, substs, required_predicates, explicit_map, - IgnoreSelfTy(false), + None, ); } @@ -208,11 +207,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( .substs; check_explicit_predicates( tcx, - &ex_trait_ref.skip_binder().def_id, + ex_trait_ref.skip_binder().def_id, substs, required_predicates, explicit_map, - IgnoreSelfTy(true), + Some(tcx.types.self_param), ); } } @@ -223,11 +222,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( debug!("Projection"); check_explicit_predicates( tcx, - &tcx.associated_item(obj.item_def_id).container.id(), + tcx.associated_item(obj.item_def_id).container.id(), obj.substs, required_predicates, explicit_map, - IgnoreSelfTy(false), + None, ); } @@ -236,9 +235,6 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } -#[derive(Debug)] -pub struct IgnoreSelfTy(bool); - /// We also have to check the explicit predicates /// declared on the type. /// @@ -256,25 +252,25 @@ pub struct IgnoreSelfTy(bool); /// applying the substitution as above. pub fn check_explicit_predicates<'tcx>( tcx: TyCtxt<'tcx>, - def_id: &DefId, + def_id: DefId, substs: &[Kind<'tcx>], required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, - ignore_self_ty: IgnoreSelfTy, + ignored_self_ty: Option>, ) { debug!( "check_explicit_predicates(def_id={:?}, \ substs={:?}, \ explicit_map={:?}, \ required_predicates={:?}, \ - ignore_self_ty={:?})", + ignored_self_ty={:?})", def_id, substs, explicit_map, required_predicates, - ignore_self_ty, + ignored_self_ty, ); - let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id); + let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); for outlives_predicate in explicit_predicates.iter() { debug!("outlives_predicate = {:?}", &outlives_predicate); @@ -313,9 +309,9 @@ pub fn check_explicit_predicates<'tcx>( // = X` binding from the object type (there must be such a // binding) and thus infer an outlives requirement that `X: // 'b`. - if ignore_self_ty.0 { + if let Some(self_ty) = ignored_self_ty { if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.has_self_ty() { + if ty.walk().any(|ty| ty == self_ty) { debug!("skipping self ty = {:?}", &ty); continue; } diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index 3e3eab8cf4..273a36edc5 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -48,7 +48,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> { fn session(&self) -> &Session { self.sess } fn code(&self) -> DiagnosticId { - __diagnostic_used!(E0617); + syntax::diagnostic_used!(E0617); DiagnosticId::Error("E0617".to_owned()) } @@ -104,7 +104,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> { fn session(&self) -> &Session { self.sess } fn code(&self) -> DiagnosticId { - __diagnostic_used!(E0607); + syntax::diagnostic_used!(E0607); DiagnosticId::Error("E0607".to_owned()) } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index b75a091265..7ed9d6606f 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -82,8 +82,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { self.visit_node_helper(item.hir_id); for variant in &enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.node.data { - self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap()); + if let hir::VariantData::Tuple(..) = variant.data { + self.visit_node_helper(variant.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 7af7c79bb3..e10837e52a 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -145,8 +145,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.add_inferreds_for_item(item.hir_id); for variant in &enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.node.data { - self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap()); + if let hir::VariantData::Tuple(..) = variant.data { + self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 5a4dc7be32..516be99ed6 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // it is *not* required (i.e., '?Sized') let sized_trait = self.cx .tcx - .require_lang_item(lang_items::SizedTraitLangItem); + .require_lang_item(lang_items::SizedTraitLangItem, None); let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, @@ -777,9 +777,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool { match &ty { &&Type::ResolvedPath { ref did, .. } => { - *did == tcx.require_lang_item(lang_items::FnTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem) + *did == tcx.require_lang_item(lang_items::FnTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem, None) } _ => false, } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index b9b3e621bb..c3092cea98 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -81,10 +81,10 @@ impl Cfg { }, MetaItemKind::List(ref items) => { let mut sub_cfgs = items.iter().map(Cfg::parse_nested); - match &*name.as_str() { - "all" => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)), - "any" => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)), - "not" => if sub_cfgs.len() == 1 { + match name { + sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)), + sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)), + sym::not => if sub_cfgs.len() == 1 { Ok(!sub_cfgs.next().unwrap()?) } else { Err(InvalidCfgError { diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 405144b444..ec5d86b2c6 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -3,7 +3,6 @@ use super::*; use syntax_pos::DUMMY_SP; use syntax::ast::*; use syntax::attr; -use syntax::source_map::dummy_spanned; use syntax::symbol::Symbol; use syntax::with_default_globals; @@ -181,7 +180,8 @@ fn test_parse_ok() { let mi = attr::mk_name_value_item_str( Ident::from_str("all"), - dummy_spanned(Symbol::intern("done")) + Symbol::intern("done"), + DUMMY_SP, ); assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 6f93c95ede..d71acb4fa7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -20,6 +20,7 @@ use crate::clean::{ self, GetDefId, ToSource, + TypeKind }; use super::Clean; @@ -107,15 +108,16 @@ pub fn try_inline( record_extern_fqn(cx, did, clean::TypeKind::Const); clean::ConstantItem(build_const(cx, did)) } - // FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty - Res::Def(DefKind::Macro(MacroKind::Bang), did) => { + Res::Def(DefKind::Macro(kind), did) => { let mac = build_macro(cx, did, name); - if let clean::MacroItem(..) = mac { - record_extern_fqn(cx, did, clean::TypeKind::Macro); - mac - } else { - return None; - } + + let type_kind = match kind { + MacroKind::Bang => TypeKind::Macro, + MacroKind::Attr => TypeKind::Attr, + MacroKind::Derive => TypeKind::Derive + }; + record_extern_fqn(cx, did, type_kind); + mac } _ => return None, }; @@ -215,10 +217,11 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - + let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); - let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); - let decl = (did, sig).clean(cx); + let (generics, decl) = clean::enter_impl_trait(cx, || { + ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) + }); let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx); clean::Function { decl, @@ -227,7 +230,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, all_types, ret_types, @@ -372,7 +375,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option>, None } }).collect::>(), - (tcx.generics_of(did), &predicates).clean(cx), + clean::enter_impl_trait(cx, || { + (tcx.generics_of(did), &predicates).clean(cx) + }), ) }; let polarity = tcx.impl_polarity(did); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b281505956..95a5869e84 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -29,7 +29,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; use syntax::ext::base::MacroKind; -use syntax::source_map::{dummy_spanned, Spanned}; +use syntax::source_map::DUMMY_SP; use syntax::symbol::{Symbol, kw, sym}; use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; @@ -45,7 +45,7 @@ use std::cell::RefCell; use std::sync::Arc; use std::u32; -use crate::core::{self, DocContext}; +use crate::core::{self, DocContext, ImplTraitParam}; use crate::doctree; use crate::html::render::{cache, ExternalLocation}; use crate::html::item_type::ItemType; @@ -136,94 +136,88 @@ pub struct Crate { pub collapsed: bool, } -impl Clean for hir::Crate { - // note that self here is ignored in favor of `cx.tcx.hir().krate()` since - // that gets around tying self's lifetime to the '_ in cx. - fn clean(&self, cx: &DocContext<'_>) -> Crate { - use crate::visit_lib::LibEmbargoVisitor; - - let v = crate::visit_ast::RustdocVisitor::new(&cx); - let module = v.visit(cx.tcx.hir().krate()); - - { - let mut r = cx.renderinfo.borrow_mut(); - r.deref_trait_did = cx.tcx.lang_items().deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items().owned_box(); - } - - let mut externs = Vec::new(); - for &cnum in cx.tcx.crates().iter() { - externs.push((cnum, cnum.clean(cx))); - // Analyze doc-reachability for extern items - LibEmbargoVisitor::new(cx).visit_lib(cnum); - } - externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - - // Clean the crate, translating the entire libsyntax AST to one that is - // understood by rustdoc. - let mut module = module.clean(cx); - let mut masked_crates = FxHashSet::default(); - - match module.inner { - ModuleItem(ref module) => { - for it in &module.items { - // `compiler_builtins` should be masked too, but we can't apply - // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.def_id.krate)) - { - masked_crates.insert(it.def_id.krate); - } +pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { + use crate::visit_lib::LibEmbargoVisitor; + + let krate = cx.tcx.hir().krate(); + let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate); + + let mut r = cx.renderinfo.get_mut(); + r.deref_trait_did = cx.tcx.lang_items().deref_trait(); + r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); + r.owned_box_did = cx.tcx.lang_items().owned_box(); + + let mut externs = Vec::new(); + for &cnum in cx.tcx.crates().iter() { + externs.push((cnum, cnum.clean(cx))); + // Analyze doc-reachability for extern items + LibEmbargoVisitor::new(&mut cx).visit_lib(cnum); + } + externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); + + // Clean the crate, translating the entire libsyntax AST to one that is + // understood by rustdoc. + let mut module = module.clean(cx); + let mut masked_crates = FxHashSet::default(); + + match module.inner { + ModuleItem(ref module) => { + for it in &module.items { + // `compiler_builtins` should be masked too, but we can't apply + // `#[doc(masked)]` to the injected `extern crate` because it's unstable. + if it.is_extern_crate() + && (it.attrs.has_doc_flag(sym::masked) + || cx.tcx.is_compiler_builtins(it.def_id.krate)) + { + masked_crates.insert(it.def_id.krate); } } - _ => unreachable!(), } + _ => unreachable!(), + } - let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); - { - let m = match module.inner { - ModuleItem(ref mut m) => m, - _ => unreachable!(), - }; - m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { - Item { - source: Span::empty(), - name: Some(prim.to_url_str().to_string()), - attrs: attrs.clone(), - visibility: Some(Public), - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: PrimitiveItem(prim), - } - })); - m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { - Item { - source: Span::empty(), - name: Some(kw.clone()), - attrs: attrs, - visibility: Some(Public), - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: KeywordItem(kw), - } - })); - } + let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); + { + let m = match module.inner { + ModuleItem(ref mut m) => m, + _ => unreachable!(), + }; + m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { + Item { + source: Span::empty(), + name: Some(prim.to_url_str().to_string()), + attrs: attrs.clone(), + visibility: Some(Public), + stability: get_stability(cx, def_id), + deprecation: get_deprecation(cx, def_id), + def_id, + inner: PrimitiveItem(prim), + } + })); + m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { + Item { + source: Span::empty(), + name: Some(kw.clone()), + attrs: attrs, + visibility: Some(Public), + stability: get_stability(cx, def_id), + deprecation: get_deprecation(cx, def_id), + def_id, + inner: KeywordItem(kw), + } + })); + } - Crate { - name, - version: None, - src, - module: Some(module), - externs, - primitives, - external_traits: cx.external_traits.clone(), - masked_crates, - collapsed: false, - } + Crate { + name, + version: None, + src, + module: Some(module), + externs, + primitives, + external_traits: cx.external_traits.clone(), + masked_crates, + collapsed: false, } } @@ -572,23 +566,6 @@ pub enum ItemEnum { } impl ItemEnum { - pub fn generics(&self) -> Option<&Generics> { - Some(match *self { - ItemEnum::StructItem(ref s) => &s.generics, - ItemEnum::EnumItem(ref e) => &e.generics, - ItemEnum::FunctionItem(ref f) => &f.generics, - ItemEnum::TypedefItem(ref t, _) => &t.generics, - ItemEnum::OpaqueTyItem(ref t, _) => &t.generics, - ItemEnum::TraitItem(ref t) => &t.generics, - ItemEnum::ImplItem(ref i) => &i.generics, - ItemEnum::TyMethodItem(ref i) => &i.generics, - ItemEnum::MethodItem(ref i) => &i.generics, - ItemEnum::ForeignFunctionItem(ref f) => &f.generics, - ItemEnum::TraitAliasItem(ref ta) => &ta.generics, - _ => return None, - }) - } - pub fn is_associated(&self) -> bool { match *self { ItemEnum::TypedefItem(_, _) | @@ -930,8 +907,8 @@ impl Attributes { if attr.check_name(sym::enable) { if let Some(feat) = attr.value_str() { let meta = attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::target_feature), - dummy_spanned(feat)); + Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP + ); if let Ok(feat_cfg) = Cfg::parse(&meta) { cfg &= feat_cfg; } @@ -1060,9 +1037,9 @@ pub enum GenericBound { impl GenericBound { fn maybe_sized(cx: &DocContext<'_>) -> GenericBound { - let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); GenericBound::TraitBound(PolyTrait { @@ -1161,13 +1138,13 @@ fn external_generic_args( // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar // from Fn<(A, B,), C> to Fn(A, B) -> C -fn external_path(cx: &DocContext<'_>, name: &str, trait_did: Option, has_self: bool, +fn external_path(cx: &DocContext<'_>, name: Symbol, trait_did: Option, has_self: bool, bindings: Vec, substs: SubstsRef<'_>) -> Path { Path { global: false, res: Res::Err, segments: vec![PathSegment { - name: name.to_string(), + name: name.as_str().to_string(), args: external_generic_args(cx, trait_did, has_self, bindings, substs) }], } @@ -1177,7 +1154,7 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec fn clean(&self, cx: &DocContext<'_>) -> GenericBound { let (trait_ref, ref bounds) = *self; inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(), + let path = external_path(cx, cx.tcx.item_name(trait_ref.def_id), Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs); debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); @@ -1540,9 +1517,7 @@ impl Clean for ty::GenericParamDef { ty::GenericParamDefKind::Lifetime => { (self.name.to_string(), GenericParamDefKind::Lifetime) } - ty::GenericParamDefKind::Type { has_default, .. } => { - cx.renderinfo.borrow_mut().external_param_names - .insert(self.def_id, self.name.clean(cx)); + ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { let default = if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { @@ -1552,7 +1527,7 @@ impl Clean for ty::GenericParamDef { did: self.def_id, bounds: vec![], // These are filled in from the where-clauses. default, - synthetic: None, + synthetic, }) } ty::GenericParamDefKind::Const { .. } => { @@ -1641,7 +1616,7 @@ impl Clean for hir::Generics { match param.kind { GenericParamDefKind::Lifetime => unreachable!(), GenericParamDefKind::Type { did, ref bounds, .. } => { - cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone()); + cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone()); } GenericParamDefKind::Const { .. } => unreachable!(), } @@ -1693,26 +1668,123 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, &'a &'tcx ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext<'_>) -> Generics { use self::WherePredicate as WP; + use std::collections::BTreeMap; let (gens, preds) = *self; + // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses, + // since `Clean for ty::Predicate` would consume them. + let mut impl_trait = BTreeMap::>::default(); + // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { .. } => { - if param.name.as_symbol() == kw::SelfUpper { - assert_eq!(param.index, 0); - return None; + let stripped_typarams = gens.params.iter() + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => None, + ty::GenericParamDefKind::Type { synthetic, .. } => { + if param.name.as_symbol() == kw::SelfUpper { + assert_eq!(param.index, 0); + return None; + } + if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + impl_trait.insert(param.index.into(), vec![]); + return None; + } + Some(param.clean(cx)) + } + ty::GenericParamDefKind::Const { .. } => None, + }).collect::>(); + + // param index -> [(DefId of trait, associated type name, type)] + let mut impl_trait_proj = + FxHashMap::)>>::default(); + + let where_predicates = preds.predicates.iter() + .flat_map(|(p, _)| { + let mut projection = None; + let param_idx = (|| { + if let Some(trait_ref) = p.to_opt_poly_trait_ref() { + if let ty::Param(param) = trait_ref.self_ty().sty { + return Some(param.index); + } + } else if let Some(outlives) = p.to_opt_type_outlives() { + if let ty::Param(param) = outlives.skip_binder().0.sty { + return Some(param.index); + } + } else if let ty::Predicate::Projection(p) = p { + if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty { + projection = Some(p); + return Some(param.index); + } + } + + None + })(); + + if let Some(param_idx) = param_idx { + if let Some(b) = impl_trait.get_mut(¶m_idx.into()) { + let p = p.clean(cx)?; + + b.extend( + p.get_bounds() + .into_iter() + .flatten() + .cloned() + .filter(|b| !b.is_sized_bound(cx)) + ); + + let proj = projection + .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty)); + if let Some(((_, trait_did, name), rhs)) = + proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))) + { + impl_trait_proj + .entry(param_idx) + .or_default() + .push((trait_did, name.to_string(), rhs)); + } + + return None; + } } - Some(param.clean(cx)) + + Some(p) + }) + .collect::>(); + + for (param, mut bounds) in impl_trait { + // Move trait bounds to the front. + bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { + false + } else { + true + }); + + if let crate::core::ImplTraitParam::ParamIndex(idx) = param { + if let Some(proj) = impl_trait_proj.remove(&idx) { + for (trait_did, name, rhs) in proj { + simplify::merge_bounds( + cx, + &mut bounds, + trait_did, + &name, + &rhs.clean(cx), + ); + } + } + } else { + unreachable!(); } - ty::GenericParamDefKind::Const { .. } => None, - }).collect::>(); - let mut where_predicates = preds.predicates.iter() - .flat_map(|(p, _)| p.clean(cx)) + cx.impl_trait_bounds.borrow_mut().insert(param, bounds); + } + + // Now that `cx.impl_trait_bounds` is populated, we can process + // remaining predicates which could contain `impl Trait`. + let mut where_predicates = where_predicates + .into_iter() + .flat_map(|p| p.clean(cx)) .collect::>(); // Type parameters and have a Sized bound by default unless removed with @@ -2023,7 +2095,7 @@ impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { Argument { - name: name_from_pat(&body.arguments[i].pat), + name: name_from_pat(&body.params[i].pat), type_: ty.clean(cx), } }).collect() @@ -2303,7 +2375,7 @@ impl Clean for ty::AssocItem { ty::ImplContainer(def_id) => { cx.tcx.type_of(def_id) } - ty::TraitContainer(_) => cx.tcx.mk_self_type() + ty::TraitContainer(_) => cx.tcx.types.self_param, }; let self_arg_ty = *sig.input(0).skip_binder(); if self_arg_ty == self_ty { @@ -2331,6 +2403,7 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; + let asyncness = cx.tcx.asyncness(self.def_id); let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, @@ -2342,7 +2415,7 @@ impl Clean for ty::AssocItem { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, defaultness, all_types, @@ -2613,6 +2686,21 @@ impl Type { _ => false, } } + + pub fn projection(&self) -> Option<(&Type, DefId, &str)> { + let (self_, trait_, name) = match self { + QPath { ref self_type, ref trait_, ref name } => { + (self_type, trait_, name) + } + _ => return None, + }; + let trait_did = match **trait_ { + ResolvedPath { did, .. } => did, + _ => return None, + }; + Some((&self_, trait_did, name)) + } + } impl GetDefId for Type { @@ -2791,7 +2879,7 @@ impl Clean for hir::Ty { if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() { return new_ty; } - if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) { return ImplTrait(bounds); } } @@ -3002,8 +3090,7 @@ impl<'tcx> Clean for Ty<'tcx> { AdtKind::Enum => TypeKind::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), - None, false, vec![], substs); + let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs); ResolvedPath { path, param_names: None, @@ -3013,7 +3100,7 @@ impl<'tcx> Clean for Ty<'tcx> { } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, TypeKind::Foreign); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], InternalSubsts::empty()); ResolvedPath { path: path, @@ -3042,7 +3129,7 @@ impl<'tcx> Clean for Ty<'tcx> { reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b))); for did in dids { let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = GenericBound::TraitBound(PolyTrait { @@ -3067,7 +3154,7 @@ impl<'tcx> Clean for Ty<'tcx> { }); } - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), + let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); ResolvedPath { path, @@ -3082,7 +3169,13 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Projection(ref data) => data.clean(cx), - ty::Param(ref p) => Generic(p.name.to_string()), + ty::Param(ref p) => { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) { + ImplTrait(bounds) + } else { + Generic(p.name.to_string()) + } + } ty::Opaque(def_id, substs) => { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, @@ -3686,7 +3779,7 @@ pub struct BareFunctionDecl { impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, || { - (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx)) + (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx)) }); BareFunctionDecl { unsafety: self.unsafety, @@ -3884,7 +3977,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>, F32 => tcx.lang_items().f32_impl(), F64 => tcx.lang_items().f64_impl(), Char => tcx.lang_items().char_impl(), - Bool => None, + Bool => tcx.lang_items().bool_impl(), Str => tcx.lang_items().str_impl(), Slice => tcx.lang_items().slice_impl(), Array => tcx.lang_items().slice_impl(), @@ -4102,12 +4195,14 @@ fn name_from_pat(p: &hir::Pat) -> String { PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::Struct(ref name, ref fields, etc) => { format!("{} {{ {}{} }}", qpath_to_string(name), - fields.iter().map(|&Spanned { node: ref fp, .. }| - format!("{}: {}", fp.ident, name_from_pat(&*fp.pat))) + fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat))) .collect::>().join(", "), if etc { ", .." } else { "" } ) } + PatKind::Or(ref pats) => { + pats.iter().map(|p| name_from_pat(&**p)).collect::>().join(" | ") + } PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::>().join(", ")), PatKind::Box(ref p) => name_from_pat(&**p), diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index e4fba73b82..8758ab1969 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -53,58 +53,21 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { // Look for equality predicates on associated types that can be merged into // general bound predicates equalities.retain(|&(ref lhs, ref rhs)| { - let (self_, trait_, name) = match *lhs { - clean::QPath { ref self_type, ref trait_, ref name } => { - (self_type, trait_, name) - } - _ => return true, - }; - let generic = match **self_ { - clean::Generic(ref s) => s, - _ => return true, + let (self_, trait_did, name) = if let Some(p) = lhs.projection() { + p + } else { + return true; }; - let trait_did = match **trait_ { - clean::ResolvedPath { did, .. } => did, + let generic = match self_ { + clean::Generic(s) => s, _ => return true, }; let bounds = match params.get_mut(generic) { Some(bound) => bound, None => return true, }; - !bounds.iter_mut().any(|b| { - let trait_ref = match *b { - clean::GenericBound::TraitBound(ref mut tr, _) => tr, - clean::GenericBound::Outlives(..) => return false, - }; - let (did, path) = match trait_ref.trait_ { - clean::ResolvedPath { did, ref mut path, ..} => (did, path), - _ => return false, - }; - // If this QPath's trait `trait_did` is the same as, or a supertrait - // of, the bound's trait `did` then we can keep going, otherwise - // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, did, trait_did) { - return false - } - let last = path.segments.last_mut().expect("segments were empty"); - match last.args { - PP::AngleBracketed { ref mut bindings, .. } => { - bindings.push(clean::TypeBinding { - name: name.clone(), - kind: clean::TypeBindingKind::Equality { - ty: rhs.clone(), - }, - }); - } - PP::Parenthesized { ref mut output, .. } => { - assert!(output.is_none()); - if *rhs != clean::Type::Tuple(Vec::new()) { - *output = Some(rhs.clone()); - } - } - }; - true - }) + + merge_bounds(cx, bounds, trait_did, name, rhs) }); // And finally, let's reassemble everything @@ -127,6 +90,49 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { clauses } +pub fn merge_bounds( + cx: &clean::DocContext<'_>, + bounds: &mut Vec, + trait_did: DefId, + name: &str, + rhs: &clean::Type, +) -> bool { + !bounds.iter_mut().any(|b| { + let trait_ref = match *b { + clean::GenericBound::TraitBound(ref mut tr, _) => tr, + clean::GenericBound::Outlives(..) => return false, + }; + let (did, path) = match trait_ref.trait_ { + clean::ResolvedPath { did, ref mut path, ..} => (did, path), + _ => return false, + }; + // If this QPath's trait `trait_did` is the same as, or a supertrait + // of, the bound's trait `did` then we can keep going, otherwise + // this is just a plain old equality bound. + if !trait_is_same_or_supertrait(cx, did, trait_did) { + return false + } + let last = path.segments.last_mut().expect("segments were empty"); + match last.args { + PP::AngleBracketed { ref mut bindings, .. } => { + bindings.push(clean::TypeBinding { + name: name.to_string(), + kind: clean::TypeBindingKind::Equality { + ty: rhs.clone(), + }, + }); + } + PP::Parenthesized { ref mut output, .. } => { + assert!(output.is_none()); + if *rhs != clean::Type::Tuple(Vec::new()) { + *output = Some(rhs.clone()); + } + } + }; + true + }) +} + pub fn ty_params(mut params: Vec) -> Vec { for param in &mut params { match param.kind { @@ -149,9 +155,11 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, return true } let predicates = cx.tcx.super_predicates_of(child); + debug_assert!(cx.tcx.generics_of(child).has_self); + let self_ty = cx.tcx.types.self_param; predicates.predicates.iter().filter_map(|(pred, _)| { if let ty::Predicate::Trait(ref pred) = *pred { - if pred.skip_binder().trait_ref.self_ty().is_self() { + if pred.skip_binder().trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 98ab957ecb..19ea781430 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -6,9 +6,10 @@ use errors; use getopts; use rustc::lint::Level; use rustc::session; +use rustc::session::config::{CrateType, parse_crate_types_from_list}; use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options, - get_cmd_lint_options, ExternEntry}; + get_cmd_lint_options, host_triple, ExternEntry}; use rustc::session::search_paths::SearchPath; use rustc_driver; use rustc_target::spec::TargetTriple; @@ -32,27 +33,33 @@ pub struct Options { pub input: PathBuf, /// The name of the crate being documented. pub crate_name: Option, + /// Whether or not this is a proc-macro crate + pub proc_macro_crate: bool, /// How to format errors and warnings. pub error_format: ErrorOutputType, /// Library search paths to hand to the compiler. pub libs: Vec, + /// Library search paths strings to hand to the compiler. + pub lib_strs: Vec, /// The list of external crates to link against. pub externs: Externs, + /// The list of external crates strings to link against. + pub extern_strs: Vec, /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`. pub cfgs: Vec, /// Codegen options to hand to the compiler. pub codegen_options: CodegenOptions, + /// Codegen options strings to hand to the compiler. + pub codegen_options_strs: Vec, /// Debugging (`-Z`) options to pass to the compiler. pub debugging_options: DebuggingOptions, /// The target used to compile the crate against. - pub target: Option, + pub target: TargetTriple, /// Edition used when reading the crate. Defaults to "2015". Also used by default when /// compiling doctests from the crate. pub edition: Edition, /// The path to the sysroot. Used during the compilation process. pub maybe_sysroot: Option, - /// Linker to use when building doctests. - pub linker: Option, /// Lint information passed over the command-line. pub lint_opts: Vec<(String, Level)>, /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be @@ -70,6 +77,18 @@ pub struct Options { /// Optional path to persist the doctest executables to, defaults to a /// temporary directory if not set. pub persist_doctests: Option, + /// Runtool to run doctests with + pub runtool: Option, + /// Arguments to pass to the runtool + pub runtool_args: Vec, + /// Whether to allow ignoring doctests on a per-target basis + /// For example, using ignore-foo to ignore running the doctest on any target that + /// contains "foo" as a substring + pub enable_per_target_ignores: bool, + + /// The path to a rustc-like binary to build tests with. If not set, we + /// default to loading from $sysroot/bin/rustc. + pub test_builder: Option, // Options that affect the documentation process @@ -111,6 +130,7 @@ impl fmt::Debug for Options { f.debug_struct("Options") .field("input", &self.input) .field("crate_name", &self.crate_name) + .field("proc_macro_crate", &self.proc_macro_crate) .field("error_format", &self.error_format) .field("libs", &self.libs) .field("externs", &FmtExterns(&self.externs)) @@ -120,7 +140,6 @@ impl fmt::Debug for Options { .field("target", &self.target) .field("edition", &self.edition) .field("maybe_sysroot", &self.maybe_sysroot) - .field("linker", &self.linker) .field("lint_opts", &self.lint_opts) .field("describe_lints", &self.describe_lints) .field("lint_cap", &self.lint_cap) @@ -133,6 +152,9 @@ impl fmt::Debug for Options { .field("show_coverage", &self.show_coverage) .field("crate_version", &self.crate_version) .field("render_options", &self.render_options) + .field("runtool", &self.runtool) + .field("runtool_args", &self.runtool_args) + .field("enable-per-target-ignores", &self.enable_per_target_ignores) .finish() } } @@ -407,7 +429,9 @@ impl Options { } } - let target = matches.opt_str("target").map(|target| { + let target = matches.opt_str("target").map_or( + TargetTriple::from_triple(host_triple()), + |target| { if target.ends_with(".json") { TargetTriple::TargetPath(PathBuf::from(target)) } else { @@ -431,11 +455,19 @@ impl Options { }; let manual_passes = matches.opt_strs("passes"); + let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) { + Ok(types) => types, + Err(e) =>{ + diag.struct_err(&format!("unknown crate type: {}", e)).emit(); + return Err(1); + } + }; + let crate_name = matches.opt_str("crate-name"); + let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let display_warnings = matches.opt_present("display-warnings"); - let linker = matches.opt_str("linker").map(PathBuf::from); let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); let enable_minification = !matches.opt_present("disable-minification"); @@ -448,22 +480,32 @@ impl Options { let generate_search_filter = !matches.opt_present("disable-per-crate-search"); let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from); let generate_redirect_pages = matches.opt_present("generate-redirect-pages"); + let test_builder = matches.opt_str("test-builder").map(PathBuf::from); + let codegen_options_strs = matches.opt_strs("C"); + let lib_strs = matches.opt_strs("L"); + let extern_strs = matches.opt_strs("extern"); + let runtool = matches.opt_str("runtool"); + let runtool_args = matches.opt_strs("runtool-arg"); + let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); Ok(Options { input, crate_name, + proc_macro_crate, error_format, libs, + lib_strs, externs, + extern_strs, cfgs, codegen_options, + codegen_options_strs, debugging_options, target, edition, maybe_sysroot, - linker, lint_opts, describe_lints, lint_cap, @@ -475,6 +517,10 @@ impl Options { show_coverage, crate_version, persist_doctests, + runtool, + runtool_args, + enable_per_target_ignores, + test_builder, render_options: RenderOptions { output, external_html, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 87381f224d..010e4cf6cd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,6 @@ use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; -use rustc_target::spec::TargetTriple; use syntax::source_map; use syntax::attr; @@ -30,7 +29,7 @@ use std::rc::Rc; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::clean; -use crate::clean::{Clean, MAX_DEF_ID, AttributesExt}; +use crate::clean::{MAX_DEF_ID, AttributesExt}; use crate::html::render::RenderInfo; use crate::passes; @@ -61,8 +60,8 @@ pub struct DocContext<'tcx> { pub lt_substs: RefCell>, /// Table `DefId` of const parameter -> substituted const pub ct_substs: RefCell>, - /// Table DefId of `impl Trait` in argument position -> bounds - pub impl_trait_bounds: RefCell>>, + /// Table synthetic type parameter for `impl Trait` in argument position -> bounds + pub impl_trait_bounds: RefCell>>, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. @@ -193,6 +192,8 @@ pub fn new_handler(error_format: ErrorOutputType, source_map.map(|cm| cm as _), short, sessopts.debugging_opts.teach, + sessopts.debugging_opts.terminal_width, + false, ).ui_testing(ui_testing) ) }, @@ -205,6 +206,7 @@ pub fn new_handler(error_format: ErrorOutputType, source_map, pretty, json_rendered, + false, ).ui_testing(ui_testing) ) }, @@ -228,6 +230,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let RustdocOptions { input, crate_name, + proc_macro_crate, error_format, libs, externs, @@ -292,12 +295,16 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } }).collect(); - let host_triple = TargetTriple::from_triple(config::host_triple()); + let crate_types = if proc_macro_crate { + vec![config::CrateType::ProcMacro] + } else { + vec![config::CrateType::Rlib] + }; // plays with error output here! let sessopts = config::Options { maybe_sysroot, search_paths: libs, - crate_types: vec![config::CrateType::Rlib], + crate_types, lint_opts: if !display_warnings { lint_opts } else { @@ -306,7 +313,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt lint_cap: Some(lint_cap.unwrap_or_else(|| lint::Forbid)), cg: codegen_options, externs, - target_triple: target.unwrap_or(host_triple), + target_triple: target, // Ensure that rustdoc works even if rustc is feature-staged unstable_features: UnstableFeatures::Allow, actually_rustdoc: true, @@ -363,7 +370,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut renderinfo = RenderInfo::default(); renderinfo.access_levels = access_levels; - let ctxt = DocContext { + let mut ctxt = DocContext { tcx, resolver, cstore: compiler.cstore().clone(), @@ -383,7 +390,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; debug!("crate: {:?}", tcx.hir().krate()); - let mut krate = tcx.hir().krate().clean(&ctxt); + let mut krate = clean::krate(&mut ctxt); fn report_deprecated_attr(name: &str, diag: &errors::Handler) { let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ @@ -459,3 +466,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }) }) } + +/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter +/// for `impl Trait` in argument position. +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum ImplTraitParam { + DefId(DefId), + ParamIndex(u32), +} + +impl From for ImplTraitParam { + fn from(did: DefId) -> Self { + ImplTraitParam::DefId(did) + } +} + +impl From for ImplTraitParam { + fn from(idx: u32) -> Self { + ImplTraitParam::ParamIndex(idx) + } +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9c22837bda..dcd32192ff 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -6,6 +6,7 @@ //! them in the future to instead emit any format desired. use std::borrow::Cow; +use std::cell::Cell; use std::fmt; use rustc::hir::def_id::DefId; @@ -15,7 +16,101 @@ use rustc::hir; use crate::clean::{self, PrimitiveType}; use crate::html::item_type::ItemType; -use crate::html::render::{self, cache, CURRENT_LOCATION_KEY}; +use crate::html::render::{self, cache, CURRENT_DEPTH}; + +pub trait Print { + fn print(self, buffer: &mut Buffer); +} + +impl Print for F + where F: FnOnce(&mut Buffer), +{ + fn print(self, buffer: &mut Buffer) { + (self)(buffer) + } +} + +impl Print for String { + fn print(self, buffer: &mut Buffer) { + buffer.write_str(&self); + } +} + +impl Print for &'_ str { + fn print(self, buffer: &mut Buffer) { + buffer.write_str(self); + } +} + +#[derive(Debug, Clone)] +pub struct Buffer { + for_html: bool, + buffer: String, +} + +impl Buffer { + crate fn empty_from(v: &Buffer) -> Buffer { + Buffer { + for_html: v.for_html, + buffer: String::new(), + } + } + + crate fn html() -> Buffer { + Buffer { + for_html: true, + buffer: String::new(), + } + } + + crate fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + crate fn into_inner(self) -> String { + self.buffer + } + + crate fn insert_str(&mut self, idx: usize, s: &str) { + self.buffer.insert_str(idx, s); + } + + crate fn push_str(&mut self, s: &str) { + self.buffer.push_str(s); + } + + // Intended for consumption by write! and writeln! (std::fmt) but without + // the fmt::Result return type imposed by fmt::Write (and avoiding the trait + // import). + crate fn write_str(&mut self, s: &str) { + self.buffer.push_str(s); + } + + // Intended for consumption by write! and writeln! (std::fmt) but without + // the fmt::Result return type imposed by fmt::Write (and avoiding the trait + // import). + crate fn write_fmt(&mut self, v: fmt::Arguments<'_>) { + use fmt::Write; + self.buffer.write_fmt(v).unwrap(); + } + + crate fn to_display(mut self, t: T) -> String { + t.print(&mut self); + self.into_inner() + } + + crate fn with_formatter) -> fmt::Result>(&mut self, t: T) { + self.from_display(display_fn(move |f| (t)(f))); + } + + crate fn from_display(&mut self, t: T) { + if self.for_html { + write!(self, "{}", t); + } else { + write!(self, "{:#}", t); + } + } +} /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) @@ -36,13 +131,8 @@ pub struct AsyncSpace(pub hir::IsAsync); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); -/// Similar to VisSpace, but used for mutability -#[derive(Copy, Clone)] -pub struct RawMutableSpace(pub clean::Mutability); /// Wrapper struct for emitting type parameter bounds. pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); -/// Wrapper struct for emitting a comma-separated list of items -pub struct CommaSep<'a, T>(pub &'a [T]); pub struct AbiSpace(pub Abi); pub struct DefaultSpace(pub bool); @@ -71,11 +161,6 @@ pub struct WhereClause<'a>{ pub end_newline: bool, } -pub struct HRef<'a> { - pub did: DefId, - pub text: &'a str, -} - impl<'a> VisSpace<'a> { pub fn get(self) -> &'a Option { let VisSpace(v) = self; v @@ -94,14 +179,14 @@ impl ConstnessSpace { } } -impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, item) in self.0.iter().enumerate() { +fn comma_sep(items: &[T]) -> impl fmt::Display + '_ { + display_fn(move |f| { + for (i, item) in items.iter().enumerate() { if i != 0 { write!(f, ", ")?; } fmt::Display::fmt(item, f)?; } Ok(()) - } + }) } impl<'a> fmt::Display for GenericBounds<'a> { @@ -168,9 +253,9 @@ impl fmt::Display for clean::Generics { return Ok(()); } if f.alternate() { - write!(f, "<{:#}>", CommaSep(&real_params)) + write!(f, "<{:#}>", comma_sep(&real_params)) } else { - write!(f, "<{}>", CommaSep(&real_params)) + write!(f, "<{}>", comma_sep(&real_params)) } } } @@ -209,11 +294,11 @@ impl<'a> fmt::Display for WhereClause<'a> { } &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => { clause.push_str(&format!("{}: {}", - lifetime, - bounds.iter() - .map(|b| b.to_string()) - .collect::>() - .join(" + "))); + lifetime, + bounds.iter() + .map(|b| b.to_string()) + .collect::>() + .join(" + "))); } &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { if f.alternate() { @@ -268,9 +353,9 @@ impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if !self.generic_params.is_empty() { if f.alternate() { - write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{:#}> ", comma_sep(&self.generic_params))?; } else { - write!(f, "for<{}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{}> ", comma_sep(&self.generic_params))?; } } if f.alternate() { @@ -407,16 +492,16 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { return None } - let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone()); + let depth = CURRENT_DEPTH.with(|l| l.get()); let (fqp, shortty, mut url) = match cache.paths.get(&did) { Some(&(ref fqp, shortty)) => { - (fqp, shortty, "../".repeat(loc.len())) + (fqp, shortty, "../".repeat(depth)) } None => { let &(ref fqp, shortty) = cache.external_paths.get(&did)?; (fqp, shortty, match cache.extern_locations[&did.krate] { (.., render::Remote(ref s)) => s.to_string(), - (.., render::Local) => "../".repeat(loc.len()), + (.., render::Local) => "../".repeat(depth), (.., render::Unknown) => return None, }) } @@ -452,19 +537,18 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, } } if w.alternate() { - write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?; + write!(w, "{}{:#}", &last.name, last.args)?; } else { let path = if use_absolute { - match href(did) { - Some((_, _, fqp)) => { - format!("{}::{}", - fqp[..fqp.len() - 1].join("::"), - HRef::new(did, fqp.last().unwrap())) - } - None => HRef::new(did, &last.name).to_string(), + if let Some((_, _, fqp)) = href(did) { + format!("{}::{}", + fqp[..fqp.len() - 1].join("::"), + anchor(did, fqp.last().unwrap())) + } else { + last.name.to_string() } } else { - HRef::new(did, &last.name).to_string() + anchor(did, &last.name).to_string() }; write!(w, "{}{}", path, last.args)?; } @@ -479,7 +563,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, if !f.alternate() { match m.primitive_locations.get(&prim) { Some(&def_id) if def_id.is_local() => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); let len = if len == 0 {0} else {len - 1}; write!(f, "", "../".repeat(len), @@ -492,7 +576,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, Some((cname, s.to_string())) } (ref cname, _, render::Local) => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); Some((cname, "../".repeat(len))) } (.., render::Unknown) => None, @@ -516,38 +600,30 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, } /// Helper to render type parameters -fn tybounds(w: &mut fmt::Formatter<'_>, - param_names: &Option>) -> fmt::Result { - match *param_names { - Some(ref params) => { - for param in params { - write!(w, " + ")?; - fmt::Display::fmt(param, w)?; +fn tybounds(param_names: &Option>) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *param_names { + Some(ref params) => { + for param in params { + write!(f, " + ")?; + fmt::Display::fmt(param, f)?; + } + Ok(()) } - Ok(()) + None => Ok(()) } - None => Ok(()) - } -} - -impl<'a> HRef<'a> { - pub fn new(did: DefId, text: &'a str) -> HRef<'a> { - HRef { did: did, text: text } - } + }) } -impl<'a> fmt::Display for HRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match href(self.did) { - Some((url, shortty, fqp)) => if !f.alternate() { - write!(f, "{}", - shortty, url, shortty, fqp.join("::"), self.text) - } else { - write!(f, "{}", self.text) - }, - _ => write!(f, "{}", self.text), +pub fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ { + display_fn(move |f| { + if let Some((url, short_ty, fqp)) = href(did) { + write!(f, r#"{}"#, + short_ty, url, short_ty, fqp.join("::"), text) + } else { + write!(f, "{}", text) } - } + }) } fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> fmt::Result { @@ -561,7 +637,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. resolved_path(f, did, path, is_generic, use_absolute)?; - tybounds(f, param_names) + fmt::Display::fmt(&tybounds(param_names), f) } clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), @@ -570,12 +646,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> write!(f, "{}{:#}fn{:#}{:#}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi), - CommaSep(&decl.generic_params), + comma_sep(&decl.generic_params), decl.decl) } else { write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl) + write!(f, "{}{}", comma_sep(&decl.generic_params), decl.decl) } } clean::Tuple(ref typs) => { @@ -589,7 +665,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&CommaSep(many), f)?; + fmt::Display::fmt(&comma_sep(many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } @@ -607,19 +683,22 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Never => primitive_link(f, PrimitiveType::Never, "!"), clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."), clean::RawPointer(m, ref t) => { + let m = match m { + clean::Immutable => "const", + clean::Mutable => "mut", + }; match **t { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { if f.alternate() { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{:#}", RawMutableSpace(m), t)) + &format!("*{} {:#}", m, t)) } else { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{}", RawMutableSpace(m), t)) + &format!("*{} {}", m, t)) } } _ => { - primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}", RawMutableSpace(m)))?; + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?; fmt::Display::fmt(t, f) } } @@ -793,9 +872,9 @@ impl fmt::Display for clean::Impl { // The difference from above is that trait is not hyperlinked. pub fn fmt_impl_for_trait_page(i: &clean::Impl, - f: &mut fmt::Formatter<'_>, - use_absolute: bool) -> fmt::Result { - fmt_impl(i, f, false, use_absolute) + f: &mut Buffer, + use_absolute: bool) { + f.with_formatter(|f| fmt_impl(i, f, false, use_absolute)) } impl fmt::Display for clean::Arguments { @@ -1047,15 +1126,6 @@ impl fmt::Display for MutableSpace { } } -impl fmt::Display for RawMutableSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawMutableSpace(clean::Immutable) => write!(f, "const "), - RawMutableSpace(clean::Mutable) => write!(f, "mut "), - } - } -} - impl fmt::Display for AbiSpace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let quot = if f.alternate() { "\"" } else { """ }; @@ -1075,3 +1145,19 @@ impl fmt::Display for DefaultSpace { } } } + +crate fn display_fn( + f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +) -> impl fmt::Display { + WithFormatter(Cell::new(Some(f))) +} + +struct WithFormatter(Cell>); + +impl fmt::Display for WithFormatter + where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0.take()).unwrap()(f) + } +} diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index ae0bd1aafa..56074f4ab1 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,9 +1,8 @@ -use std::fmt; -use std::io; use std::path::PathBuf; use crate::externalfiles::ExternalHtml; use crate::html::render::SlashChecker; +use crate::html::format::{Buffer, Print}; #[derive(Clone)] pub struct Layout { @@ -11,6 +10,12 @@ pub struct Layout { pub favicon: String, pub external_html: ExternalHtml, pub krate: String, + /// The given user css file which allow to customize the generated + /// documentation theme. + pub css_file_extension: Option, + /// If false, the `select` element to have search filtering by crates on rendered docs + /// won't be generated. + pub generate_search_filter: bool, } pub struct Page<'a> { @@ -25,19 +30,15 @@ pub struct Page<'a> { pub static_extra_scripts: &'a [&'a str], } -pub fn render( - dst: &mut dyn io::Write, +pub fn render( layout: &Layout, page: &Page<'_>, - sidebar: &S, - t: &T, - css_file_extension: bool, + sidebar: S, + t: T, themes: &[PathBuf], - generate_search_filter: bool, -) -> io::Result<()> { +) -> String { let static_root_path = page.static_root_path.unwrap_or(page.root_path); - write!(dst, -"\ + format!("\ \ \ \ @@ -164,7 +165,7 @@ pub fn render( \ \ ", - css_extension = if css_file_extension { + css_extension = if layout.css_file_extension.is_some() { format!("", @@ -173,7 +174,7 @@ pub fn render( } else { String::new() }, - content = *t, + content = Buffer::html().to_display(t), static_root_path = static_root_path, root_path = page.root_path, css_class = page.css_class, @@ -207,7 +208,7 @@ pub fn render( in_header = layout.external_html.in_header, before_content = layout.external_html.before_content, after_content = layout.external_html.after_content, - sidebar = *sidebar, + sidebar = Buffer::html().to_display(sidebar), krate = layout.krate, themes = themes.iter() .filter_map(|t| t.file_stem()) @@ -228,7 +229,7 @@ pub fn render( root_path=page.root_path, extra_script=e) }).collect::(), - filter_crates=if generate_search_filter { + filter_crates=if layout.generate_search_filter { "" @@ -238,9 +239,9 @@ pub fn render( ) } -pub fn redirect(dst: &mut dyn io::Write, url: &str) -> io::Result<()> { +pub fn redirect(url: &str) -> String { // ", - self.settings.iter() - .map(|(id, text, enabled)| { - format!("

\ - \ -
{}
\ -
", id, if *enabled { " checked" } else { "" }, text) - }) - .collect::(), - self.root_path, - self.suffix) - } + settings.iter() + .map(|(id, text, enabled)| { + format!("
\ + \ +
{}
\ +
", id, if *enabled { " checked" } else { "" }, text) + }) + .collect::(), + root_path, + suffix) } impl Context { @@ -2057,31 +1838,6 @@ impl Context { "../".repeat(self.current.len()) } - /// Recurse in the directory structure and change the "root path" to make - /// sure it always points to the top (relatively). - fn recurse(&mut self, s: String, f: F) -> T where - F: FnOnce(&mut Context) -> T, - { - if s.is_empty() { - panic!("Unexpected empty destination: {:?}", self.current); - } - let prev = self.dst.clone(); - self.dst.push(&s); - self.current.push(s); - - info!("Recursing into {}", self.dst.display()); - - let ret = f(self); - - info!("Recursed; leaving {}", self.dst.display()); - - // Go back to where we were at - self.dst = prev; - self.current.pop().unwrap(); - - ret - } - /// Main method for rendering a crate. /// /// This currently isn't parallelized, but it'd be pretty easy to add @@ -2136,18 +1892,12 @@ impl Context { } else { String::new() }; - let mut v = Vec::new(); - try_err!(layout::render(&mut v, &self.shared.layout, - &page, &sidebar, &all, - self.shared.css_file_extension.is_some(), - &self.shared.themes, - self.shared.generate_search_filter), - &final_file); - self.shared.fs.write(&final_file, &v)?; + let v = layout::render(&self.shared.layout, + &page, sidebar, |buf: &mut Buffer| all.print(buf), + &self.shared.themes); + self.shared.fs.write(&final_file, v.as_bytes())?; // Generating settings page. - let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"), - &self.shared.resource_suffix); page.title = "Rustdoc settings"; page.description = "Settings of Rustdoc"; page.root_path = "./"; @@ -2155,28 +1905,25 @@ impl Context { let mut themes = self.shared.themes.clone(); let sidebar = "

Settings

"; themes.push(PathBuf::from("settings.css")); - let layout = self.shared.layout.clone(); - let mut v = Vec::new(); - try_err!(layout::render(&mut v, &layout, - &page, &sidebar, &settings, - self.shared.css_file_extension.is_some(), - &themes, - self.shared.generate_search_filter), - &settings_file); - self.shared.fs.write(&settings_file, &v)?; + let v = layout::render( + &self.shared.layout, + &page, sidebar, settings( + self.shared.static_root_path.as_deref().unwrap_or("./"), + &self.shared.resource_suffix + ), + &themes); + self.shared.fs.write(&settings_file, v.as_bytes())?; Ok(()) } fn render_item(&self, - writer: &mut dyn io::Write, it: &clean::Item, - pushname: bool) - -> io::Result<()> { + pushname: bool) -> String { // A little unfortunate that this is done like this, but it sure // does make formatting *a lot* nicer. - CURRENT_LOCATION_KEY.with(|slot| { - *slot.borrow_mut() = self.current.clone(); + CURRENT_DEPTH.with(|slot| { + slot.set(self.current.len()); }); let mut title = if it.is_primitive() || it.is_keyword() { @@ -2219,12 +1966,10 @@ impl Context { } if !self.render_redirect_pages { - layout::render(writer, &self.shared.layout, &page, - &Sidebar{ cx: self, item: it }, - &Item{ cx: self, item: it }, - self.shared.css_file_extension.is_some(), - &self.shared.themes, - self.shared.generate_search_filter)?; + layout::render(&self.shared.layout, &page, + |buf: &mut _| print_sidebar(self, it, buf), + |buf: &mut _| print_item(self, it, buf), + &self.shared.themes) } else { let mut url = self.root_path(); if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { @@ -2233,10 +1978,11 @@ impl Context { url.push_str("/"); } url.push_str(&item_path(ty, names.last().unwrap())); - layout::redirect(writer, &url)?; + layout::redirect(&url) + } else { + String::new() } } - Ok(()) } /// Non-parallelized version of rendering an item. This will take the input @@ -2262,45 +2008,49 @@ impl Context { // modules are special because they add a namespace. We also need to // recurse into the items of the module as well. let name = item.name.as_ref().unwrap().to_string(); - let mut item = Some(item); - let scx = self.shared.clone(); - self.recurse(name, |this| { - let item = item.take().unwrap(); - - let mut buf = Vec::new(); - this.render_item(&mut buf, &item, false).unwrap(); - // buf will be empty if the module is stripped and there is no redirect for it - if !buf.is_empty() { - this.shared.ensure_dir(&this.dst)?; - let joint_dst = this.dst.join("index.html"); - scx.fs.write(&joint_dst, buf)?; - } + let scx = &self.shared; + if name.is_empty() { + panic!("Unexpected empty destination: {:?}", self.current); + } + let prev = self.dst.clone(); + self.dst.push(&name); + self.current.push(name); - let m = match item.inner { - clean::StrippedItem(box clean::ModuleItem(m)) | - clean::ModuleItem(m) => m, - _ => unreachable!() - }; + info!("Recursing into {}", self.dst.display()); - // Render sidebar-items.js used throughout this module. - if !this.render_redirect_pages { - let items = this.build_sidebar_items(&m); - let js_dst = this.dst.join("sidebar-items.js"); - let mut v = Vec::new(); - try_err!(write!(&mut v, "initSidebarItems({});", - as_json(&items)), &js_dst); - scx.fs.write(&js_dst, &v)?; - } + let buf = self.render_item(&item, false); + // buf will be empty if the module is stripped and there is no redirect for it + if !buf.is_empty() { + self.shared.ensure_dir(&self.dst)?; + let joint_dst = self.dst.join("index.html"); + scx.fs.write(&joint_dst, buf.as_bytes())?; + } - for item in m.items { - f(this, item); - } + let m = match item.inner { + clean::StrippedItem(box clean::ModuleItem(m)) | + clean::ModuleItem(m) => m, + _ => unreachable!() + }; + + // Render sidebar-items.js used throughout this module. + if !self.render_redirect_pages { + let items = self.build_sidebar_items(&m); + let js_dst = self.dst.join("sidebar-items.js"); + let v = format!("initSidebarItems({});", as_json(&items)); + scx.fs.write(&js_dst, &v)?; + } - Ok(()) - })?; + for item in m.items { + f(self, item); + } + + info!("Recursed; leaving {}", self.dst.display()); + + // Go back to where we were at + self.dst = prev; + self.current.pop().unwrap(); } else if item.name.is_some() { - let mut buf = Vec::new(); - self.render_item(&mut buf, &item, true).unwrap(); + let buf = self.render_item(&item, true); // buf will be empty if the item is stripped and there is no redirect for it if !buf.is_empty() { let name = item.name.as_ref().unwrap(); @@ -2308,7 +2058,7 @@ impl Context { let file_name = &item_path(item_type, name); self.shared.ensure_dir(&self.dst)?; let joint_dst = self.dst.join(file_name); - self.shared.fs.write(&joint_dst, buf)?; + self.shared.fs.write(&joint_dst, buf.as_bytes())?; if !self.render_redirect_pages { all.append(full_path(self, &item), &item_type); @@ -2318,18 +2068,16 @@ impl Context { // URL for the page. let redir_name = format!("{}.{}.html", name, item_type.name_space()); let redir_dst = self.dst.join(redir_name); - let mut v = Vec::new(); - try_err!(layout::redirect(&mut v, file_name), &redir_dst); - self.shared.fs.write(&redir_dst, &v)?; + let v = layout::redirect(file_name); + self.shared.fs.write(&redir_dst, v.as_bytes())?; } // If the item is a macro, redirect from the old macro URL (with !) // to the new one (without). if item_type == ItemType::Macro { let redir_name = format!("{}.{}!.html", item_type, name); let redir_dst = self.dst.join(redir_name); - let mut v = Vec::new(); - try_err!(layout::redirect(&mut v, file_name), &redir_dst); - self.shared.fs.write(&redir_dst, &v)?; + let v = layout::redirect(file_name); + self.shared.fs.write(&redir_dst, v.as_bytes())?; } } } @@ -2361,7 +2109,7 @@ impl Context { } } -impl<'a> Item<'a> { +impl Context { /// Generates a url appropriate for an `href` attribute back to the source of /// this item. /// @@ -2371,26 +2119,26 @@ impl<'a> Item<'a> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn src_href(&self) -> Option { - let mut root = self.cx.root_path(); + fn src_href(&self, item: &clean::Item) -> Option { + let mut root = self.root_path(); let cache = cache(); let mut path = String::new(); // We can safely ignore macros from other libraries - let file = match self.item.source.filename { + let file = match item.source.filename { FileName::Real(ref path) => path, _ => return None, }; - let (krate, path) = if self.item.def_id.is_local() { - if let Some(path) = self.cx.shared.local_sources.get(file) { - (&self.cx.shared.layout.krate, path) + let (krate, path) = if item.def_id.is_local() { + if let Some(path) = self.shared.local_sources.get(file) { + (&self.shared.layout.krate, path) } else { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&self.item.def_id.krate)? { + let (krate, src_root) = match *cache.extern_locations.get(&item.def_id.krate)? { (ref name, ref src, Local) => (name, src), (ref name, ref src, Remote(ref s)) => { root = s.to_string(); @@ -2399,7 +2147,7 @@ impl<'a> Item<'a> { (_, _, Unknown) => return None, }; - clean_srcpath(&src_root, file, false, |component| { + sources::clean_path(&src_root, file, false, |component| { path.push_str(&component.to_string_lossy()); path.push('/'); }); @@ -2410,10 +2158,10 @@ impl<'a> Item<'a> { (krate, &path) }; - let lines = if self.item.source.loline == self.item.source.hiline { - self.item.source.loline.to_string() + let lines = if item.source.loline == item.source.hiline { + item.source.loline.to_string() } else { - format!("{}-{}", self.item.source.loline, self.item.source.hiline) + format!("{}-{}", item.source.loline, item.source.hiline) }; Some(format!("{root}src/{krate}/{path}#{lines}", root = Escape(&root), @@ -2423,114 +2171,113 @@ impl<'a> Item<'a> { } } -fn wrap_into_docblock(w: &mut fmt::Formatter<'_>, - f: F) -> fmt::Result -where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { - write!(w, "
")?; - f(w)?; +fn wrap_into_docblock(w: &mut Buffer, f: F) + where F: FnOnce(&mut Buffer) +{ + write!(w, "
"); + f(w); write!(w, "
") } -impl<'a> fmt::Display for Item<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_assert!(!self.item.is_stripped()); - // Write the breadcrumb trail header for the top - write!(fmt, "

")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; - } - write!(fmt, - "\ - \ - []\ - \ - ")?; - - // Write `src` tag - // - // When this item is part of a `pub use` in a downstream crate, the - // [src] link in the downstream documentation will actually come back to - // this page, and this link will be auto-clicked. The `id` attribute is - // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; - } - } +fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { + debug_assert!(!item.is_stripped()); + // Write the breadcrumb trail header for the top + write!(buf, "

"); + if let Some(version) = item.stable_since() { + write!(buf, "{0}", + version); + } + write!(buf, + "\ + \ + []\ + \ + "); - write!(fmt, "")?; // out-of-band - write!(fmt, "")?; - match self.item.inner { - clean::ModuleItem(ref m) => if m.is_crate { - write!(fmt, "Crate ")?; - } else { - write!(fmt, "Module ")?; - }, - clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, - clean::TraitItem(..) => write!(fmt, "Trait ")?, - clean::StructItem(..) => write!(fmt, "Struct ")?, - clean::UnionItem(..) => write!(fmt, "Union ")?, - clean::EnumItem(..) => write!(fmt, "Enum ")?, - clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, - clean::MacroItem(..) => write!(fmt, "Macro ")?, - clean::ProcMacroItem(ref mac) => match mac.kind { - MacroKind::Bang => write!(fmt, "Macro ")?, - MacroKind::Attr => write!(fmt, "Attribute Macro ")?, - MacroKind::Derive => write!(fmt, "Derive Macro ")?, - } - clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, - clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, - clean::ConstantItem(..) => write!(fmt, "Constant ")?, - clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, - clean::KeywordItem(..) => write!(fmt, "Keyword ")?, - clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, - clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, - _ => { - // We don't generate pages for any other type. - unreachable!(); - } + // Write `src` tag + // + // When this item is part of a `pub use` in a downstream crate, the + // [src] link in the downstream documentation will actually come back to + // this page, and this link will be auto-clicked. The `id` attribute is + // used to find the link to auto-click. + if cx.shared.include_sources && !item.is_primitive() { + if let Some(l) = cx.src_href(item) { + write!(buf, "[src]", + l, "goto source code"); + } + } + + write!(buf, ""); // out-of-band + write!(buf, ""); + let name = match item.inner { + clean::ModuleItem(ref m) => if m.is_crate { + "Crate " + } else { + "Module " + }, + clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ", + clean::TraitItem(..) => "Trait ", + clean::StructItem(..) => "Struct ", + clean::UnionItem(..) => "Union ", + clean::EnumItem(..) => "Enum ", + clean::TypedefItem(..) => "Type Definition ", + clean::MacroItem(..) => "Macro ", + clean::ProcMacroItem(ref mac) => match mac.kind { + MacroKind::Bang => "Macro ", + MacroKind::Attr => "Attribute Macro ", + MacroKind::Derive => "Derive Macro ", + } + clean::PrimitiveItem(..) => "Primitive Type ", + clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ", + clean::ConstantItem(..) => "Constant ", + clean::ForeignTypeItem => "Foreign Type ", + clean::KeywordItem(..) => "Keyword ", + clean::OpaqueTyItem(..) => "Opaque Type ", + clean::TraitAliasItem(..) => "Trait Alias ", + _ => { + // We don't generate pages for any other type. + unreachable!(); } - if !self.item.is_primitive() && !self.item.is_keyword() { - let cur = &self.cx.current; - let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - write!(fmt, "{}::", - "../".repeat(cur.len() - i - 1), - component)?; - } + }; + buf.write_str(name); + if !item.is_primitive() && !item.is_keyword() { + let cur = &cx.current; + let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() }; + for (i, component) in cur.iter().enumerate().take(amt) { + write!(buf, "{}::", + "../".repeat(cur.len() - i - 1), + component); } - write!(fmt, "{}", - self.item.type_(), self.item.name.as_ref().unwrap())?; - - write!(fmt, "

")?; // in-band - - match self.item.inner { - clean::ModuleItem(ref m) => - item_module(fmt, self.cx, self.item, &m.items), - clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.cx, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), - clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), - clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.cx, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), - clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), - _ => { - // We don't generate pages for any other type. - unreachable!(); - } + } + write!(buf, "{}", + item.type_(), item.name.as_ref().unwrap()); + + write!(buf, "

"); // in-band + + match item.inner { + clean::ModuleItem(ref m) => + item_module(buf, cx, item, &m.items), + clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => + item_function(buf, cx, item, f), + clean::TraitItem(ref t) => item_trait(buf, cx, item, t), + clean::StructItem(ref s) => item_struct(buf, cx, item, s), + clean::UnionItem(ref s) => item_union(buf, cx, item, s), + clean::EnumItem(ref e) => item_enum(buf, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), + clean::MacroItem(ref m) => item_macro(buf, cx, item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), + clean::PrimitiveItem(ref p) => item_primitive(buf, cx, item, p), + clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => + item_static(buf, cx, item, i), + clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), + clean::ForeignTypeItem => item_foreign_type(buf, cx, item), + clean::KeywordItem(ref k) => item_keyword(buf, cx, item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), + _ => { + // We don't generate pages for any other type. + unreachable!(); } } } @@ -2549,48 +2296,58 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { s } -fn shorter(s: Option<&str>) -> String { - match s { - Some(s) => s.lines() - .skip_while(|s| s.chars().all(|c| c.is_whitespace())) - .take_while(|line|{ - (*line).chars().any(|chr|{ - !chr.is_whitespace() - }) - }).collect::>().join("\n"), - None => String::new() - } -} - #[inline] fn plain_summary_line(s: Option<&str>) -> String { - let line = shorter(s).replace("\n", " "); - markdown::plain_summary_line_full(&line[..], false) -} - -#[inline] -fn plain_summary_line_short(s: Option<&str>) -> String { - let line = shorter(s).replace("\n", " "); - markdown::plain_summary_line_full(&line[..], true) + let s = s.unwrap_or(""); + // This essentially gets the first paragraph of text in one line. + let mut line = s.lines() + .skip_while(|line| line.chars().all(|c| c.is_whitespace())) + .take_while(|line| line.chars().any(|c| !c.is_whitespace())) + .fold(String::new(), |mut acc, line| { + acc.push_str(line); + acc.push(' '); + acc + }); + // remove final whitespace + line.pop(); + markdown::plain_summary_line(&line[..]) +} + +fn shorten(s: String) -> String { + if s.chars().count() > 60 { + let mut len = 0; + let mut ret = s.split_whitespace() + .take_while(|p| { + // + 1 for the added character after the word. + len += p.chars().count() + 1; + len < 60 + }) + .collect::>() + .join(" "); + ret.push('…'); + ret + } else { + s + } } -fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt::Result { +fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) { if let Some(ref name) = item.name { info!("Documenting {}", name); } - document_stability(w, cx, item, false)?; - document_full(w, item, cx, "", false)?; - Ok(()) + document_stability(w, cx, item, false); + document_full(w, item, cx, "", false); } /// Render md_text as markdown. -fn render_markdown(w: &mut fmt::Formatter<'_>, - cx: &Context, - md_text: &str, - links: Vec<(String, String)>, - prefix: &str, - is_hidden: bool) - -> fmt::Result { +fn render_markdown( + w: &mut Buffer, + cx: &Context, + md_text: &str, + links: Vec<(String, String)>, + prefix: &str, + is_hidden: bool, +) { let mut ids = cx.id_map.borrow_mut(); write!(w, "
{}{}
", if is_hidden { " hidden" } else { "" }, @@ -2600,12 +2357,13 @@ fn render_markdown(w: &mut fmt::Formatter<'_>, } fn document_short( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, item: &clean::Item, link: AssocItemLink<'_>, - prefix: &str, is_hidden: bool -) -> fmt::Result { + prefix: &str, + is_hidden: bool, +) { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -2613,46 +2371,41 @@ fn document_short( } else { plain_summary_line(Some(s)) }; - render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
{}
", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_full(w: &mut fmt::Formatter<'_>, item: &clean::Item, - cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result { +fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, is_hidden: bool) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &*s, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
{}
", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_stability(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item, - is_hidden: bool) -> fmt::Result { +fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) { let stabilities = short_stability(item, cx); if !stabilities.is_empty() { - write!(w, "
", if is_hidden { " hidden" } else { "" })?; + write!(w, "
", if is_hidden { " hidden" } else { "" }); for stability in stabilities { - write!(w, "{}", stability)?; + write!(w, "{}", stability); } - write!(w, "
")?; + write!(w, "
"); } - Ok(()) } fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fmt::Result { +fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { if item.is_non_exhaustive() { write!(w, "
", { if item.is_struct() { @@ -2664,31 +2417,29 @@ fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fm } else { "type" } - })?; + }); if item.is_struct() { write!(w, "Non-exhaustive structs could have additional fields added in future. \ Therefore, non-exhaustive structs cannot be constructed in external crates \ using the traditional Struct {{ .. }} syntax; cannot be \ matched against without a wildcard ..; and \ - struct update syntax will not work.")?; + struct update syntax will not work."); } else if item.is_enum() { write!(w, "Non-exhaustive enums could have additional variants added in future. \ Therefore, when matching against variants of non-exhaustive enums, an \ - extra wildcard arm must be added to account for any future variants.")?; + extra wildcard arm must be added to account for any future variants."); } else if item.is_variant() { write!(w, "Non-exhaustive enum variants could have additional fields added in future. \ Therefore, non-exhaustive enum variants cannot be constructed in external \ - crates and cannot be matched against.")?; + crates and cannot be matched against."); } else { write!(w, "This type will require a wildcard arm in any match statements or \ - constructors.")?; + constructors."); } - write!(w, "
")?; + write!(w, "
"); } - - Ok(()) } fn name_key(name: &str) -> (&str, u64, usize) { @@ -2712,9 +2463,8 @@ fn name_key(name: &str) -> (&str, u64, usize) { } } -fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, - item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - document(w, cx, item)?; +fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { + document(w, cx, item); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -2805,38 +2555,38 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, curty = myty; } else if myty != curty { if curty.is_some() { - write!(w, "")?; + write!(w, ""); } curty = myty; let (short, name) = item_ty_to_strs(&myty.unwrap()); write!(w, "

\ {name}

\n", - id = cx.derive_id(short.to_owned()), name = name)?; + id = cx.derive_id(short.to_owned()), name = name); } match myitem.inner { clean::ExternCrateItem(ref name, ref src) => { - use crate::html::format::HRef; + use crate::html::format::anchor; match *src { Some(ref src) => { write!(w, "")?; + write!(w, ""); } clean::ImportItem(ref import) => { write!(w, "", - VisSpace(&myitem.visibility), *import)?; + VisSpace(&myitem.visibility), *import); } _ => { @@ -2881,15 +2631,14 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, }) .collect::>() .join(" "), - )?; + ); } } } if curty.is_some() { - write!(w, "
{}extern crate {} as {};", VisSpace(&myitem.visibility), - HRef::new(myitem.def_id, src), - name)? + anchor(myitem.def_id, src), + name) } None => { write!(w, "
{}extern crate {};", VisSpace(&myitem.visibility), - HRef::new(myitem.def_id, name))? + anchor(myitem.def_id, name)) } } - write!(w, "
{}{}
")?; + write!(w, ""); } - Ok(()) } /// Render the stability and deprecation tags that are displayed in the item's summary at the @@ -3038,33 +2787,30 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { stability } -fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - c: &clean::Constant) -> fmt::Result { - write!(w, "
")?;
-    render_attributes(w, it, false)?;
+fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) {
+    write!(w, "
");
+    render_attributes(w, it, false);
     write!(w, "{vis}const \
                {name}: {typ}
", vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), - typ = c.type_)?; + typ = c.type_); document(w, cx, it) } -fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - s: &clean::Static) -> fmt::Result { - write!(w, "
")?;
-    render_attributes(w, it, false)?;
+fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
+    write!(w, "
");
+    render_attributes(w, it, false);
     write!(w, "{vis}static {mutability}\
                {name}: {typ}
", vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), - typ = s.type_)?; + typ = s.type_); document(w, cx, it) } -fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - f: &clean::Function) -> fmt::Result { +fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) { let header_len = format!( "{}{}{}{}{:#}fn {}{:#}", VisSpace(&it.visibility), @@ -3075,8 +2821,8 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, it.name.as_ref().unwrap(), f.generics ).len(); - write!(w, "{}
", render_spotlight_traits(it)?)?;
-    render_attributes(w, it, false)?;
+    write!(w, "{}
", render_spotlight_traits(it));
+    render_attributes(w, it, false);
     write!(w,
            "{vis}{constness}{unsafety}{asyncness}{abi}fn \
            {name}{generics}{decl}{where_clause}
", @@ -3093,12 +2839,12 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, header_len, indent: 0, asyncness: f.header.asyncness, - })?; + }); document(w, cx, it) } -fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<'_>, - implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result { +fn render_implementor(cx: &Context, implementor: &Impl, w: &mut Buffer, + implementor_dups: &FxHashMap<&str, (DefId, bool)>) { // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -3110,20 +2856,18 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<' _ => false, }; render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?; - Ok(()) + implementor.impl_item.stable_since(), false, Some(use_absolute), false, false); } -fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>, +fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], - containing_item: &clean::Item) -> fmt::Result { + containing_item: &clean::Item) { for i in traits { let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); render_impl(w, cx, i, assoc_link, - RenderMode::Normal, containing_item.stable_since(), true, None, false, true)?; + RenderMode::Normal, containing_item.stable_since(), true, None, false, true); } - Ok(()) } fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { @@ -3151,11 +2895,11 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { } fn item_trait( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, -) -> fmt::Result { +) { let bounds = bounds(&t.bounds, false); let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); @@ -3164,146 +2908,144 @@ fn item_trait( // Output the trait definition wrap_into_docblock(w, |w| { - write!(w, "
")?;
-        render_attributes(w, it, true)?;
+        write!(w, "
");
+        render_attributes(w, it, true);
         write!(w, "{}{}{}trait {}{}{}",
                VisSpace(&it.visibility),
                UnsafetySpace(t.unsafety),
                if t.is_auto { "auto " } else { "" },
                it.name.as_ref().unwrap(),
                t.generics,
-               bounds)?;
+               bounds);
 
         if !t.generics.where_predicates.is_empty() {
-            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?;
+            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true });
         } else {
-            write!(w, " ")?;
+            write!(w, " ");
         }
 
         if t.items.is_empty() {
-            write!(w, "{{ }}")?;
+            write!(w, "{{ }}");
         } else {
             // FIXME: we should be using a derived_id for the Anchors here
-            write!(w, "{{\n")?;
+            write!(w, "{{\n");
             for t in &types {
-                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
             }
             if !types.is_empty() && !consts.is_empty() {
-                w.write_str("\n")?;
+                w.write_str("\n");
             }
             for t in &consts {
-                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
             }
             if !consts.is_empty() && !required.is_empty() {
-                w.write_str("\n")?;
+                w.write_str("\n");
             }
             for (pos, m) in required.iter().enumerate() {
-                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
 
                 if pos < required.len() - 1 {
-                   write!(w, "
")?; + write!(w, "
"); } } if !required.is_empty() && !provided.is_empty() { - w.write_str("\n")?; + w.write_str("\n"); } for (pos, m) in provided.iter().enumerate() { - render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; + render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait); match m.inner { clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { - write!(w, ",\n {{ ... }}\n")?; + write!(w, ",\n {{ ... }}\n"); }, _ => { - write!(w, " {{ ... }}\n")?; + write!(w, " {{ ... }}\n"); }, } if pos < provided.len() - 1 { - write!(w, "
")?; + write!(w, "
"); } } - write!(w, "}}")?; + write!(w, "}}"); } write!(w, "
") - })?; + }); // Trait documentation - document(w, cx, it)?; + document(w, cx, it); fn write_small_section_header( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, id: &str, title: &str, extra_content: &str, - ) -> fmt::Result { + ) { write!(w, "

\ {1}\

{2}", id, title, extra_content) } - fn write_loading_content(w: &mut fmt::Formatter<'_>, extra_content: &str) -> fmt::Result { + fn write_loading_content(w: &mut Buffer, extra_content: &str) { write!(w, "{}Loading content...", extra_content) } - fn trait_item(w: &mut fmt::Formatter<'_>, cx: &Context, m: &clean::Item, t: &clean::Item) - -> fmt::Result { + fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) { let name = m.name.as_ref().unwrap(); let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

{extra}", - extra = render_spotlight_traits(m)?, + extra = render_spotlight_traits(m), id = id, - ns_id = ns_id)?; - render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?; - write!(w, "")?; - render_stability_since(w, m, t)?; - write!(w, "

")?; - document(w, cx, m)?; - Ok(()) + ns_id = ns_id); + render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); + write!(w, ""); + render_stability_since(w, m, t); + write!(w, ""); + document(w, cx, m); } if !types.is_empty() { write_small_section_header(w, "associated-types", "Associated Types", - "
")?; + "
"); for t in &types { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); } if !consts.is_empty() { write_small_section_header(w, "associated-const", "Associated Constants", - "
")?; + "
"); for t in &consts { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); } // Output the documentation for each function individually if !required.is_empty() { write_small_section_header(w, "required-methods", "Required methods", - "
")?; + "
"); for m in &required { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); } if !provided.is_empty() { write_small_section_header(w, "provided-methods", "Provided methods", - "
")?; + "
"); for m in &provided { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?; + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); let cache = cache(); @@ -3342,7 +3084,7 @@ fn item_trait( concrete.sort_by(compare_impl); if !foreign.is_empty() { - write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?; + write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); for implementor in foreign { let assoc_link = AssocItemLink::GotoSource( @@ -3351,44 +3093,44 @@ fn item_trait( ); render_impl(w, cx, &implementor, assoc_link, RenderMode::Normal, implementor.impl_item.stable_since(), false, - None, true, false)?; + None, true, false); } - write_loading_content(w, "")?; + write_loading_content(w, ""); } write_small_section_header(w, "implementors", "Implementors", - "
")?; + "
"); for implementor in concrete { - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
")?; + "
"); for implementor in synthetic { synthetic_types.extend( collect_paths_for_type(implementor.inner_impl().for_.clone()) ); - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
")?; + write_loading_content(w, "
"); } } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into write_small_section_header(w, "implementors", "Implementors", - "
")?; - write_loading_content(w, "
")?; + "
"); + write_loading_content(w, "
"); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
")?; - write_loading_content(w, "
")?; + "
"); + write_loading_content(w, "
"); } } write!(w, r#""#, - as_json(&synthetic_types))?; + as_json(&synthetic_types)); write!(w, r#"", - name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = it.type_().css_class(), - path = relpath)?; - if parentlen == 0 { - // There is no sidebar-items.js beyond the crate root path - // FIXME maybe dynamic crate loading can be merged here - } else { - write!(fmt, "", - path = relpath)?; - } - // Closes sidebar-elems div. - write!(fmt, "")?; - - Ok(()) + _ => "", + }, + it.name.as_ref().unwrap()); + } + + if it.is_crate() { + if let Some(ref version) = cache().crate_version { + write!(buffer, + "
\ +

Version {}

\ +
", + version); + } + } + + write!(buffer, "
"); + if it.is_crate() { + write!(buffer, "

See all {}'s items

", + it.name.as_ref().expect("crates always have a name")); + } + match it.inner { + clean::StructItem(ref s) => sidebar_struct(buffer, it, s), + clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), + clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::UnionItem(ref u) => sidebar_union(buffer, it, u), + clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), + clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), + clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), + _ => (), + } + + // The sidebar is designed to display sibling functions, modules and + // other miscellaneous information. since there are lots of sibling + // items (and that causes quadratic growth in large modules), + // we refactor common parts into a shared JavaScript file per module. + // still, we don't move everything into JS because we want to preserve + // as much HTML as possible in order to allow non-JS-enabled browsers + // to navigate the documentation (though slightly inefficiently). + + write!(buffer, "

"); + for (i, name) in cx.current.iter().take(parentlen).enumerate() { + if i > 0 { + write!(buffer, "::"); + } + write!(buffer, "{}", + &cx.root_path()[..(cx.current.len() - i - 1) * 3], + *name); + } + write!(buffer, "

"); + + // Sidebar refers to the enclosing module, not this module. + let relpath = if it.is_mod() { "../" } else { "" }; + write!(buffer, + "", + name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), + ty = it.type_().css_class(), + path = relpath); + if parentlen == 0 { + // There is no sidebar-items.js beyond the crate root path + // FIXME maybe dynamic crate loading can be merged here + } else { + write!(buffer, "", + path = relpath); } + // Closes sidebar-elems div. + write!(buffer, "
"); } fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { @@ -4746,8 +4452,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { out } -fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - s: &clean::Struct) -> fmt::Result { +fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&s.fields); @@ -4761,9 +4466,8 @@ fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String { @@ -4787,8 +4491,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool { i.polarity == Some(clean::ImplPolarity::Negative) } -fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - t: &clean::Trait) -> fmt::Result { +fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { let mut sidebar = String::new(); let types = t.items @@ -4896,27 +4599,23 @@ fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); - write!(fmt, "
{}
", sidebar) + write!(buf, "
{}
", sidebar) } -fn sidebar_primitive(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _p: &clean::PrimitiveType) -> fmt::Result { +fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveType) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_typedef(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _t: &clean::Typedef) -> fmt::Result { +fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item, _t: &clean::Typedef) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_struct_fields_name(fields: &[clean::Item]) -> String { @@ -4934,8 +4633,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String { .collect() } -fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - u: &clean::Union) -> fmt::Result { +fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&u.fields); @@ -4947,13 +4645,11 @@ fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - e: &clean::Enum) -> fmt::Result { +fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) { let mut sidebar = String::new(); let variants = e.variants.iter() @@ -4971,9 +4667,8 @@ fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { @@ -5007,8 +4702,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { } } -fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, - items: &[clean::Item]) -> fmt::Result { +fn sidebar_module(buf: &mut Buffer, _it: &clean::Item, items: &[clean::Item]) { let mut sidebar = String::new(); if items.iter().any(|it| it.type_() == ItemType::ExternCrate || @@ -5035,97 +4729,71 @@ fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, } if !sidebar.is_empty() { - write!(fmt, "
    {}
", sidebar)?; + write!(buf, "
    {}
", sidebar); } - Ok(()) } -fn sidebar_foreign_type(fmt: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result { +fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -impl<'a> fmt::Display for Source<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; - let lines = s.lines().count(); - let mut cols = 0; - let mut tmp = lines; - while tmp > 0 { - cols += 1; - tmp /= 10; - } - write!(fmt, "
")?;
-        for i in 1..=lines {
-            write!(fmt, "{0:1$}\n", i, cols)?;
-        }
-        write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) - } -} - -fn item_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - t: &clean::Macro) -> fmt::Result { +fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) { wrap_into_docblock(w, |w| { w.write_str(&highlight::render_with_highlighting(&t.source, Some("macro"), None, None)) - })?; + }); document(w, cx, it) } -fn item_proc_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) - -> fmt::Result -{ +fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) { let name = it.name.as_ref().expect("proc-macros always have names"); match m.kind { MacroKind::Bang => { - write!(w, "
")?;
-            write!(w, "{}!() {{ /* proc-macro */ }}", name)?;
-            write!(w, "
")?; + write!(w, "
");
+            write!(w, "{}!() {{ /* proc-macro */ }}", name);
+            write!(w, "
"); } MacroKind::Attr => { - write!(w, "
")?;
-            write!(w, "#[{}]", name)?;
-            write!(w, "
")?; + write!(w, "
");
+            write!(w, "#[{}]", name);
+            write!(w, "
"); } MacroKind::Derive => { - write!(w, "
")?;
-            write!(w, "#[derive({})]", name)?;
+            write!(w, "
");
+            write!(w, "#[derive({})]", name);
             if !m.helpers.is_empty() {
-                writeln!(w, "\n{{")?;
-                writeln!(w, "    // Attributes available to this derive:")?;
+                writeln!(w, "\n{{");
+                writeln!(w, "    // Attributes available to this derive:");
                 for attr in &m.helpers {
-                    writeln!(w, "    #[{}]", attr)?;
+                    writeln!(w, "    #[{}]", attr);
                 }
-                write!(w, "}}")?;
+                write!(w, "}}");
             }
-            write!(w, "
")?; + write!(w, "
"); } } document(w, cx, it) } -fn item_primitive(w: &mut fmt::Formatter<'_>, cx: &Context, +fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, - _p: &clean::PrimitiveType) -> fmt::Result { - document(w, cx, it)?; + _p: &clean::PrimitiveType) { + document(w, cx, it); render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn item_keyword(w: &mut fmt::Formatter<'_>, cx: &Context, +fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item, - _p: &str) -> fmt::Result { + _p: &str) { document(w, cx, it) } -const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; +crate const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs new file mode 100644 index 0000000000..d840683a7a --- /dev/null +++ b/src/librustdoc/html/sources.rs @@ -0,0 +1,175 @@ +use crate::clean; +use crate::docfs::PathError; +use crate::fold::DocFolder; +use crate::html::layout; +use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS}; +use crate::html::highlight; +use crate::html::format::Buffer; +use std::ffi::OsStr; +use std::fs; +use std::path::{Component, Path, PathBuf}; +use syntax::source_map::FileName; + +crate fn render(dst: &Path, scx: &mut SharedContext, + krate: clean::Crate) -> Result { + info!("emitting source files"); + let dst = dst.join("src").join(&krate.name); + scx.ensure_dir(&dst)?; + let mut folder = SourceCollector { + dst, + scx, + }; + Ok(folder.fold_crate(krate)) +} + +/// Helper struct to render all source code to HTML pages +struct SourceCollector<'a> { + scx: &'a mut SharedContext, + + /// Root destination to place all HTML output into + dst: PathBuf, +} + +impl<'a> DocFolder for SourceCollector<'a> { + fn fold_item(&mut self, item: clean::Item) -> Option { + // If we're including source files, and we haven't seen this file yet, + // then we need to render it out to the filesystem. + if self.scx.include_sources + // skip all invalid or macro spans + && item.source.filename.is_real() + // skip non-local items + && item.def_id.is_local() { + + // If it turns out that we couldn't read this file, then we probably + // can't read any of the files (generating html output from json or + // something like that), so just don't include sources for the + // entire crate. The other option is maintaining this mapping on a + // per-file basis, but that's probably not worth it... + self.scx + .include_sources = match self.emit_source(&item.source.filename) { + Ok(()) => true, + Err(e) => { + println!("warning: source code was requested to be rendered, \ + but processing `{}` had an error: {}", + item.source.filename, e); + println!(" skipping rendering of source code"); + false + } + }; + } + self.fold_item_recur(item) + } +} + +impl<'a> SourceCollector<'a> { + /// Renders the given filename into its corresponding HTML source file. + fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> { + let p = match *filename { + FileName::Real(ref file) => file, + _ => return Ok(()), + }; + if self.scx.local_sources.contains_key(&**p) { + // We've already emitted this source + return Ok(()); + } + + let contents = match fs::read_to_string(&p) { + Ok(contents) => contents, + Err(e) => { + return Err(Error::new(e, &p)); + } + }; + + // Remove the utf-8 BOM if any + let contents = if contents.starts_with("\u{feff}") { + &contents[3..] + } else { + &contents[..] + }; + + // Create the intermediate directories + let mut cur = self.dst.clone(); + let mut root_path = String::from("../../"); + let mut href = String::new(); + clean_path(&self.scx.src_root, &p, false, |component| { + cur.push(component); + root_path.push_str("../"); + href.push_str(&component.to_string_lossy()); + href.push('/'); + }); + self.scx.ensure_dir(&cur)?; + let mut fname = p.file_name() + .expect("source has no filename") + .to_os_string(); + fname.push(".html"); + cur.push(&fname); + href.push_str(&fname.to_string_lossy()); + + let title = format!("{} -- source", cur.file_name().expect("failed to get file name") + .to_string_lossy()); + let desc = format!("Source to the Rust file `{}`.", filename); + let page = layout::Page { + title: &title, + css_class: "source", + root_path: &root_path, + static_root_path: self.scx.static_root_path.as_deref(), + description: &desc, + keywords: BASIC_KEYWORDS, + resource_suffix: &self.scx.resource_suffix, + extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)], + static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], + }; + let v = layout::render(&self.scx.layout, + &page, "", |buf: &mut _| print_src(buf, &contents), + &self.scx.themes); + self.scx.fs.write(&cur, v.as_bytes())?; + self.scx.local_sources.insert(p.clone(), href); + Ok(()) + } +} + +/// Takes a path to a source file and cleans the path to it. This canonicalizes +/// things like ".." to components which preserve the "top down" hierarchy of a +/// static HTML tree. Each component in the cleaned path will be passed as an +/// argument to `f`. The very last component of the path (ie the file name) will +/// be passed to `f` if `keep_filename` is true, and ignored otherwise. +pub fn clean_path(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) +where + F: FnMut(&OsStr), +{ + // make it relative, if possible + let p = p.strip_prefix(src_root).unwrap_or(p); + + let mut iter = p.components().peekable(); + + while let Some(c) = iter.next() { + if !keep_filename && iter.peek().is_none() { + break; + } + + match c { + Component::ParentDir => f("up".as_ref()), + Component::Normal(c) => f(c), + _ => continue, + } + } +} + +/// Wrapper struct to render the source code of a file. This will do things like +/// adding line numbers to the left-hand side. +fn print_src(buf: &mut Buffer, s: &str) { + let lines = s.lines().count(); + let mut cols = 0; + let mut tmp = lines; + while tmp > 0 { + cols += 1; + tmp /= 10; + } + write!(buf, "
");
+    for i in 1..=lines {
+        write!(buf, "{0:1$}\n", i, cols);
+    }
+    write!(buf, "
"); + write!(buf, "{}", + highlight::render_with_highlighting(s, None, None, None)); +} diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 82d2c11b24..17a940cc4c 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -3,7 +3,7 @@ // Local js definitions: /* global addClass, getCurrentValue, hasClass */ -/* global isHidden onEach, removeClass, updateLocalStorage */ +/* global isHidden, onEach, removeClass, updateLocalStorage */ if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { @@ -39,6 +39,14 @@ if (!DOMTokenList.prototype.remove) { }; } +function getSearchInput() { + return document.getElementsByClassName("search-input")[0]; +} + +function getSearchElement() { + return document.getElementById("search"); +} + (function() { "use strict"; @@ -71,7 +79,7 @@ if (!DOMTokenList.prototype.remove) { "derive", "traitalias"]; - var search_input = document.getElementsByClassName("search-input")[0]; + var search_input = getSearchInput(); // On the search screen, so you remain on the last tab you opened. // @@ -105,9 +113,9 @@ if (!DOMTokenList.prototype.remove) { sidebar.appendChild(div); } } - var themePicker = document.getElementsByClassName("theme-picker"); - if (themePicker && themePicker.length > 0) { - themePicker[0].style.display = "none"; + var themePickers = document.getElementsByClassName("theme-picker"); + if (themePickers && themePickers.length > 0) { + themePickers[0].style.display = "none"; } } @@ -123,9 +131,9 @@ if (!DOMTokenList.prototype.remove) { filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ""; - var themePicker = document.getElementsByClassName("theme-picker"); - if (themePicker && themePicker.length > 0) { - themePicker[0].style.display = null; + var themePickers = document.getElementsByClassName("theme-picker"); + if (themePickers && themePickers.length > 0) { + themePickers[0].style.display = null; } } @@ -158,7 +166,7 @@ if (!DOMTokenList.prototype.remove) { // If we're in mobile mode, we should add the sidebar in any case. hideSidebar(); var elem; - var search = document.getElementById("search"); + var search = getSearchElement(); var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { from = parseInt(match[1], 10); @@ -250,7 +258,12 @@ if (!DOMTokenList.prototype.remove) { return String.fromCharCode(c); } + function getHelpElement() { + return document.getElementById("help"); + } + function displayHelp(display, ev, help) { + var help = help ? help : getHelpElement(); if (display === true) { if (hasClass(help, "hidden")) { ev.preventDefault(); @@ -264,9 +277,10 @@ if (!DOMTokenList.prototype.remove) { } } - function handleEscape(ev, help) { + function handleEscape(ev) { + var help = getHelpElement(); + var search = getSearchElement(); hideModal(); - var search = document.getElementById("search"); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { @@ -284,22 +298,21 @@ if (!DOMTokenList.prototype.remove) { return; } - var help = document.getElementById("help"); if (document.activeElement.tagName === "INPUT") { switch (getVirtualKey(ev)) { case "Escape": - handleEscape(ev, help); + handleEscape(ev); break; } } else { switch (getVirtualKey(ev)) { case "Escape": - handleEscape(ev, help); + handleEscape(ev); break; case "s": case "S": - displayHelp(false, ev, help); + displayHelp(false, ev); hideModal(); ev.preventDefault(); focusSearchBar(); @@ -314,7 +327,7 @@ if (!DOMTokenList.prototype.remove) { case "?": if (ev.shiftKey) { hideModal(); - displayHelp(true, ev, help); + displayHelp(true, ev); } break; } @@ -344,7 +357,7 @@ if (!DOMTokenList.prototype.remove) { var set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, "#" + name); - window.hashchange(); + highlightSourceLines(null); } else { location.replace("#" + name); } @@ -445,6 +458,21 @@ if (!DOMTokenList.prototype.remove) { var OUTPUT_DATA = 1; var params = getQueryStringParams(); + // Set the crate filter from saved storage, if the current page has the saved crate filter. + // + // If not, ignore the crate filter -- we want to support filtering for crates on sites like + // doc.rust-lang.org where the crates may differ from page to page while on the same domain. + var savedCrate = getCurrentValue("rustdoc-saved-filter-crate"); + if (savedCrate !== null) { + onEachLazy(document.getElementById("crate-search").getElementsByTagName("option"), + function(e) { + if (e.value === savedCrate) { + document.getElementById("crate-search").value = e.value; + return true; + } + }); + } + // Populate search bar with query string search term when provided, // but only if the input bar is empty. This avoid the obnoxious issue // where you start trying to do a search, and the index loads, and @@ -532,6 +560,11 @@ if (!DOMTokenList.prototype.remove) { results.sort(function(aaa, bbb) { var a, b; + // sort by exact match with regard to the last word (mismatch goes later) + a = (aaa.word !== val); + b = (bbb.word !== val); + if (a !== b) { return a - b; } + // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) a = (aaa.lev); @@ -543,11 +576,6 @@ if (!DOMTokenList.prototype.remove) { b = (bbb.item.crate !== window.currentCrate); if (a !== b) { return a - b; } - // sort by exact match (mismatch goes later) - a = (aaa.word !== valLower); - b = (bbb.word !== valLower); - if (a !== b) { return a - b; } - // sort by item name length (longer goes later) a = aaa.word.length; b = bbb.word.length; @@ -1013,7 +1041,7 @@ if (!DOMTokenList.prototype.remove) { if (lev > MAX_LEV_DISTANCE) { continue; } else if (lev > 0) { - lev_add = 1; + lev_add = lev / 10; } } @@ -1084,10 +1112,6 @@ if (!DOMTokenList.prototype.remove) { if (index !== -1 || lev <= MAX_LEV_DISTANCE) { if (index !== -1 && paths.length < 2) { lev = 0; - } else if (searchWords[j] === val) { - // Small trick to fix when you're looking for a one letter type - // and there are other short named types. - lev = -1; } if (results[fullId] === undefined) { results[fullId] = { @@ -1270,9 +1294,7 @@ if (!DOMTokenList.prototype.remove) { } else if (e.which === 16) { // shift // Does nothing, it's just to avoid losing "focus" on the highlighted element. } else if (e.which === 27) { // escape - removeClass(actives[currentTab][0], "highlighted"); - search_input.value = ""; - defocusSearchBar(); + handleEscape(e); } else if (actives[currentTab].length > 0) { removeClass(actives[currentTab][0], "highlighted"); } @@ -1423,7 +1445,7 @@ if (!DOMTokenList.prototype.remove) { ret_others[0] + ret_in_args[0] + ret_returned[0] + ""; addClass(main, "hidden"); - var search = document.getElementById("search"); + var search = getSearchElement(); removeClass(search, "hidden"); search.innerHTML = output; var tds = search.getElementsByTagName("td"); @@ -1633,7 +1655,7 @@ if (!DOMTokenList.prototype.remove) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + var search_c = getSearchElement(); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -1658,9 +1680,10 @@ if (!DOMTokenList.prototype.remove) { }; search_input.onpaste = search_input.onchange; - var selectCrate = document.getElementById('crate-search'); + var selectCrate = document.getElementById("crate-search"); if (selectCrate) { selectCrate.onchange = function() { + updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value); search(undefined, true); }; } @@ -1679,7 +1702,7 @@ if (!DOMTokenList.prototype.remove) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + var search_c = getSearchElement(); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -2448,7 +2471,7 @@ if (!DOMTokenList.prototype.remove) { var params = getQueryStringParams(); if (params && params.search) { addClass(main, "hidden"); - var search = document.getElementById("search"); + var search = getSearchElement(); removeClass(search, "hidden"); search.innerHTML = "

Loading search results...

"; } @@ -2496,7 +2519,7 @@ if (!DOMTokenList.prototype.remove) { } function addSearchOptions(crates) { - var elem = document.getElementById('crate-search'); + var elem = document.getElementById("crate-search"); if (!elem) { return; @@ -2533,10 +2556,10 @@ if (!DOMTokenList.prototype.remove) { // Sets the focus on the search bar at the top of the page function focusSearchBar() { - document.getElementsByClassName("search-input")[0].focus(); + getSearchInput().focus(); } // Removes the focus from the search bar function defocusSearchBar() { - document.getElementsByClassName("search-input")[0].blur(); + getSearchInput().blur(); } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 59d10668f1..244b24af43 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -54,6 +54,21 @@ box-sizing: border-box; } +/* This part handles the "default" theme being used depending on the system one. */ +html { + content: ""; +} +@media (prefers-color-scheme: light) { + html { + content: "light"; + } +} +@media (prefers-color-scheme: dark) { + html { + content: "dark"; + } +} + /* General structure and fonts */ body { diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index e3927350d1..eae998ca3e 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -57,7 +57,7 @@ function onEachLazy(lazyArray, func, reversed) { function usableLocalStorage() { // Check if the browser supports localStorage at all: - if (typeof(Storage) === "undefined") { + if (typeof Storage === "undefined") { return false; } // Check if we can access it; this access will fail if the browser @@ -86,7 +86,7 @@ function getCurrentValue(name) { return null; } -function switchTheme(styleElem, mainStyleElem, newTheme) { +function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; var fullNewTheme = newTheme + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); @@ -109,8 +109,19 @@ function switchTheme(styleElem, mainStyleElem, newTheme) { }); if (found === true) { styleElem.href = newHref; - updateLocalStorage("rustdoc-theme", newTheme); + // If this new value comes from a system setting or from the previously saved theme, no + // need to save it. + if (saveTheme === true) { + updateLocalStorage("rustdoc-theme", newTheme); + } } } -switchTheme(currentTheme, mainTheme, getCurrentValue("rustdoc-theme") || "light"); +function getSystemValue() { + var property = getComputedStyle(document.documentElement).getPropertyValue('content'); + return property.replace(/[\"\']/g, ""); +} + +switchTheme(currentTheme, mainTheme, + getCurrentValue("rustdoc-theme") || getSystemValue() || "light", + false); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e30b35937d..0b9e717221 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(rustc_private)] #![feature(arbitrary_self_types)] #![feature(box_patterns)] @@ -33,6 +33,7 @@ extern crate rustc_interface; extern crate rustc_metadata; extern crate rustc_target; extern crate rustc_typeck; +extern crate rustc_lexer; extern crate serialize; extern crate syntax; extern crate syntax_pos; @@ -46,7 +47,7 @@ use std::panic; use std::process; use rustc::session::{early_warn, early_error}; -use rustc::session::config::{ErrorOutputType, RustcOptGroup}; +use rustc::session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; #[macro_use] mod externalfiles; @@ -67,6 +68,7 @@ pub mod html { crate mod render; crate mod static_files; crate mod toc; + crate mod sources; } mod markdown; mod passes; @@ -88,7 +90,7 @@ pub fn main() { 32_000_000 // 32MB on other platforms }; rustc_driver::set_sigpipe_handler(); - env_logger::init(); + env_logger::init_from_env("RUSTDOC_LOG"); let res = std::thread::Builder::new().stack_size(thread_stack_size).spawn(move || { get_args().map(|args| main_args(&args)).unwrap_or(1) }).unwrap().join().unwrap_or(rustc_driver::EXIT_FAILURE); @@ -132,6 +134,7 @@ fn opts() -> Vec { stable("crate-name", |o| { o.optopt("", "crate-name", "specify the name of this crate", "NAME") }), + make_crate_type_option(), stable("L", |o| { o.optmulti("L", "library-path", "directory to add to crate search path", "DIR") @@ -240,9 +243,6 @@ fn opts() -> Vec { unstable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") }), - unstable("linker", |o| { - o.optopt("", "linker", "linker used for building executable test code", "PATH") - }), unstable("sort-modules-by-appearance", |o| { o.optflag("", "sort-modules-by-appearance", "sort modules by where they appear in the \ program, rather than alphabetically") @@ -356,6 +356,28 @@ fn opts() -> Vec { "show-coverage", "calculate percentage of public items with documentation") }), + unstable("enable-per-target-ignores", |o| { + o.optflag("", + "enable-per-target-ignores", + "parse ignore-foo for ignoring doctests on a per-target basis") + }), + unstable("runtool", |o| { + o.optopt("", + "runtool", + "", + "The tool to run tests with when building for a different target than host") + }), + unstable("runtool-arg", |o| { + o.optmulti("", + "runtool-arg", + "", + "One (of possibly many) arguments to pass to the runtool") + }), + unstable("test-builder", |o| { + o.optflag("", + "test-builder", + "specified the rustc-like binary to use as the test builder") + }), ] } @@ -451,7 +473,7 @@ where R: 'static + Send, // First, parse the crate and extract all relevant information. info!("starting to run rustc"); - let result = rustc_driver::report_ices_to_stderr_if_any(move || { + let result = rustc_driver::catch_fatal_errors(move || { let crate_name = options.crate_name.clone(); let crate_version = options.crate_version.clone(); let (mut krate, renderinfo, renderopts) = core::run_core(options); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index eaaae3261c..8431271e62 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -43,7 +43,7 @@ pub fn render( edition: Edition ) -> i32 { let mut output = options.output; - output.push(input.file_stem().unwrap()); + output.push(input.file_name().unwrap()); output.set_extension("html"); let mut css = String::new(); @@ -142,18 +142,16 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 { let mut opts = TestOptions::default(); opts.no_crate_inject = true; opts.display_warnings = options.display_warnings; - let mut collector = Collector::new(options.input.display().to_string(), options.cfgs, - options.libs, options.codegen_options, options.externs, - true, opts, options.maybe_sysroot, None, - Some(options.input), - options.linker, options.edition, options.persist_doctests); + let mut collector = Collector::new(options.input.display().to_string(), options.clone(), + true, opts, None, Some(options.input), + options.enable_per_target_ignores); collector.set_position(DUMMY_SP); let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); - find_testable_code(&input_str, &mut collector, codes); + find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores); options.test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&options.test_args, collector.tests, - testing::Options::new().display_output(options.display_warnings)); + Some(testing::Options::new().display_output(options.display_warnings))); 0 } diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 67aa014a78..32044e48b6 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -32,27 +32,39 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { dox[code_block.code].to_owned(), ); - let has_errors = { - let mut has_errors = false; + let validation_status = { + let mut has_syntax_errors = false; + let mut only_whitespace = true; + // even if there is a syntax error, we need to run the lexer over the whole file let mut lexer = Lexer::new(&sess, source_file, None); loop { match lexer.next_token().kind { token::Eof => break, - token::Unknown(..) => has_errors = true, - _ => (), + token::Whitespace => (), + token::Unknown(..) => has_syntax_errors = true, + _ => only_whitespace = false, } } - has_errors + + if has_syntax_errors { + Some(CodeBlockInvalid::SyntaxError) + } else if only_whitespace { + Some(CodeBlockInvalid::Empty) + } else { + None + } }; - if has_errors { + if let Some(code_block_invalid) = validation_status { let mut diag = if let Some(sp) = super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs) { - let mut diag = self - .cx - .sess() - .struct_span_warn(sp, "could not parse code block as Rust code"); + let warning_message = match code_block_invalid { + CodeBlockInvalid::SyntaxError => "could not parse code block as Rust code", + CodeBlockInvalid::Empty => "Rust code block is empty", + }; + + let mut diag = self.cx.sess().struct_span_warn(sp, warning_message); if code_block.syntax.is_none() && code_block.is_fenced { let sp = sp.from_inner(InnerSpan::new(0, 3)); @@ -96,3 +108,8 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { self.fold_item_recur(item) } } + +enum CodeBlockInvalid { + SyntaxError, + Empty, +} diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7f4a17225e..d6073cdc1e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -4,6 +4,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint as lint; use rustc::ty; +use rustc_resolve::ParentScope; use syntax; use syntax::ast::{self, Ident}; use syntax::ext::base::SyntaxExtensionKind; @@ -431,7 +432,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { let path = ast::Path::from_ident(Ident::from_str(path_str)); cx.enter_resolver(|resolver| { if let Ok((Some(ext), res)) = resolver.resolve_macro_path( - &path, None, &resolver.dummy_parent_scope(), false, false + &path, None, &ParentScope::module(resolver.graph_root), false, false ) { if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind { return Some(res.map_id(|_| panic!("unexpected id"))); @@ -678,6 +679,7 @@ fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option { "f32" => tcx.lang_items().f32_impl(), "f64" => tcx.lang_items().f64_impl(), "str" => tcx.lang_items().str_impl(), + "bool" => tcx.lang_items().bool_impl(), "char" => tcx.lang_items().char_impl(), _ => None, } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 86e4e9fd95..28c64d0b96 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -53,6 +53,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { lang_items.f64_impl(), lang_items.f32_runtime_impl(), lang_items.f64_runtime_impl(), + lang_items.bool_impl(), lang_items.char_impl(), lang_items.str_impl(), lang_items.slice_impl(), diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 49a34c7e46..14f8b16dc3 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -336,7 +336,7 @@ pub fn look_for_tests<'tcx>( found_tests: 0, }; - find_testable_code(&dox, &mut tests, ErrorCodes::No); + find_testable_code(&dox, &mut tests, ErrorCodes::No, false); if check_missing_code == true && tests.found_tests == 0 { let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 462e21b8f6..424239c998 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -1,11 +1,9 @@ use rustc_data_structures::sync::Lrc; use rustc_interface::interface; +use rustc_target::spec::TargetTriple; use rustc::hir; use rustc::hir::intravisit; -use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::{self, config, DiagnosticOutput}; -use rustc::session::config::{OutputType, OutputTypes, Externs, CodegenOptions}; -use rustc::session::search_paths::SearchPath; use rustc::util::common::ErrorReported; use syntax::ast; use syntax::with_globals; @@ -13,13 +11,11 @@ use syntax::source_map::SourceMap; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; use std::env; -use std::io::prelude::*; -use std::io; -use std::panic::{self, AssertUnwindSafe}; +use std::io::{self, Write}; +use std::panic; use std::path::PathBuf; -use std::process::{self, Command}; +use std::process::{self, Command, Stdio}; use std::str; -use std::sync::{Arc, Mutex}; use syntax::symbol::sym; use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; use tempfile::Builder as TempFileBuilder; @@ -27,7 +23,7 @@ use testing; use crate::clean::Attributes; use crate::config::Options; -use crate::html::markdown::{self, ErrorCodes, LangString}; +use crate::html::markdown::{self, ErrorCodes, LangString, Ignore}; #[derive(Clone, Default)] pub struct TestOptions { @@ -43,10 +39,16 @@ pub struct TestOptions { pub fn run(options: Options) -> i32 { let input = config::Input::File(options.input.clone()); + let crate_types = if options.proc_macro_crate { + vec![config::CrateType::ProcMacro] + } else { + vec![config::CrateType::Dylib] + }; + let sessopts = config::Options { maybe_sysroot: options.maybe_sysroot.clone(), search_paths: options.libs.clone(), - crate_types: vec![config::CrateType::Dylib], + crate_types, cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: UnstableFeatures::from_environment(), @@ -56,6 +58,7 @@ pub fn run(options: Options) -> i32 { ..config::basic_debugging_options() }, edition: options.edition, + target_triple: options.target.clone(), ..config::Options::default() }; @@ -81,20 +84,15 @@ pub fn run(options: Options) -> i32 { let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); opts.display_warnings |= options.display_warnings; + let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( compiler.crate_name()?.peek().to_string(), - options.cfgs, - options.libs, - options.codegen_options, - options.externs, + options, false, opts, - options.maybe_sysroot, Some(compiler.source_map().clone()), None, - options.linker, - options.edition, - options.persist_doctests, + enable_per_target_ignores, ); let mut global_ctxt = compiler.global_ctxt()?.take(); @@ -120,7 +118,7 @@ pub fn run(options: Options) -> i32 { testing::test_main( &test_args, tests, - testing::Options::new().display_output(display_warnings) + Some(testing::Options::new().display_output(display_warnings)) ); 0 @@ -183,20 +181,17 @@ fn run_test( cratename: &str, filename: &FileName, line: usize, - cfgs: Vec, - libs: Vec, - cg: CodegenOptions, - externs: Externs, + options: Options, should_panic: bool, no_run: bool, as_test_harness: bool, + runtool: Option, + runtool_args: Vec, + target: TargetTriple, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option, - linker: Option, edition: Edition, - persist_doctests: Option, ) -> Result<(), TestFailure> { let (test, line_offset) = match panic::catch_unwind(|| { make_test(test, Some(cratename), as_test_harness, opts, edition) @@ -217,61 +212,6 @@ fn run_test( _ => PathBuf::from(r"doctest.rs"), }; - let input = config::Input::Str { - name: FileName::DocTest(path, line as isize - line_offset as isize), - input: test, - }; - let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); - - let sessopts = config::Options { - maybe_sysroot, - search_paths: libs, - crate_types: vec![config::CrateType::Executable], - output_types: outputs, - externs, - cg: config::CodegenOptions { - linker, - ..cg - }, - test: as_test_harness, - unstable_features: UnstableFeatures::from_environment(), - debugging_opts: config::DebuggingOptions { - ..config::basic_debugging_options() - }, - edition, - ..config::Options::default() - }; - - // Shuffle around a few input and output handles here. We're going to pass - // an explicit handle into rustc to collect output messages, but we also - // want to catch the error message that rustc prints when it fails. - // - // We take our thread-local stderr (likely set by the test runner) and replace - // it with a sink that is also passed to rustc itself. When this function - // returns the output of the sink is copied onto the output of our own thread. - // - // The basic idea is to not use a default Handler for rustc, and then also - // not print things by default to the actual stderr. - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } - } - struct Bomb(Arc>>, Option>); - impl Drop for Bomb { - fn drop(&mut self) { - let mut old = self.1.take().unwrap(); - let _ = old.write_all(&self.0.lock().unwrap()); - io::set_panic(Some(old)); - } - } - let data = Arc::new(Mutex::new(Vec::new())); - - let old = io::set_panic(Some(box Sink(data.clone()))); - let _bomb = Bomb(data.clone(), Some(old.unwrap_or(box io::stdout()))); - enum DirState { Temp(tempfile::TempDir), Perm(PathBuf), @@ -286,7 +226,7 @@ fn run_test( } } - let outdir = if let Some(mut path) = persist_doctests { + let outdir = if let Some(mut path) = options.persist_doctests { path.push(format!("{}_{}", filename .to_string() @@ -308,41 +248,67 @@ fn run_test( }; let output_file = outdir.path().join("rust_out"); - let config = interface::Config { - opts: sessopts, - crate_cfg: config::parse_cfgspecs(cfgs), - input, - input_path: None, - output_file: Some(output_file.clone()), - output_dir: None, - file_loader: None, - diagnostic_output: DiagnosticOutput::Raw(box Sink(data.clone())), - stderr: Some(data.clone()), - crate_name: None, - lint_caps: Default::default(), - }; + let rustc_binary = options.test_builder.as_ref().map(|v| &**v).unwrap_or_else(|| { + rustc_interface::util::rustc_path().expect("found rustc") + }); + let mut compiler = Command::new(&rustc_binary); + compiler.arg("--crate-type").arg("bin"); + for cfg in &options.cfgs { + compiler.arg("--cfg").arg(&cfg); + } + if let Some(sysroot) = options.maybe_sysroot { + compiler.arg("--sysroot").arg(sysroot); + } + compiler.arg("--edition").arg(&edition.to_string()); + compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path); + compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", + format!("{}", line as isize - line_offset as isize)); + compiler.arg("-o").arg(&output_file); + if as_test_harness { + compiler.arg("--test"); + } + for lib_str in &options.lib_strs { + compiler.arg("-L").arg(&lib_str); + } + for extern_str in &options.extern_strs { + compiler.arg("--extern").arg(&extern_str); + } + compiler.arg("-Ccodegen-units=1"); + for codegen_options_str in &options.codegen_options_strs { + compiler.arg("-C").arg(&codegen_options_str); + } + if no_run { + compiler.arg("--emit=metadata"); + } + compiler.arg("--target").arg(target.to_string()); - let compile_result = panic::catch_unwind(AssertUnwindSafe(|| { - interface::run_compiler(config, |compiler| { - if no_run { - compiler.global_ctxt().and_then(|global_ctxt| global_ctxt.take().enter(|tcx| { - tcx.analysis(LOCAL_CRATE) - })).ok(); - } else { - compiler.compile().ok(); - }; - compiler.session().compile_status() - }) - })).map_err(|_| ()).and_then(|s| s.map_err(|_| ())); + compiler.arg("-"); + compiler.stdin(Stdio::piped()); + compiler.stderr(Stdio::piped()); - match (compile_result, compile_fail) { - (Ok(()), true) => { + let mut child = compiler.spawn().expect("Failed to spawn rustc process"); + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + stdin.write_all(test.as_bytes()).expect("could write out test sources"); + } + let output = child.wait_with_output().expect("Failed to read stdout"); + + struct Bomb<'a>(&'a str); + impl Drop for Bomb<'_> { + fn drop(&mut self) { + eprint!("{}",self.0); + } + } + + let out = str::from_utf8(&output.stderr).unwrap(); + let _bomb = Bomb(&out); + match (output.status.success(), compile_fail) { + (true, true) => { return Err(TestFailure::UnexpectedCompilePass); } - (Ok(()), false) => {} - (Err(_), true) => { + (true, false) => {} + (false, true) => { if !error_codes.is_empty() { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); if !error_codes.is_empty() { @@ -350,7 +316,7 @@ fn run_test( } } } - (Err(_), false) => { + (false, false) => { return Err(TestFailure::CompileError); } } @@ -360,7 +326,15 @@ fn run_test( } // Run the code! - let mut cmd = Command::new(output_file); + let mut cmd; + + if let Some(tool) = runtool { + cmd = Command::new(tool); + cmd.arg(output_file); + cmd.args(runtool_args); + } else { + cmd = Command::new(output_file); + } match cmd.output() { Err(e) => return Err(TestFailure::ExecutionError(e)), @@ -427,7 +401,7 @@ pub fn make_test(s: &str, // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = EmitterWriter::new(box io::sink(), None, false, false, false); + let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, cm); @@ -452,7 +426,7 @@ pub fn make_test(s: &str, Ok(Some(item)) => { if !found_main { if let ast::ItemKind::Fn(..) = item.node { - if item.ident.as_str() == "main" { + if item.ident.name == sym::main { found_main = true; } } @@ -646,45 +620,31 @@ pub struct Collector { // the `names` vector of that test will be `["Title", "Subtitle"]`. names: Vec, - cfgs: Vec, - libs: Vec, - cg: CodegenOptions, - externs: Externs, + options: Options, use_headers: bool, + enable_per_target_ignores: bool, cratename: String, opts: TestOptions, - maybe_sysroot: Option, position: Span, source_map: Option>, filename: Option, - linker: Option, - edition: Edition, - persist_doctests: Option, } impl Collector { - pub fn new(cratename: String, cfgs: Vec, libs: Vec, cg: CodegenOptions, - externs: Externs, use_headers: bool, opts: TestOptions, - maybe_sysroot: Option, source_map: Option>, - filename: Option, linker: Option, edition: Edition, - persist_doctests: Option) -> Collector { + pub fn new(cratename: String, options: Options, use_headers: bool, opts: TestOptions, + source_map: Option>, filename: Option, + enable_per_target_ignores: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), - cfgs, - libs, - cg, - externs, + options, use_headers, + enable_per_target_ignores, cratename, opts, - maybe_sysroot, position: DUMMY_SP, source_map, filename, - linker, - edition, - persist_doctests, } } @@ -719,22 +679,26 @@ impl Tester for Collector { fn add_test(&mut self, test: String, config: LangString, line: usize) { let filename = self.get_filename(); let name = self.generate_name(line, &filename); - let cfgs = self.cfgs.clone(); - let libs = self.libs.clone(); - let cg = self.cg.clone(); - let externs = self.externs.clone(); let cratename = self.cratename.to_string(); let opts = self.opts.clone(); - let maybe_sysroot = self.maybe_sysroot.clone(); - let linker = self.linker.clone(); - let edition = config.edition.unwrap_or(self.edition); - let persist_doctests = self.persist_doctests.clone(); + let edition = config.edition.unwrap_or(self.options.edition.clone()); + let options = self.options.clone(); + let runtool = self.options.runtool.clone(); + let runtool_args = self.options.runtool_args.clone(); + let target = self.options.target.clone(); + let target_str = target.to_string(); debug!("creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { - name: testing::DynTestName(name), - ignore: config.ignore, + name: testing::DynTestName(name.clone()), + ignore: match config.ignore { + Ignore::All => true, + Ignore::None => false, + Ignore::Some(ref ignores) => { + ignores.iter().any(|s| target_str.contains(s)) + }, + }, // compiler failures are test failures should_panic: testing::ShouldPanic::No, allow_fail: config.allow_fail, @@ -745,20 +709,17 @@ impl Tester for Collector { &cratename, &filename, line, - cfgs, - libs, - cg, - externs, + options, config.should_panic, config.no_run, config.test_harness, + runtool, + runtool_args, + target, config.compile_fail, config.error_codes, &opts, - maybe_sysroot, - linker, edition, - persist_doctests ); if let Err(err) = res { @@ -837,8 +798,8 @@ impl Tester for Collector { // We use these headings as test names, so it's good if // they're valid identifiers. let name = name.chars().enumerate().map(|(i, c)| { - if (i == 0 && c.is_xid_start()) || - (i != 0 && c.is_xid_continue()) { + if (i == 0 && rustc_lexer::is_id_start(c)) || + (i != 0 && rustc_lexer::is_id_continue(c)) { c } else { '_' @@ -901,7 +862,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // anything else, this will combine them for us. if let Some(doc) = attrs.collapsed_doc_value() { self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); - markdown::find_testable_code(&doc, self.collector, self.codes); + markdown::find_testable_code(&doc, + self.collector, + self.codes, + self.collector.enable_per_target_ignores); } nested(self); @@ -951,7 +915,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { v: &'hir hir::Variant, g: &'hir hir::Generics, item_id: hir::HirId) { - self.visit_testable(v.node.ident.to_string(), &v.node.attrs, |this| { + self.visit_testable(v.ident.to_string(), &v.attrs, |this| { intravisit::walk_variant(this, v, g, item_id); }); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 35b6d9972d..ee330cb321 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -41,7 +41,7 @@ fn def_id_to_path( // framework from syntax?. pub struct RustdocVisitor<'a, 'tcx> { - cx: &'a core::DocContext<'tcx>, + cx: &'a mut core::DocContext<'tcx>, view_item_stack: FxHashSet, inlining: bool, /// Are the current module and all of its parents public? @@ -51,7 +51,7 @@ pub struct RustdocVisitor<'a, 'tcx> { impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn new( - cx: &'a core::DocContext<'tcx> + cx: &'a mut core::DocContext<'tcx> ) -> RustdocVisitor<'a, 'tcx> { // If the root is re-exported, terminate all recursion. let mut stack = FxHashSet::default(); @@ -84,7 +84,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ); module.is_crate = true; - self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths; + self.cx.renderinfo.get_mut().exact_paths = self.exact_paths; module } @@ -130,10 +130,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Enum { name, variants: def.variants.iter().map(|v| Variant { - name: v.node.ident.name, - id: v.node.id, - attrs: &v.node.attrs, - def: &v.node.data, + name: v.ident.name, + id: v.id, + attrs: &v.attrs, + def: &v.data, whence: v.span, }).collect(), vis: &it.vis, @@ -292,7 +292,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Res::Def(DefKind::ForeignTy, did) | Res::Def(DefKind::TyAlias, did) if !self_is_hidden => { self.cx.renderinfo - .borrow_mut() + .get_mut() .access_levels.map .insert(did, AccessLevel::Public); }, diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 2547e3a06e..b229b5f688 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -1,12 +1,10 @@ use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; -use rustc::ty::Visibility; +use rustc::ty::{TyCtxt, Visibility}; use rustc::util::nodemap::FxHashSet; use syntax::symbol::sym; -use std::cell::RefMut; - use crate::clean::{AttributesExt, NestedAttributesExt}; // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses @@ -14,9 +12,9 @@ use crate::clean::{AttributesExt, NestedAttributesExt}; /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes /// specific rustdoc annotations into account (i.e., `doc(hidden)`) pub struct LibEmbargoVisitor<'a, 'tcx> { - cx: &'a crate::core::DocContext<'tcx>, + tcx: TyCtxt<'tcx>, // Accessibility levels for reachable nodes - access_levels: RefMut<'a, AccessLevels>, + access_levels: &'a mut AccessLevels, // Previous accessibility level, None means unreachable prev_level: Option, // Keeps track of already visited modules, in case a module re-exports its parent @@ -25,13 +23,13 @@ pub struct LibEmbargoVisitor<'a, 'tcx> { impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { pub fn new( - cx: &'a crate::core::DocContext<'tcx> + cx: &'a mut crate::core::DocContext<'tcx> ) -> LibEmbargoVisitor<'a, 'tcx> { LibEmbargoVisitor { - cx, - access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels), + tcx: cx.tcx, + access_levels: &mut cx.renderinfo.get_mut().access_levels, prev_level: Some(AccessLevel::Public), - visited_mods: FxHashSet::default() + visited_mods: FxHashSet::default(), } } @@ -43,7 +41,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { // Updates node level and returns the updated level fn update(&mut self, did: DefId, level: Option) -> Option { - let is_hidden = self.cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden); + let is_hidden = self.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden); let old_level = self.access_levels.map.get(&did).cloned(); // Accessibility levels can only grow @@ -60,9 +58,9 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { return; } - for item in self.cx.tcx.item_children(def_id).iter() { + for item in self.tcx.item_children(def_id).iter() { if let Some(def_id) = item.res.opt_def_id() { - if self.cx.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || + if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || item.vis == Visibility::Public { self.visit_item(item.res); } @@ -72,7 +70,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, res: Res) { let def_id = res.def_id(); - let vis = self.cx.tcx.visibility(def_id); + let vis = self.tcx.visibility(def_id); let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 67a48ca4af..e45d56c320 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -15,6 +15,7 @@ Core encoding and decoding interfaces. #![feature(nll)] #![feature(associated_type_bounds)] #![cfg_attr(test, feature(test))] +#![allow(rustc::internal)] pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; diff --git a/src/libserialize/tests/json.rs b/src/libserialize/tests/json.rs index 3fb6bda679..898168252e 100644 --- a/src/libserialize/tests/json.rs +++ b/src/libserialize/tests/json.rs @@ -1,3 +1,5 @@ +#![allow(rustc::internal)] + extern crate serialize as rustc_serialize; use rustc_serialize::{Encodable, Decodable}; diff --git a/src/libserialize/tests/opaque.rs b/src/libserialize/tests/opaque.rs index fff6fc69e7..592bc09039 100644 --- a/src/libserialize/tests/opaque.rs +++ b/src/libserialize/tests/opaque.rs @@ -1,3 +1,5 @@ +#![allow(rustc::internal)] + extern crate serialize as rustc_serialize; use rustc_serialize::{Encodable, Decodable}; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5334c4dfc6..af1d2402f8 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,22 +23,16 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.4.0", features = ['rustc-dep-of-std'] } - -[dependencies.backtrace] -version = "0.3.34" -default-features = false # don't use coresymbolication on OSX -features = [ - "rustc-dep-of-std", # enable build support for integrating into libstd - "dbghelp", # backtrace/symbolize on MSVC - "libbacktrace", # symbolize on most platforms - "libunwind", # backtrace on most platforms - "dladdr", # symbolize on platforms w/o libbacktrace -] -optional = true +hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } + +[dependencies.backtrace_rs] +package = "backtrace" +version = "0.3.37" +default-features = false # without the libstd `backtrace` feature, stub out everything +features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd [dev-dependencies] -rand = "0.6.1" +rand = "0.7" [target.x86_64-apple-darwin.dependencies] rustc_asan = { path = "../librustc_asan" } @@ -56,12 +50,22 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } +[target.wasm32-wasi.dependencies] +wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] } + [build-dependencies] cc = "1.0" [features] default = ["std_detect_file_io", "std_detect_dlsym_getauxval"] +backtrace = [ + "backtrace_rs/dbghelp", # backtrace/symbolize on MSVC + "backtrace_rs/libbacktrace", # symbolize on most platforms + "backtrace_rs/libunwind", # backtrace on most platforms + "backtrace_rs/dladdr", # symbolize on platforms w/o libbacktrace +] + panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] compiler-builtins-c = ["alloc/compiler-builtins-c"] @@ -70,11 +74,6 @@ llvm-libunwind = ["unwind/llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message panic_immediate_abort = ["core/panic_immediate_abort"] -# An off-by-default feature which enables a linux-syscall-like ABI for libstd to -# interoperate with the host environment. Currently not well documented and -# requires rebuilding the standard library to use it. -wasm_syscall = [] - # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs new file mode 100644 index 0000000000..61c42a5607 --- /dev/null +++ b/src/libstd/backtrace.rs @@ -0,0 +1,353 @@ +//! Support for capturing a stack backtrace of an OS thread +//! +//! This module contains the support necessary to capture a stack backtrace of a +//! running OS thread from the OS thread itself. The `Backtrace` type supports +//! capturing a stack trace via the `Backtrace::capture` and +//! `Backtrace::force_capture` functions. +//! +//! A backtrace is typically quite handy to attach to errors (e.g. types +//! implementing `std::error::Error`) to get a causal chain of where an error +//! was generated. +//! +//! > **Note**: this module is unstable and is designed in [RFC 2504], and you +//! > can learn more about its status in the [tracking issue]. +//! +//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md +//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487 +//! +//! ## Accuracy +//! +//! Backtraces are attempted to be as accurate as possible, but no guarantees +//! are provided about the exact accuracy of a backtrace. Instruction pointers, +//! symbol names, filenames, line numbers, etc, may all be incorrect when +//! reported. Accuracy is attempted on a best-effort basis, however, and bugs +//! are always welcome to indicate areas of improvement! +//! +//! For most platforms a backtrace with a filename/line number requires that +//! programs be compiled with debug information. Without debug information +//! filenames/line numbers will not be reported. +//! +//! ## Platform support +//! +//! Not all platforms that libstd compiles for support capturing backtraces. +//! Some platforms simply do nothing when capturing a backtrace. To check +//! whether the platform supports capturing backtraces you can consult the +//! `BacktraceStatus` enum as a result of `Backtrace::status`. +//! +//! Like above with accuracy platform support is done on a best effort basis. +//! Sometimes libraries may not be available at runtime or something may go +//! wrong which would cause a backtrace to not be captured. Please feel free to +//! report issues with platforms where a backtrace cannot be captured though! +//! +//! ## Environment Variables +//! +//! The `Backtrace::capture` function may not actually capture a backtrace by +//! default. Its behavior is governed by two environment variables: +//! +//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture` +//! will never capture a backtrace. Any other value this is set to will enable +//! `Backtrace::capture`. +//! +//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable +//! is consulted with the same rules of `RUST_LIB_BACKTRACE`. +//! +//! * If neither of the above env vars are set, then `Backtrace::capture` will +//! be disabled. +//! +//! Capturing a backtrace can be a quite expensive runtime operation, so the +//! environment variables allow either forcibly disabling this runtime +//! performance hit or allow selectively enabling it in some programs. +//! +//! Note that the `Backtrace::force_capture` function can be used to ignore +//! these environment variables. Also note that the state of environment +//! variables is cached once the first backtrace is created, so altering +//! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime may not actually change +//! how backtraces are captured. + +#![unstable(feature = "backtrace", issue = "53487")] + +// NB: A note on resolution of a backtrace: +// +// Backtraces primarily happen in two steps, one is where we actually capture +// the stack backtrace, giving us a list of instruction pointers corresponding +// to stack frames. Next we take these instruction pointers and, one-by-one, +// turn them into a human readable name (like `main`). +// +// The first phase can be somewhat expensive (walking the stack), especially +// on MSVC where debug information is consulted to return inline frames each as +// their own frame. The second phase, however, is almost always extremely +// expensive (on the order of milliseconds sometimes) when it's consulting debug +// information. +// +// We attempt to amortize this cost as much as possible by delaying resolution +// of an address to a human readable name for as long as possible. When +// `Backtrace::create` is called to capture a backtrace it doesn't actually +// perform any symbol resolution, but rather we lazily resolve symbols only just +// before they're needed for printing. This way we can make capturing a +// backtrace and throwing it away much cheaper, but actually printing a +// backtrace is still basically the same cost. +// +// This strategy comes at the cost of some synchronization required inside of a +// `Backtrace`, but that's a relatively small price to pay relative to capturing +// a backtrace or actually symbolizing it. + +use crate::env; +use crate::fmt; +use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::sync::Mutex; +use crate::sys_common::backtrace::{output_filename, lock}; +use crate::vec::Vec; +use backtrace_rs as backtrace; +use backtrace::BytesOrWideString; + +/// A captured OS thread stack backtrace. +/// +/// This type represents a stack backtrace for an OS thread captured at a +/// previous point in time. In some instances the `Backtrace` type may +/// internally be empty due to configuration. For more information see +/// `Backtrace::capture`. +pub struct Backtrace { + inner: Inner, +} + +/// The current status of a backtrace, indicating whether it was captured or +/// whether it is empty for some other reason. +#[non_exhaustive] +#[derive(Debug)] +pub enum BacktraceStatus { + /// Capturing a backtrace is not supported, likely because it's not + /// implemented for the current platform. + Unsupported, + /// Capturing a backtrace has been disabled through either the + /// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables. + Disabled, + /// A backtrace has been captured and the `Backtrace` should print + /// reasonable information when rendered. + Captured, +} + +enum Inner { + Unsupported, + Disabled, + Captured(Mutex), +} + +struct Capture { + actual_start: usize, + resolved: bool, + frames: Vec, +} + +fn _assert_send_sync() { + fn _assert() {} + _assert::(); +} + +struct BacktraceFrame { + frame: backtrace::Frame, + symbols: Vec, +} + +struct BacktraceSymbol { + name: Option>, + filename: Option, + lineno: Option, +} + +enum BytesOrWide { + Bytes(Vec), + Wide(Vec), +} + +impl Backtrace { + /// Returns whether backtrace captures are enabled through environment + /// variables. + fn enabled() -> bool { + // Cache the result of reading the environment variables to make + // backtrace captures speedy, because otherwise reading environment + // variables every time can be somewhat slow. + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(SeqCst) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var("RUST_LIB_BACKTRACE") { + Ok(s) => s != "0", + Err(_) => match env::var("RUST_BACKTRACE") { + Ok(s) => s != "0", + Err(_) => false, + }, + }; + ENABLED.store(enabled as usize + 1, SeqCst); + return enabled; + } + + /// Capture a stack backtrace of the current thread. + /// + /// This function will capture a stack backtrace of the current OS thread of + /// execution, returning a `Backtrace` type which can be later used to print + /// the entire stack trace or render it to a string. + /// + /// This function will be a noop if the `RUST_BACKTRACE` or + /// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either + /// environment variable is set and enabled then this function will actually + /// capture a backtrace. Capturing a backtrace can be both memory intensive + /// and slow, so these environment variables allow liberally using + /// `Backtrace::capture` and only incurring a slowdown when the environment + /// variables are set. + /// + /// To forcibly capture a backtrace regardless of environment variables, use + /// the `Backtrace::force_capture` function. + #[inline(never)] // want to make sure there's a frame here to remove + pub fn capture() -> Backtrace { + if !Backtrace::enabled() { + return Backtrace { inner: Inner::Disabled }; + } + Backtrace::create(Backtrace::capture as usize) + } + + /// Forcibly captures a full backtrace, regardless of environment variable + /// configuration. + /// + /// This function behaves the same as `capture` except that it ignores the + /// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment + /// variables, always capturing a backtrace. + /// + /// Note that capturing a backtrace can be an expensive operation on some + /// platforms, so this should be used with caution in performance-sensitive + /// parts of code. + #[inline(never)] // want to make sure there's a frame here to remove + pub fn force_capture() -> Backtrace { + Backtrace::create(Backtrace::force_capture as usize) + } + + // Capture a backtrace which start just before the function addressed by + // `ip` + fn create(ip: usize) -> Backtrace { + let _lock = lock(); + let mut frames = Vec::new(); + let mut actual_start = None; + unsafe { + backtrace::trace_unsynchronized(|frame| { + frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len()); + } + true + }); + } + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right now, + // and this should be a good enough approximation. + let inner = if frames.len() == 0 { + Inner::Unsupported + } else { + Inner::Captured(Mutex::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + Backtrace { inner } + } + + /// Returns the status of this backtrace, indicating whether this backtrace + /// request was unsupported, disabled, or a stack trace was actually + /// captured. + pub fn status(&self) -> BacktraceStatus { + match self.inner { + Inner::Unsupported => BacktraceStatus::Unsupported, + Inner::Disabled => BacktraceStatus::Disabled, + Inner::Captured(_) => BacktraceStatus::Captured, + } + } +} + +impl fmt::Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self, fmt) + } +} + +impl fmt::Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("unsupported backtrace"), + Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Captured(c) => c.lock().unwrap(), + }; + capture.resolve(); + + let full = fmt.alternate(); + let (frames, style) = if full { + (&capture.frames[..], backtrace::PrintFmt::Full) + } else { + (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = crate::env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| { + output_filename(fmt, path, style, cwd.as_ref().ok()) + }; + + let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + let mut f = f.frame(); + if frame.symbols.is_empty() { + f.print_raw(frame.frame.ip(), None, None, None)?; + } else { + for symbol in frame.symbols.iter() { + f.print_raw( + frame.frame.ip(), + symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)), + symbol.filename.as_ref().map(|b| match b { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }), + symbol.lineno, + )?; + } + } + } + f.finish()?; + Ok(()) + } +} + +impl Capture { + fn resolve(&mut self) { + // If we're already resolved, nothing to do! + if self.resolved { + return; + } + self.resolved = true; + + // Use the global backtrace lock to synchronize this as it's a + // requirement of the `backtrace` crate, and then actually resolve + // everything. + let _lock = lock(); + for frame in self.frames.iter_mut() { + let symbols = &mut frame.symbols; + unsafe { + backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().to_vec()), + filename: symbol.filename_raw().map(|b| match b { + BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()), + BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()), + }), + lineno: symbol.lineno(), + }); + }); + } + } + } +} diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1e28ee8da2..a0538986a2 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -6,7 +6,7 @@ use hashbrown::hash_map as base; use crate::borrow::Borrow; use crate::cell::Cell; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::fmt::{self, Debug}; #[allow(deprecated)] use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; @@ -588,7 +588,7 @@ where /// ``` #[inline] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base .try_reserve(additional) .map_err(map_collection_alloc_err) @@ -2542,10 +2542,13 @@ fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, } #[inline] -fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> CollectionAllocErr { +fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> TryReserveError { match err { - hashbrown::CollectionAllocErr::CapacityOverflow => CollectionAllocErr::CapacityOverflow, - hashbrown::CollectionAllocErr::AllocErr => CollectionAllocErr::AllocErr, + hashbrown::CollectionAllocErr::CapacityOverflow => TryReserveError::CapacityOverflow, + hashbrown::CollectionAllocErr::AllocErr { layout } => TryReserveError::AllocError { + layout, + non_exhaustive: (), + }, } } @@ -2605,7 +2608,7 @@ mod test_map { use super::RandomState; use crate::cell::RefCell; use rand::{thread_rng, Rng}; - use realstd::collections::CollectionAllocErr::*; + use realstd::collections::TryReserveError::*; use realstd::usize; // https://github.com/rust-lang/rust/issues/62301 @@ -3405,7 +3408,7 @@ mod test_map { panic!("usize::MAX should trigger an overflow!"); } - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 8) { } else { panic!("usize::MAX / 8 should trigger an OOM!") } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index d243412405..26db651ef8 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1,5 +1,5 @@ use crate::borrow::Borrow; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, BuildHasher}; use crate::iter::{Chain, FromIterator, FusedIterator}; @@ -383,7 +383,7 @@ impl HashSet /// ``` #[inline] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.map.try_reserve(additional) } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 15c2532f8b..f5957466be 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -427,7 +427,7 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub use alloc_crate::collections::CollectionAllocErr; +pub use alloc_crate::collections::TryReserveError; mod hash; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index eca93399e5..b898936926 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -290,7 +290,7 @@ impl Error for VarError { /// /// Note that while concurrent access to environment variables is safe in Rust, /// some platforms only expose inherently unsafe non-threadsafe APIs for -/// inspecting the environment. As a result extra care needs to be taken when +/// inspecting the environment. As a result, extra care needs to be taken when /// auditing calls to unsafe external FFI functions to ensure that any external /// environment accesses are properly synchronized with accesses in Rust. /// diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 117a430eec..4a1bb75d58 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -17,6 +17,7 @@ use core::array; use crate::alloc::{AllocErr, LayoutErr, CannotReallocInPlace}; use crate::any::TypeId; +use crate::backtrace::Backtrace; use crate::borrow::Cow; use crate::cell; use crate::char; @@ -196,14 +197,28 @@ pub trait Error: Debug + Display { #[stable(feature = "error_source", since = "1.30.0")] fn source(&self) -> Option<&(dyn Error + 'static)> { None } - /// Gets the `TypeId` of `self` + /// Gets the `TypeId` of `self`. #[doc(hidden)] #[unstable(feature = "error_type_id", - reason = "this is memory unsafe to override in user code", + reason = "this is memory-unsafe to override in user code", issue = "60784")] fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static { TypeId::of::() } + + /// Returns a stack backtrace, if available, of where this error ocurred. + /// + /// This function allows inspecting the location, in code, of where an error + /// happened. The returned `Backtrace` contains information about the stack + /// trace of the OS thread of execution of where the error originated from. + /// + /// Note that not all errors contain a `Backtrace`. Also note that a + /// `Backtrace` may actually be empty. For more information consult the + /// `Backtrace` type itself. + #[unstable(feature = "backtrace", issue = "53487")] + fn backtrace(&self) -> Option<&Backtrace> { + None + } } mod private { @@ -601,19 +616,19 @@ impl Error for char::ParseCharError { } } -// copied from any.rs +// Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { - // Get TypeId of the type this function is instantiated with + // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); - // Get TypeId of the type in the trait object + // Get `TypeId` of the type in the trait object. let boxed = self.type_id(private::Internal); - // Compare both TypeIds on equality + // Compare both `TypeId`s on equality. t == boxed } @@ -647,21 +662,21 @@ impl dyn Error + 'static { } impl dyn Error + 'static + Send { - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { ::is::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { @@ -670,21 +685,21 @@ impl dyn Error + 'static + Send { } impl dyn Error + 'static + Send + Sync { - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { ::is::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { @@ -695,7 +710,7 @@ impl dyn Error + 'static + Send + Sync { impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempt to downcast the box to a concrete type. + /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { if self.is::() { unsafe { @@ -863,12 +878,12 @@ impl<'a> Iterator for ErrorIter<'a> { impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempt to downcast the box to a concrete type. + /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { - // reapply the Send marker + // Reapply the `Send` marker. transmute::, Box>(s) }) } @@ -877,12 +892,12 @@ impl dyn Error + Send { impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempt to downcast the box to a concrete type. + /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { - // reapply the Send+Sync marker + // Reapply the `Send + Sync` marker. transmute::, Box>(s) }) } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f649170c40..795830a52c 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -236,7 +236,7 @@ impl f32 { /// let b = 60.0_f32; /// /// // 100.0 - /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -318,7 +318,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.powi(2) - x*x).abs(); + /// let abs_difference = (x.powi(2) - (x * x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -336,7 +336,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -600,7 +600,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI/2.0; + /// let x = f32::consts::FRAC_PI_2; /// /// let abs_difference = (x.sin() - 1.0).abs(); /// @@ -623,7 +623,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = 2.0*f32::consts::PI; + /// let x = 2.0 * f32::consts::PI; /// /// let abs_difference = (x.cos() - 1.0).abs(); /// @@ -646,7 +646,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI / 4.0; + /// let x = f32::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); @@ -666,10 +666,10 @@ impl f32 { /// ``` /// use std::f32; /// - /// let f = f32::consts::PI / 2.0; + /// let f = f32::consts::FRAC_PI_2; /// /// // asin(sin(pi/2)) - /// let abs_difference = (f.sin().asin() - f32::consts::PI / 2.0).abs(); + /// let abs_difference = (f.sin().asin() - f32::consts::FRAC_PI_2).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -688,10 +688,10 @@ impl f32 { /// ``` /// use std::f32; /// - /// let f = f32::consts::PI / 4.0; + /// let f = f32::consts::FRAC_PI_4; /// /// // acos(cos(pi/4)) - /// let abs_difference = (f.cos().acos() - f32::consts::PI / 4.0).abs(); + /// let abs_difference = (f.cos().acos() - f32::consts::FRAC_PI_4).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -734,7 +734,6 @@ impl f32 { /// ``` /// use std::f32; /// - /// let pi = f32::consts::PI; /// // Positive angles measured counter-clockwise /// // from positive x axis /// // -pi/4 radians (45 deg clockwise) @@ -745,8 +744,8 @@ impl f32 { /// let x2 = -3.0f32; /// let y2 = 3.0f32; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-f32::consts::FRAC_PI_4)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * f32::consts::FRAC_PI_4)).abs(); /// /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); @@ -765,7 +764,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI/4.0; + /// let x = f32::consts::FRAC_PI_4; /// let f = x.sin_cos(); /// /// let abs_difference_0 = (f.0 - x.sin()).abs(); @@ -834,7 +833,7 @@ impl f32 { /// /// let f = x.sinh(); /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// let g = (e*e - 1.0)/(2.0*e); + /// let g = ((e * e) - 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference <= f32::EPSILON); @@ -856,7 +855,7 @@ impl f32 { /// let x = 1.0f32; /// let f = x.cosh(); /// // Solving cosh() at 1 gives this result - /// let g = (e*e + 1.0)/(2.0*e); + /// let g = ((e * e) + 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// // Same result @@ -880,7 +879,7 @@ impl f32 { /// /// let f = x.tanh(); /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2)); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference <= f32::EPSILON); @@ -911,7 +910,7 @@ impl f32 { if self == NEG_INFINITY { NEG_INFINITY } else { - (self + ((self * self) + 1.0).sqrt()).ln() + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -932,9 +931,10 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { - match self { - x if x < 1.0 => crate::f32::NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + crate::f32::NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } @@ -1488,6 +1488,7 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index f61630997d..44d25f1b47 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -212,7 +212,7 @@ impl f64 { /// let b = 60.0_f64; /// /// // 100.0 - /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -244,7 +244,7 @@ impl f64 { pub fn div_euclid(self, rhs: f64) -> f64 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { - return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; } q } @@ -291,7 +291,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.powi(2) - x*x).abs(); + /// let abs_difference = (x.powi(2) - (x * x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -307,7 +307,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -437,9 +437,9 @@ impl f64 { pub fn log2(self) -> f64 { self.log_wrapper(|n| { #[cfg(target_os = "android")] - return crate::sys::android::log2f64(n); + return crate::sys::android::log2f64(n); #[cfg(not(target_os = "android"))] - return unsafe { intrinsics::log2f64(n) }; + return unsafe { intrinsics::log2f64(n) }; }) } @@ -481,16 +481,16 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_deprecated(since = "1.10.0", - reason = "you probably meant `(self - other).abs()`: \ + reason = "you probably meant `(self - other).abs()`: \ this operation is `(self - other).max(0.0)` \ except that `abs_sub` also propagates NaNs (also \ known as `fdim` in C). If you truly need the positive \ difference, consider using that expression or the C function \ `fdim`, depending on how you wish to handle NaN (please consider \ filing an issue describing your use-case too).")] - pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } - } + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } /// Takes the cubic root of a number. /// @@ -537,7 +537,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/2.0; + /// let x = f64::consts::FRAC_PI_2; /// /// let abs_difference = (x.sin() - 1.0).abs(); /// @@ -556,7 +556,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = 2.0*f64::consts::PI; + /// let x = 2.0 * f64::consts::PI; /// /// let abs_difference = (x.cos() - 1.0).abs(); /// @@ -575,7 +575,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/4.0; + /// let x = f64::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); /// /// assert!(abs_difference < 1e-14); @@ -595,10 +595,10 @@ impl f64 { /// ``` /// use std::f64; /// - /// let f = f64::consts::PI / 2.0; + /// let f = f64::consts::FRAC_PI_2; /// /// // asin(sin(pi/2)) - /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// let abs_difference = (f.sin().asin() - f64::consts::FRAC_PI_2).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -617,10 +617,10 @@ impl f64 { /// ``` /// use std::f64; /// - /// let f = f64::consts::PI / 4.0; + /// let f = f64::consts::FRAC_PI_4; /// /// // acos(cos(pi/4)) - /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// let abs_difference = (f.cos().acos() - f64::consts::FRAC_PI_4).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -661,7 +661,6 @@ impl f64 { /// ``` /// use std::f64; /// - /// let pi = f64::consts::PI; /// // Positive angles measured counter-clockwise /// // from positive x axis /// // -pi/4 radians (45 deg clockwise) @@ -672,8 +671,8 @@ impl f64 { /// let x2 = -3.0_f64; /// let y2 = 3.0_f64; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-f64::consts::FRAC_PI_4)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * f64::consts::FRAC_PI_4)).abs(); /// /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); @@ -692,7 +691,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/4.0; + /// let x = f64::consts::FRAC_PI_4; /// let f = x.sin_cos(); /// /// let abs_difference_0 = (f.0 - x.sin()).abs(); @@ -759,7 +758,7 @@ impl f64 { /// /// let f = x.sinh(); /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// let g = (e*e - 1.0)/(2.0*e); + /// let g = ((e * e) - 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference < 1e-10); @@ -781,7 +780,7 @@ impl f64 { /// let x = 1.0_f64; /// let f = x.cosh(); /// // Solving cosh() at 1 gives this result - /// let g = (e*e + 1.0)/(2.0*e); + /// let g = ((e * e) + 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// // Same result @@ -805,7 +804,7 @@ impl f64 { /// /// let f = x.tanh(); /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2)); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference < 1.0e-10); @@ -834,7 +833,7 @@ impl f64 { if self == NEG_INFINITY { NEG_INFINITY } else { - (self + ((self * self) + 1.0).sqrt()).ln() + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -853,9 +852,10 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { - match self { - x if x < 1.0 => NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } @@ -1188,7 +1188,7 @@ mod tests { assert_eq!((-0f64).abs(), 0f64); assert_eq!((-1f64).abs(), 1f64); assert_eq!(NEG_INFINITY.abs(), INFINITY); - assert_eq!((1f64/NEG_INFINITY).abs(), 0f64); + assert_eq!((1f64 / NEG_INFINITY).abs(), 0f64); assert!(NAN.abs().is_nan()); } @@ -1200,7 +1200,7 @@ mod tests { assert_eq!((-0f64).signum(), -1f64); assert_eq!((-1f64).signum(), -1f64); assert_eq!(NEG_INFINITY.signum(), -1f64); - assert_eq!((1f64/NEG_INFINITY).signum(), -1f64); + assert_eq!((1f64 / NEG_INFINITY).signum(), -1f64); assert!(NAN.signum().is_nan()); } @@ -1212,7 +1212,7 @@ mod tests { assert!(!(-0f64).is_sign_positive()); assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); - assert!(!(1f64/NEG_INFINITY).is_sign_positive()); + assert!(!(1f64 / NEG_INFINITY).is_sign_positive()); assert!(NAN.is_sign_positive()); assert!(!(-NAN).is_sign_positive()); } @@ -1225,7 +1225,7 @@ mod tests { assert!((-0f64).is_sign_negative()); assert!((-1f64).is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative()); - assert!((1f64/NEG_INFINITY).is_sign_negative()); + assert!((1f64 / NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); assert!((-NAN).is_sign_negative()); } @@ -1434,6 +1434,8 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f64).asinh().is_sign_negative()); + // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 512839a12c..d7f4cc5d1f 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -572,8 +572,8 @@ impl CString { /// use std::ffi::{CString, CStr}; /// /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); - /// let c_str = c_string.as_c_str(); - /// assert_eq!(c_str, + /// let cstr = c_string.as_c_str(); + /// assert_eq!(cstr, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[inline] @@ -615,7 +615,7 @@ impl CString { } // Turns this `CString` into an empty string to prevent -// memory unsafe code from working by accident. Inline +// memory-unsafe code from working by accident. Inline // to prevent LLVM from optimizing it away in debug builds. #[stable(feature = "cstring_drop", since = "1.13.0")] impl Drop for CString { @@ -935,8 +935,10 @@ impl CStr { /// Wraps a raw C string with a safe C string wrapper. /// /// This function will wrap the provided `ptr` with a `CStr` wrapper, which - /// allows inspection and interoperation of non-owned C strings. This method - /// is unsafe for a number of reasons: + /// allows inspection and interoperation of non-owned C strings. The total + /// size of the raw C string must be smaller than `isize::MAX` **bytes** + /// in memory due to calling the `slice::from_raw_parts` function. + /// This method is unsafe for a number of reasons: /// /// * There is no guarantee to the validity of `ptr`. /// * The returned lifetime is not guaranteed to be the actual lifetime of @@ -994,8 +996,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"hello"); - /// assert!(c_str.is_err()); + /// let cstr = CStr::from_bytes_with_nul(b"hello"); + /// assert!(cstr.is_err()); /// ``` /// /// Creating a `CStr` with an interior nul byte is an error: @@ -1003,8 +1005,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"he\0llo\0"); - /// assert!(c_str.is_err()); + /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0"); + /// assert!(cstr.is_err()); /// ``` #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub fn from_bytes_with_nul(bytes: &[u8]) @@ -1111,8 +1113,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_bytes(), b"foo"); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes(), b"foo"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1137,8 +1139,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0"); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1164,8 +1166,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_str(), Ok("foo")); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_str(), Ok("foo")); /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_str(&self) -> Result<&str, str::Utf8Error> { @@ -1205,9 +1207,9 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0") + /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0") /// .expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World")); + /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World")); /// ``` /// /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: @@ -1216,10 +1218,10 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") + /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!( - /// c_str.to_string_lossy(), + /// cstr.to_string_lossy(), /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> /// ); /// ``` diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 1f384cbada..6cf062d4f3 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -233,7 +233,7 @@ impl OsString { /// ``` /// use std::ffi::OsString; /// - /// let mut os_string = OsString::with_capacity(10); + /// let os_string = OsString::with_capacity(10); /// assert!(os_string.capacity() >= 10); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] @@ -616,7 +616,7 @@ impl OsStr { /// Note that this does **not** return the number of bytes in the string in /// OS string form. /// - /// The length returned is that of the underlying storage used by `OsStr`; + /// The length returned is that of the underlying storage used by `OsStr`. /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr` /// store strings in a form best suited for cheap inter-conversion between /// native-platform and Rust string forms, which may differ significantly diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5f76875bd6..b5265fe369 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1956,7 +1956,8 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// # Platform-specific behavior /// /// This function currently corresponds to the `opendir` function on Unix -/// and the `FindFirstFile` function on Windows. +/// and the `FindFirstFile` function on Windows. Advancing the iterator +/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: ../io/index.html#platform-specific-behavior @@ -2144,7 +2145,7 @@ mod tests { use crate::sys_common::io::test::{TempDir, tmpdir}; use crate::thread; - use rand::{rngs::StdRng, FromEntropy, RngCore}; + use rand::{rngs::StdRng, RngCore, SeedableRng}; #[cfg(windows)] use crate::os::windows::fs::{symlink_dir, symlink_file}; diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 0406549ff0..80b2c5f488 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -26,6 +26,7 @@ pub fn from_generator>(x: T) -> impl Future>(T); // We rely on the fact that async/await futures are immovable in order to create diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index aaf628e6c2..9593a1bae0 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -9,21 +9,21 @@ use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoSliceMut}; use crate::memchr; -/// The `BufReader` struct adds buffering to any reader. +/// The `BufReader` struct adds buffering to any reader. /// /// It can be excessively inefficient to work directly with a [`Read`] instance. /// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`] -/// results in a system call. A `BufReader` performs large, infrequent reads on +/// results in a system call. A `BufReader` performs large, infrequent reads on /// the underlying [`Read`] and maintains an in-memory buffer of the results. /// -/// `BufReader` can improve the speed of programs that make *small* and +/// `BufReader` can improve the speed of programs that make *small* and /// *repeated* read calls to the same file or network socket. It does not /// help when reading very large amounts at once, or reading just one or a few /// times. It also provides no advantage when reading from a source that is /// already in memory, like a `Vec`. /// -/// When the `BufReader` is dropped, the contents of its buffer will be -/// discarded. Creating multiple instances of a `BufReader` on the same +/// When the `BufReader` is dropped, the contents of its buffer will be +/// discarded. Creating multiple instances of a `BufReader` on the same /// stream can cause data loss. /// /// [`Read`]: ../../std/io/trait.Read.html @@ -56,7 +56,7 @@ pub struct BufReader { } impl BufReader { - /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples @@ -76,7 +76,7 @@ impl BufReader { BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) } - /// Creates a new `BufReader` with the specified buffer capacity. + /// Creates a new `BufReader` with the specified buffer capacity. /// /// # Examples /// @@ -177,7 +177,7 @@ impl BufReader { &self.buf[self.pos..self.cap] } - /// Unwraps this `BufReader`, returning the underlying reader. + /// Unwraps this `BufReader`, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. /// @@ -304,7 +304,7 @@ impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with `SeekFrom::Current(_)` is the - /// position the underlying reader would be at if the `BufReader` had no + /// position the underlying reader would be at if the `BufReader` had no /// internal buffer. /// /// Seeking always discards the internal buffer, even if the seek position @@ -355,19 +355,20 @@ impl Seek for BufReader { /// It can be excessively inefficient to work directly with something that /// implements [`Write`]. For example, every call to /// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A -/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying +/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// -/// `BufWriter` can improve the speed of programs that make *small* and +/// `BufWriter` can improve the speed of programs that make *small* and /// *repeated* write calls to the same file or network socket. It does not /// help when writing very large amounts at once, or writing just one or a few /// times. It also provides no advantage when writing to a destination that is /// in memory, like a `Vec`. /// -/// When the `BufWriter` is dropped, the contents of its buffer will be written -/// out. However, any errors that happen in the process of flushing the buffer -/// when the writer is dropped will be ignored. Code that wishes to handle such -/// errors must manually call [`flush`] before the writer is dropped. +/// It is critical to call [`flush`] before `BufWriter` is dropped. Though +/// dropping will attempt to flush the the contents of the buffer, any errors +/// that happen in the process of dropping will be ignored. Calling ['flush'] +/// ensures that the buffer is empty and thus dropping will not even attempt +/// file operations. /// /// # Examples /// @@ -386,7 +387,7 @@ impl Seek for BufReader { /// /// Because we're not buffering, we write each one in turn, incurring the /// overhead of a system call per byte written. We can fix this with a -/// `BufWriter`: +/// `BufWriter`: /// /// ```no_run /// use std::io::prelude::*; @@ -398,11 +399,12 @@ impl Seek for BufReader { /// for i in 0..10 { /// stream.write(&[i+1]).unwrap(); /// } +/// stream.flush().unwrap(); /// ``` /// -/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped -/// together by the buffer, and will all be written out in one system call when -/// the `stream` is dropped. +/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped +/// together by the buffer and will all be written out in one system call when +/// the `stream` is flushed. /// /// [`Write`]: ../../std/io/trait.Write.html /// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write @@ -447,7 +449,7 @@ pub struct BufWriter { pub struct IntoInnerError(W, Error); impl BufWriter { - /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples @@ -463,7 +465,7 @@ impl BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } - /// Creates a new `BufWriter` with the specified buffer capacity. + /// Creates a new `BufWriter` with the specified buffer capacity. /// /// # Examples /// @@ -564,7 +566,7 @@ impl BufWriter { &self.buf } - /// Unwraps this `BufWriter`, returning the underlying writer. + /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. /// diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index f2b6ce6feb..be364a1059 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -353,12 +353,17 @@ fn append_to_string(buf: &mut String, f: F) -> Result // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { - read_to_end_with_reservation(r, buf, 32) + read_to_end_with_reservation(r, buf, |_| 32) } -fn read_to_end_with_reservation(r: &mut R, - buf: &mut Vec, - reservation_size: usize) -> Result +fn read_to_end_with_reservation( + r: &mut R, + buf: &mut Vec, + mut reservation_size: F, +) -> Result +where + R: Read + ?Sized, + F: FnMut(&R) -> usize, { let start_len = buf.len(); let mut g = Guard { len: buf.len(), buf: buf }; @@ -366,7 +371,15 @@ fn read_to_end_with_reservation(r: &mut R, loop { if g.len == g.buf.len() { unsafe { - g.buf.reserve(reservation_size); + // FIXME(danielhenrymantilla): #42788 + // + // - This creates a (mut) reference to a slice of + // _uninitialized_ integers, which is **undefined behavior** + // + // - Only the standard library gets to soundly "ignore" this, + // based on its privileged knowledge of unstable rustc + // internals; + g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); r.initializer().initialize(&mut g.buf[g.len..]); @@ -2253,9 +2266,10 @@ impl Read for Take { } fn read_to_end(&mut self, buf: &mut Vec) -> Result { - let reservation_size = cmp::min(self.limit, 32) as usize; - - read_to_end_with_reservation(self, buf, reservation_size) + // Pass in a reservation_size closure that respects the current value + // of limit for each read. If we hit the read limit, this prevents the + // final zero-byte read from allocating again. + read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize) } } @@ -2312,10 +2326,10 @@ impl Iterator for Bytes { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// This struct is generally created by calling [`split`][split] on a -/// `BufRead`. Please see the documentation of `split()` for more details. +/// This struct is generally created by calling [`split`] on a `BufRead`. +/// Please see the documentation of [`split`] for more details. /// -/// [split]: trait.BufRead.html#method.split +/// [`split`]: trait.BufRead.html#method.split #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Split { @@ -2344,10 +2358,10 @@ impl Iterator for Split { /// An iterator over the lines of an instance of `BufRead`. /// -/// This struct is generally created by calling [`lines`][lines] on a -/// `BufRead`. Please see the documentation of `lines()` for more details. +/// This struct is generally created by calling [`lines`] on a `BufRead`. +/// Please see the documentation of [`lines`] for more details. /// -/// [lines]: trait.BufRead.html#method.lines +/// [`lines`]: trait.BufRead.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Lines { @@ -2378,6 +2392,7 @@ impl Iterator for Lines { #[cfg(test)] mod tests { + use crate::cmp; use crate::io::prelude::*; use super::{Cursor, SeekFrom, repeat}; use crate::io::{self, IoSlice, IoSliceMut}; @@ -2651,6 +2666,49 @@ mod tests { Ok(()) } + // A simple example reader which uses the default implementation of + // read_to_end. + struct ExampleSliceReader<'a> { + slice: &'a [u8], + } + + impl<'a> Read for ExampleSliceReader<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = cmp::min(self.slice.len(), buf.len()); + buf[..len].copy_from_slice(&self.slice[..len]); + self.slice = &self.slice[len..]; + Ok(len) + } + } + + #[test] + fn test_read_to_end_capacity() -> io::Result<()> { + let input = &b"foo"[..]; + + // read_to_end() generally needs to over-allocate, both for efficiency + // and so that it can distinguish EOF. Assert that this is the case + // with this simple ExampleSliceReader struct, which uses the default + // implementation of read_to_end. Even though vec1 is allocated with + // exactly enough capacity for the read, read_to_end will allocate more + // space here. + let mut vec1 = Vec::with_capacity(input.len()); + ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; + assert_eq!(vec1.len(), input.len()); + assert!(vec1.capacity() > input.len(), "allocated more"); + + // However, std::io::Take includes an implementation of read_to_end + // that will not allocate when the limit has already been reached. In + // this case, vec2 never grows. + let mut vec2 = Vec::with_capacity(input.len()); + ExampleSliceReader { slice: input } + .take(input.len() as u64) + .read_to_end(&mut vec2)?; + assert_eq!(vec2.len(), input.len()); + assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); + + Ok(()) + } + #[test] fn io_slice_mut_advance() { let mut buf1 = [1; 8]; diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 990c0eb895..c798ee0e22 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -201,9 +201,9 @@ pub struct StdinLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [`lock() method`][lock]. +/// locking, see the [`Stdin::lock`] method. /// -/// [lock]: struct.Stdin.html#method.lock +/// [`Stdin::lock`]: struct.Stdin.html#method.lock /// /// ### Note: Windows Portability Consideration /// When operating in a console, the Windows implementation of this stream does not support @@ -425,9 +425,9 @@ pub struct StdoutLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [Stdout::lock] method. +/// locking, see the [`Stdout::lock`] method. /// -/// [Stdout::lock]: struct.Stdout.html#method.lock +/// [`Stdout::lock`]: struct.Stdout.html#method.lock /// /// ### Note: Windows Portability Consideration /// When operating in a console, the Windows implementation of this stream does not support diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f5018485ef..a8dfe924fd 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -681,14 +681,15 @@ mod while_keyword { } /// # break; /// } /// -/// let mut i = 0; +/// let mut i = 1; /// loop { /// println!("i is {}", i); -/// if i > 10 { +/// if i > 100 { /// break; /// } -/// i += 1; +/// i *= 2; /// } +/// assert_eq!(i, 128); /// ``` /// /// Unlike the other kinds of loops in Rust (`while`, `while let`, and `for`), loops can be used as @@ -984,7 +985,6 @@ mod where_keyword { } // 2018 Edition keywords -#[unstable(feature = "async_await", issue = "50547")] #[doc(keyword = "async")] // /// Return a [`Future`] instead of blocking the current thread. @@ -995,7 +995,6 @@ mod where_keyword { } /// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod async_keyword { } -#[unstable(feature = "async_await", issue = "50547")] #[doc(keyword = "await")] // /// Suspend execution until the result of a [`Future`] is ready. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ba80d1b700..21aeb9c26f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -228,7 +228,6 @@ // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. -#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -239,18 +238,18 @@ #![feature(array_error_internals)] #![feature(asm)] #![feature(associated_type_bounds)] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] -#![feature(checked_duration_since)] #![feature(clamp)] #![feature(compiler_builtins_lib)] #![feature(concat_idents)] #![feature(const_cstr_unchecked)] #![feature(const_raw_ptr_deref)] +#![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] #![feature(doc_alias)] @@ -453,6 +452,7 @@ pub mod f64; #[macro_use] pub mod thread; pub mod ascii; +pub mod backtrace; pub mod collections; pub mod env; pub mod error; @@ -513,7 +513,7 @@ pub use std_detect::detect; // Re-export macros defined in libcore. #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] +#[allow(deprecated, deprecated_in_future)] pub use core::{ // Stable assert_eq, @@ -531,7 +531,6 @@ pub use core::{ }; // Re-export built-in macros defined through libcore. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::{ // Stable @@ -551,7 +550,6 @@ pub use core::{ option_env, stringify, // Unstable - __rust_unstable_column, asm, concat_idents, format_args_nl, diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index f2000936b9..cbeaf20b13 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -53,20 +53,20 @@ /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)] +#[allow_internal_unstable(libstd_sys_internals)] macro_rules! panic { () => ({ $crate::panic!("explicit panic") }); ($msg:expr) => ({ - $crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!())) + $crate::rt::begin_panic($msg, &($crate::file!(), $crate::line!(), $crate::column!())) }); ($msg:expr,) => ({ $crate::panic!($msg) }); ($fmt:expr, $($arg:tt)+) => ({ - $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+), - &(file!(), line!(), __rust_unstable_column!())) + $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+), + &($crate::file!(), $crate::line!(), $crate::column!())) }); } @@ -113,7 +113,7 @@ macro_rules! panic { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(print_internals)] macro_rules! print { - ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*))); } /// Prints to the standard output, with a newline. @@ -147,7 +147,7 @@ macro_rules! print { macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ({ - $crate::io::_print(format_args_nl!($($arg)*)); + $crate::io::_print($crate::format_args_nl!($($arg)*)); }) } @@ -176,7 +176,7 @@ macro_rules! println { #[stable(feature = "eprint", since = "1.19.0")] #[allow_internal_unstable(print_internals)] macro_rules! eprint { - ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*))); } /// Prints to the standard error, with a newline. @@ -206,7 +206,7 @@ macro_rules! eprint { macro_rules! eprintln { () => ($crate::eprint!("\n")); ($($arg:tt)*) => ({ - $crate::io::_eprint(format_args_nl!($($arg)*)); + $crate::io::_eprint($crate::format_args_nl!($($arg)*)); }) } @@ -337,7 +337,7 @@ macro_rules! eprintln { #[stable(feature = "dbg_macro", since = "1.32.0")] macro_rules! dbg { () => { - $crate::eprintln!("[{}:{}]", file!(), line!()); + $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!()); }; ($val:expr) => { // Use of `match` here is intentional because it affects the lifetimes @@ -345,7 +345,7 @@ macro_rules! dbg { match $val { tmp => { $crate::eprintln!("[{}:{}] {} = {:#?}", - file!(), line!(), stringify!($val), &tmp); + $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp); tmp } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index cdffa39022..d8b6fb6da9 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1597,7 +1597,8 @@ mod tests { // FIXME: re-enabled openbsd tests once their socket timeout code // no longer has rounding errors. - #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)] + // VxWorks ignores SO_SNDTIMEO. + #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 #[test] fn timeouts() { diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index c430e10395..a5e7cd992f 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -1026,7 +1026,8 @@ mod tests { // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code // no longer has rounding errors. - #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)] + // VxWorks ignores SO_SNDTIMEO. + #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] #[test] fn timeouts() { let addr = next_test_ip4(); diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs index 0761c50f4b..611a1709c8 100644 --- a/src/libstd/os/raw/mod.rs +++ b/src/libstd/os/raw/mod.rs @@ -8,8 +8,7 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -33,8 +32,7 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64")))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -58,51 +56,37 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "schar.md"))] +#[doc(include = "schar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))] +#[doc(include = "uchar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))] -#[cfg_attr(not(bootstrap), doc(include = "short.md"))] +#[doc(include = "short.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; -#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))] +#[doc(include = "ushort.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; -#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))] -#[cfg_attr(not(bootstrap), doc(include = "int.md"))] +#[doc(include = "int.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uint.md"))] +#[doc(include = "uint.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))] +#[doc(include = "longlong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))] +#[doc(include = "ulonglong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))] -#[cfg_attr(not(bootstrap), doc(include = "float.md"))] +#[doc(include = "float.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; -#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))] -#[cfg_attr(not(bootstrap), doc(include = "double.md"))] +#[doc(include = "double.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; #[stable(feature = "raw_os", since = "1.1.0")] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 952fd9ebfd..28fb402440 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -17,8 +17,7 @@ use crate::ptr; use crate::raw; use crate::sys::stdio::panic_output; use crate::sys_common::rwlock::RWLock; -use crate::sys_common::thread_info; -use crate::sys_common::util; +use crate::sys_common::{thread_info, util, backtrace}; use crate::thread; #[cfg(not(test))] @@ -157,20 +156,18 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { } fn default_hook(info: &PanicInfo<'_>) { - #[cfg(feature = "backtrace")] - use crate::sys_common::backtrace; - // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. - #[cfg(feature = "backtrace")] - let log_backtrace = { + let log_backtrace = if cfg!(feature = "backtrace") { let panics = update_panic_count(0); if panics >= 2 { - Some(backtrace::PrintFormat::Full) + Some(backtrace_rs::PrintFmt::Full) } else { backtrace::log_enabled() } + } else { + None }; // The current implementation always returns `Some`. @@ -190,8 +187,7 @@ fn default_hook(info: &PanicInfo<'_>) { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); - #[cfg(feature = "backtrace")] - { + if cfg!(feature = "backtrace") { use crate::sync::atomic::{AtomicBool, Ordering}; static FIRST_PANIC: AtomicBool = AtomicBool::new(true); diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 1c61f21f7d..3e4cf91127 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -7,10 +7,6 @@ #![stable(feature = "rust1", since = "1.0.0")] // Re-exported core operators -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::marker::Copy; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::marker::{Send, Sized, Sync, Unpin}; @@ -24,21 +20,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; pub use crate::mem::drop; // Re-exported types and traits -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::clone::Clone; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::convert::{AsRef, AsMut, Into, From}; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::default::Default; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::iter::{Iterator, Extend, IntoIterator}; @@ -53,11 +37,9 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use core::prelude::v1::{ - __rust_unstable_column, asm, assert, cfg, @@ -83,7 +65,6 @@ pub use core::prelude::v1::{ // FIXME: Attribute and derive macros are not documented because for them rustdoc generates // dead links which fail link checker testing. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(hidden)] diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index d9a3da66a6..45816ffd22 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -655,7 +655,7 @@ mod prim_slice { } /// [`len`]: #method.len /// /// Note: This example shows the internals of `&str`. `unsafe` should not be -/// used to get a string slice under normal circumstances. Use `as_slice` +/// used to get a string slice under normal circumstances. Use `as_str` /// instead. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str { } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 000f80f99e..da136ca6bf 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -422,7 +422,7 @@ impl fmt::Debug for ChildStderr { /// // Execute `ls` in the current directory of the program. /// list_dir.status().expect("process failed to execute"); /// -/// println!(""); +/// println!(); /// /// // Change `ls` to execute in the root directory. /// list_dir.current_dir("/"); @@ -935,12 +935,12 @@ impl Stdio { /// .expect("Failed to spawn child process"); /// /// { - /// let mut stdin = child.stdin.as_mut().expect("Failed to open stdin"); + /// let stdin = child.stdin.as_mut().expect("Failed to open stdin"); /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); /// } /// /// let output = child.wait_with_output().expect("Failed to read stdout"); - /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH\n"); + /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) } @@ -1595,7 +1595,7 @@ pub fn id() -> u32 { /// A trait for implementing arbitrary return types in the `main` function. /// -/// The c-main function only supports to return integers as return type. +/// The C-main function only supports to return integers as return type. /// So, every type implementing the `Termination` trait has to be converted /// to an integer. /// diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index aeff57716e..65ce19f2a1 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -28,14 +28,14 @@ impl WaitTimeoutResult { /// once the boolean has been updated and notified. /// /// ``` - /// use std::sync::{Arc, Mutex, Condvar}; + /// use std::sync::{Arc, Condvar, Mutex}; /// use std::thread; /// use std::time::Duration; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// - /// thread::spawn(move|| { + /// thread::spawn(move || { /// let (lock, cvar) = &*pair2; /// /// // Let's wait 20 milliseconds before notifying the condvar. diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index e29faf18d8..fd6e46fd61 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -163,7 +163,6 @@ pub use self::condvar::{Condvar, WaitTimeoutResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::mutex::{Mutex, MutexGuard}; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] #[allow(deprecated)] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs index 9addba8b61..38db4dd516 100644 --- a/src/libstd/sys/cloudabi/abi/cloudabi.rs +++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs @@ -115,6 +115,7 @@ #![no_std] #![allow(non_camel_case_types)] +#![allow(deprecated)] // FIXME: using `mem::uninitialized()` include!("bitflags.rs"); diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs index 6e147612eb..2fb10cc370 100644 --- a/src/libstd/sys/cloudabi/mod.rs +++ b/src/libstd/sys/cloudabi/mod.rs @@ -1,5 +1,3 @@ -#![allow(deprecated_in_future)] // mem::uninitialized; becomes `deprecated` when nightly is 1.39 - use crate::io::ErrorKind; use crate::mem; diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs index d3ff0077b2..0e30d3a1c6 100644 --- a/src/libstd/sys/cloudabi/mutex.rs +++ b/src/libstd/sys/cloudabi/mutex.rs @@ -104,10 +104,11 @@ impl ReentrantMutex { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::::uninit(); + let mut nevents = MaybeUninit::::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex"); + let event = event.assume_init(); assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex"); } } diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs index 6da3f3841b..73499d65a0 100644 --- a/src/libstd/sys/cloudabi/rwlock.rs +++ b/src/libstd/sys/cloudabi/rwlock.rs @@ -1,5 +1,6 @@ use crate::cell::UnsafeCell; use crate::mem; +use crate::mem::MaybeUninit; use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sys::cloudabi::abi; @@ -73,10 +74,11 @@ impl RWLock { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::::uninit(); + let mut nevents = MaybeUninit::::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock"); + let event = event.assume_init(); assert_eq!( event.error, abi::errno::SUCCESS, @@ -182,10 +184,11 @@ impl RWLock { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::::uninit(); + let mut nevents = MaybeUninit::::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock"); + let event = event.assume_init(); assert_eq!( event.error, abi::errno::SUCCESS, diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs index e719b362cb..03a59d6d7c 100644 --- a/src/libstd/sys/cloudabi/shims/process.rs +++ b/src/libstd/sys/cloudabi/shims/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv, + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -37,7 +39,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) {} - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 7da16c4d24..240b6ea9e5 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -72,10 +72,11 @@ impl Thread { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = mem::MaybeUninit::::uninit(); + let mut nevents = mem::MaybeUninit::::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS); + let event = event.assume_init(); assert_eq!(event.error, abi::errno::SUCCESS); } } diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index 000bb19f26..cc1c04a83e 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -27,8 +27,7 @@ impl Condvar { pub unsafe fn wait(&self, mutex: &Mutex) { let guard = self.inner.lock(); - mutex.unlock(); - WaitQueue::wait(guard); + WaitQueue::wait(guard, || mutex.unlock()); mutex.lock() } diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs index f325fb1dd5..662da8b3f6 100644 --- a/src/libstd/sys/sgx/mutex.rs +++ b/src/libstd/sys/sgx/mutex.rs @@ -22,7 +22,7 @@ impl Mutex { let mut guard = self.inner.lock(); if *guard.lock_var() { // Another thread has the lock, wait - WaitQueue::wait(guard) + WaitQueue::wait(guard, ||{}) // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -83,7 +83,7 @@ impl ReentrantMutex { match guard.lock_var().owner { Some(tcs) if tcs != thread::current() => { // Another thread has the lock, wait - WaitQueue::wait(guard); + WaitQueue::wait(guard, ||{}); // Another thread has passed the lock to us }, _ => { diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs index a02e009d95..edf933d10e 100644 --- a/src/libstd/sys/sgx/process.rs +++ b/src/libstd/sys/sgx/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 30c47e44ee..e2f94b1d92 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -31,7 +31,7 @@ impl RWLock { if *wguard.lock_var() || !wguard.queue_empty() { // Another thread has or is waiting for the write lock, wait drop(wguard); - WaitQueue::wait(rguard); + WaitQueue::wait(rguard, ||{}); // Another thread has passed the lock to us } else { // No waiting writers, acquire the read lock @@ -62,7 +62,7 @@ impl RWLock { if *wguard.lock_var() || rguard.lock_var().is_some() { // Another thread has the lock, wait drop(rguard); - WaitQueue::wait(wguard); + WaitQueue::wait(wguard, ||{}); // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -97,6 +97,7 @@ impl RWLock { if let Ok(mut wguard) = WaitQueue::notify_one(wguard) { // A writer was waiting, pass the lock *wguard.lock_var_mut() = true; + wguard.drop_after(rguard); } else { // No writers were waiting, the lock is released rtassert!(rguard.queue_empty()); @@ -117,21 +118,26 @@ impl RWLock { rguard: SpinMutexGuard<'_, WaitVariable>>, wguard: SpinMutexGuard<'_, WaitVariable>, ) { - if let Err(mut wguard) = WaitQueue::notify_one(wguard) { - // No writers waiting, release the write lock - *wguard.lock_var_mut() = false; - if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { - // One or more readers were waiting, pass the lock to them - if let NotifiedTcs::All { count } = rguard.notified_tcs() { - *rguard.lock_var_mut() = Some(count) + match WaitQueue::notify_one(wguard) { + Err(mut wguard) => { + // No writers waiting, release the write lock + *wguard.lock_var_mut() = false; + if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { + // One or more readers were waiting, pass the lock to them + if let NotifiedTcs::All { count } = rguard.notified_tcs() { + *rguard.lock_var_mut() = Some(count) + } else { + unreachable!() // called notify_all + } + rguard.drop_after(wguard); } else { - unreachable!() // called notify_all + // No readers waiting, the lock is released } - } else { - // No readers waiting, the lock is released + }, + Ok(wguard) => { + // There was a thread waiting for write, just pass the lock + wguard.drop_after(rguard); } - } else { - // There was a thread waiting for write, just pass the lock } } diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index d542f9b410..3cb40e509b 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -98,6 +98,12 @@ impl<'a, T> WaitGuard<'a, T> { pub fn notified_tcs(&self) -> NotifiedTcs { self.notified_tcs } + + /// Drop this `WaitGuard`, after dropping another `guard`. + pub fn drop_after(self, guard: U) { + drop(guard); + drop(self); + } } impl<'a, T> Deref for WaitGuard<'a, T> { @@ -140,7 +146,7 @@ impl WaitQueue { /// until a wakeup event. /// /// This function does not return until this thread has been awoken. - pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>) { + pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>, before_wait: F) { // very unsafe: check requirements of UnsafeList::push unsafe { let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry { @@ -149,6 +155,7 @@ impl WaitQueue { })); let entry = guard.queue.inner.push(&mut entry); drop(guard); + before_wait(); while !entry.lock().wake { // don't panic, this would invalidate `entry` during unwinding let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); @@ -545,7 +552,7 @@ mod tests { assert!(WaitQueue::notify_one(wq2.lock()).is_ok()); }); - WaitQueue::wait(locked); + WaitQueue::wait(locked, ||{}); t1.join().unwrap(); } diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index bba4b21c46..056a20345f 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -1,5 +1,6 @@ pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; +pub use crate::ffi::OsString as EnvKey; mod process_common; #[cfg(not(target_os = "fuchsia"))] diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 6bb20bbe08..713d308555 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -1,25 +1,57 @@ use crate::os::unix::prelude::*; -use crate::ffi::{OsString, OsStr, CString, CStr}; +use crate::ffi::{OsString, OsStr, CString}; use crate::fmt; use crate::io; use crate::ptr; use crate::sys::fd::FileDesc; -use crate::sys::fs::{File, OpenOptions}; +use crate::sys::fs::File; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; +#[cfg(not(target_os = "fuchsia"))] +use { + crate::ffi::CStr, + crate::sys::fs::OpenOptions, +}; + use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; cfg_if::cfg_if! { - if #[cfg(target_os = "redox")] { + if #[cfg(target_os = "fuchsia")] { + // fuchsia doesn't have /dev/null + } else if #[cfg(target_os = "redox")] { const DEV_NULL: &'static str = "null:\0"; } else { const DEV_NULL: &'static str = "/dev/null\0"; } } +// Android with api less than 21 define sig* functions inline, so it is not +// available for dynamic link. Implementing sigemptyset and sigaddset allow us +// to support older Android version (independent of libc version). +// The following implementations are based on https://git.io/vSkNf +cfg_if::cfg_if! { + if #[cfg(target_os = "android")] { + pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { + set.write_bytes(0u8, 1); + return 0; + } + #[allow(dead_code)] + pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { + use crate::{slice, mem}; + + let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); + let bit = (signum - 1) as usize; + raw[bit / 8] |= 1 << (bit % 8); + return 0; + } + } else { + pub use libc::{sigemptyset, sigaddset}; + } +} + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -45,7 +77,7 @@ pub struct Command { program: CString, args: Vec, argv: Argv, - env: CommandEnv, + env: CommandEnv, cwd: Option, uid: Option, @@ -83,6 +115,11 @@ pub enum ChildStdio { Inherit, Explicit(c_int), Owned(FileDesc), + + // On Fuchsia, null stdio is the default, so we simply don't specify + // any actions at the time of spawning. + #[cfg(target_os = "fuchsia")] + Null, } pub enum Stdio { @@ -177,7 +214,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -247,7 +284,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); @@ -301,6 +338,7 @@ impl Stdio { Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours))) } + #[cfg(not(target_os = "fuchsia"))] Stdio::Null => { let mut opts = OpenOptions::new(); opts.read(readable); @@ -311,6 +349,11 @@ impl Stdio { let fd = File::open_c(&path, &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } + + #[cfg(target_os = "fuchsia")] + Stdio::Null => { + Ok((ChildStdio::Null, None)) + } } } } @@ -333,6 +376,9 @@ impl ChildStdio { ChildStdio::Inherit => None, ChildStdio::Explicit(fd) => Some(fd), ChildStdio::Owned(ref fd) => Some(fd.raw()), + + #[cfg(target_os = "fuchsia")] + ChildStdio::Null => None, } } } @@ -429,36 +475,6 @@ mod tests { } } - // Android with api less than 21 define sig* functions inline, so it is not - // available for dynamic link. Implementing sigemptyset and sigaddset allow us - // to support older Android version (independent of libc version). - // The following implementations are based on https://git.io/vSkNf - - #[cfg(not(target_os = "android"))] - extern { - #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] - fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] - fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; - } - - #[cfg(target_os = "android")] - unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { - set.write_bytes(0u8, 1); - return 0; - } - - #[cfg(target_os = "android")] - unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { - use crate::slice; - - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); - let bit = (signum - 1) as usize; - raw[bit / 8] |= 1 << (bit % 8); - return 0; - } - // See #14232 for more information, but it appears that signal delivery to a // newly spawned process may just be raced in the macOS, so to prevent this // test from being flaky we ignore it on macOS. diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 7c6be9b0a6..fff9fc6b3b 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -48,30 +48,51 @@ impl Command { use crate::sys::process::zircon::*; let envp = match maybe_envp { - Some(envp) => envp.as_ptr(), + // None means to clone the current environment, which is done in the + // flags below. None => ptr::null(), + Some(envp) => envp.as_ptr(), }; - let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd { - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_TRANSFER_FD, - local_fd, - target_fd, - ..Default::default() - } - } else { - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_CLONE_FD, - local_fd: target_fd, - target_fd, - ..Default::default() + let make_action = |local_io: &ChildStdio, target_fd| -> io::Result { + if let Some(local_fd) = local_io.fd() { + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd, + target_fd, + ..Default::default() + }) + } else { + if let ChildStdio::Null = local_io { + // acts as no-op + return Ok(Default::default()); + } + + let mut handle = ZX_HANDLE_INVALID; + let status = fdio_fd_clone(target_fd, &mut handle); + if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED { + // This descriptor is closed; skip it rather than generating an + // error. + return Ok(Default::default()); + } + zx_cvt(status)?; + + let mut cloned_fd = 0; + zx_cvt(fdio_fd_create(handle, &mut cloned_fd))?; + + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd: cloned_fd as i32, + target_fd, + ..Default::default() + }) } }; // Clone stdin, stdout, and stderr - let action1 = transfer_or_clone(stdio.stdin.fd(), 0); - let action2 = transfer_or_clone(stdio.stdout.fd(), 1); - let action3 = transfer_or_clone(stdio.stderr.fd(), 2); + let action1 = make_action(&stdio.stdin, 0)?; + let action2 = make_action(&stdio.stdout, 1)?; + let action3 = make_action(&stdio.stderr, 2)?; let actions = [action1, action2, action3]; // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc @@ -84,9 +105,11 @@ impl Command { let mut process_handle: zx_handle_t = 0; zx_cvt(fdio_spawn_etc( - 0, - FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, - self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(), + ZX_HANDLE_INVALID, + FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE + | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null + self.get_argv()[0], self.get_argv().as_ptr(), envp, + actions.len() as size_t, actions.as_ptr(), &mut process_handle, ptr::null_mut(), ))?; diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 327d82e60c..e6a742bd45 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -178,23 +178,22 @@ impl Command { cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?; } - if cfg!(not(any(target_os = "l4re"))) { + #[cfg(not(target_os = "l4re"))] + { if let Some(u) = self.get_gid() { cvt(libc::setgid(u as gid_t))?; } if let Some(u) = self.get_uid() { + // When dropping privileges from root, the `setgroups` call + // will remove any extraneous groups. If we don't call this, + // then even though our uid has dropped, we may still have + // groups that enable us to do super-user things. This will + // fail if we aren't root, so don't bother checking the + // return value, this is just done as an optimistic + // privilege dropping function. //FIXME: Redox kernel does not support setgroups yet - if cfg!(not(target_os = "redox")) { - // When dropping privileges from root, the `setgroups` call - // will remove any extraneous groups. If we don't call this, - // then even though our uid has dropped, we may still have - // groups that enable us to do super-user things. This will - // fail if we aren't root, so don't bother checking the - // return value, this is just done as an optimistic - // privilege dropping function. - let _ = libc::setgroups(0, ptr::null()); - } - + #[cfg(not(target_os = "redox"))] + let _ = libc::setgroups(0, ptr::null()); cvt(libc::setuid(u as uid_t))?; } } @@ -203,7 +202,7 @@ impl Command { } // emscripten has no signal support. - #[cfg(not(any(target_os = "emscripten")))] + #[cfg(not(target_os = "emscripten"))] { use crate::mem::MaybeUninit; // Reset signal handling so the child process starts in a @@ -214,14 +213,7 @@ impl Command { // need to clean things up now to avoid confusing the program // we're about to run. let mut set = MaybeUninit::::uninit(); - if cfg!(target_os = "android") { - // Implementing sigemptyset allow us to support older Android - // versions. See the comment about Android and sig* functions in - // process_common.rs - set.as_mut_ptr().write_bytes(0u8, 1); - } else { - cvt(libc::sigemptyset(set.as_mut_ptr()))?; - } + cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?; let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); @@ -363,10 +355,10 @@ impl Command { } let mut set = MaybeUninit::::uninit(); - cvt(libc::sigemptyset(set.as_mut_ptr()))?; + cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(), set.as_ptr()))?; - cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?; + cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?; cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(), set.as_ptr()))?; diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index ec715d5490..1ba48de3c0 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -2,8 +2,9 @@ use crate::convert::TryInto; use crate::io; +use crate::i64; +use crate::mem::MaybeUninit; use crate::os::raw::c_char; -use crate::u64; use libc::{c_int, c_void, size_t}; @@ -14,8 +15,8 @@ pub type zx_status_t = i32; pub const ZX_HANDLE_INVALID: zx_handle_t = 0; -pub type zx_time_t = u64; -pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX; +pub type zx_time_t = i64; +pub const ZX_TIME_INFINITE : zx_time_t = i64::MAX; pub type zx_signals_t = u32; @@ -120,8 +121,11 @@ pub struct fdio_spawn_action_t { extern { pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char, - action_count: u64, actions: *const fdio_spawn_action_t, + action_count: size_t, actions: *const fdio_spawn_action_t, process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t; + + pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t; + pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t; } // fdio_spawn_etc flags diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 02f377d55c..fd6796ad22 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -311,6 +311,7 @@ mod inner { pub fn actually_monotonic() -> bool { (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) || (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) || + cfg!(target_os = "fuchsia") || false // last clause, used so `||` is always trailing above } diff --git a/src/libstd/sys/vxworks/backtrace/mod.rs b/src/libstd/sys/vxworks/backtrace/mod.rs deleted file mode 100644 index 0887e5a4df..0000000000 --- a/src/libstd/sys/vxworks/backtrace/mod.rs +++ /dev/null @@ -1,110 +0,0 @@ -/// Backtrace support built on libgcc with some extra OS-specific support -/// -/// Some methods of getting a backtrace: -/// -/// * The backtrace() functions on unix. It turns out this doesn't work very -/// well for green threads on macOS, and the address to symbol portion of it -/// suffers problems that are described below. -/// -/// * Using libunwind. This is more difficult than it sounds because libunwind -/// isn't installed everywhere by default. It's also a bit of a hefty library, -/// so possibly not the best option. When testing, libunwind was excellent at -/// getting both accurate backtraces and accurate symbols across platforms. -/// This route was not chosen in favor of the next option, however. -/// -/// * We're already using libgcc_s for exceptions in rust (triggering thread -/// unwinding and running destructors on the stack), and it turns out that it -/// conveniently comes with a function that also gives us a backtrace. All of -/// these functions look like _Unwind_*, but it's not quite the full -/// repertoire of the libunwind API. Due to it already being in use, this was -/// the chosen route of getting a backtrace. -/// -/// After choosing libgcc_s for backtraces, the sad part is that it will only -/// give us a stack trace of instruction pointers. Thankfully these instruction -/// pointers are accurate (they work for green and native threads), but it's -/// then up to us again to figure out how to translate these addresses to -/// symbols. As with before, we have a few options. Before, that, a little bit -/// of an interlude about symbols. This is my very limited knowledge about -/// symbol tables, and this information is likely slightly wrong, but the -/// general idea should be correct. -/// -/// When talking about symbols, it's helpful to know a few things about where -/// symbols are located. Some symbols are located in the dynamic symbol table -/// of the executable which in theory means that they're available for dynamic -/// linking and lookup. Other symbols end up only in the local symbol table of -/// the file. This loosely corresponds to pub and priv functions in Rust. -/// -/// Armed with this knowledge, we know that our solution for address to symbol -/// translation will need to consult both the local and dynamic symbol tables. -/// With that in mind, here's our options of translating an address to -/// a symbol. -/// -/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr() -/// behind the scenes to translate, and this is why backtrace() was not used. -/// Conveniently, this method works fantastically on macOS. It appears dladdr() -/// uses magic to consult the local symbol table, or we're putting everything -/// in the dynamic symbol table anyway. Regardless, for macOS, this is the -/// method used for translation. It's provided by the system and easy to do.o -/// -/// Sadly, all other systems have a dladdr() implementation that does not -/// consult the local symbol table. This means that most functions are blank -/// because they don't have symbols. This means that we need another solution. -/// -/// * Use unw_get_proc_name(). This is part of the libunwind api (not the -/// libgcc_s version of the libunwind api), but involves taking a dependency -/// to libunwind. We may pursue this route in the future if we bundle -/// libunwind, but libunwind was unwieldy enough that it was not chosen at -/// this time to provide this functionality. -/// -/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a -/// semi-reasonable solution. The stdlib already knows how to spawn processes, -/// so in theory it could invoke readelf, parse the output, and consult the -/// local/dynamic symbol tables from there. This ended up not getting chosen -/// due to the craziness of the idea plus the advent of the next option. -/// -/// * Use `libbacktrace`. It turns out that this is a small library bundled in -/// the gcc repository which provides backtrace and symbol translation -/// functionality. All we really need from it is the backtrace functionality, -/// and we only really need this on everything that's not macOS, so this is the -/// chosen route for now. -/// -/// In summary, the current situation uses libgcc_s to get a trace of stack -/// pointers, and we use dladdr() or libbacktrace to translate these addresses -/// to symbols. This is a bit of a hokey implementation as-is, but it works for -/// all unix platforms we support right now, so it at least gets the job done. - -pub use self::tracing::unwind_backtrace; -pub use self::printing::{foreach_symbol_fileline, resolve_symname}; - -// tracing impls: -mod tracing; -// symbol resolvers: -mod printing; - -#[cfg(not(target_os = "emscripten"))] -pub mod gnu { - use crate::io; - use crate::fs; - - use libc::c_char; - - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { - use crate::env; - use crate::os::unix::ffi::OsStrExt; - - let filename = env::current_exe()?; - let file = fs::File::open(&filename)?; - let mut filename_cstr: Vec<_> = filename.as_os_str().as_bytes().iter() - .map(|&x| x as c_char).collect(); - filename_cstr.push(0); // Null terminate - Ok((filename_cstr, file)) - } -} - -pub struct BacktraceContext; diff --git a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs deleted file mode 100644 index 202164dd3c..0000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::io; -use crate::intrinsics; -use crate::ffi::CStr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -pub fn resolve_symname(frame: Frame, - callback: F, - _: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> -{ - unsafe { - let mut info: Dl_info = intrinsics::init(); - let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 || - info.dli_sname.is_null() { - None - } else { - CStr::from_ptr(info.dli_sname).to_str().ok() - }; - callback(symname) - } -} - -#[repr(C)] -struct Dl_info { - dli_fname: *const libc::c_char, - dli_fbase: *mut libc::c_void, - dli_sname: *const libc::c_char, - dli_saddr: *mut libc::c_void, -} - -extern { - #[ link_name = "_rtld_dladdr" ] - fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/printing/mod.rs b/src/libstd/sys/vxworks/backtrace/printing/mod.rs deleted file mode 100644 index d090caede4..0000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod dladdr; - -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; -use crate::io; - -#[cfg(target_os = "emscripten")] -pub use self::dladdr::resolve_symname; - -#[cfg(target_os = "emscripten")] -pub fn foreach_symbol_fileline(_: Frame, _: F, _: &BacktraceContext) -> io::Result -where - F: FnMut(&[u8], u32) -> io::Result<()> -{ - Ok(false) -} - -#[cfg(not(target_os = "emscripten"))] -pub use crate::sys_common::gnu::libbacktrace::foreach_symbol_fileline; - -#[cfg(not(target_os = "emscripten"))] -pub fn resolve_symname(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()> -where - F: FnOnce(Option<&str>) -> io::Result<()> -{ - crate::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| { - if symname.is_some() { - callback(symname) - } else { - dladdr::resolve_symname(frame, callback, bc) - } - }, bc) -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs deleted file mode 100644 index a628d107ad..0000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs +++ /dev/null @@ -1,39 +0,0 @@ -/// As always - iOS on arm uses SjLj exceptions and -/// _Unwind_Backtrace is even not available there. Still, -/// backtraces could be extracted using a backtrace function, -/// which thanks god is public -/// -/// As mentioned in a huge comment block in `super::super`, backtrace -/// doesn't play well with green threads, so while it is extremely nice and -/// simple to use it should be used only on iOS devices as the only viable -/// option. - -use crate::io; -use crate::ptr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - const FRAME_LEN: usize = 100; - assert!(FRAME_LEN >= frames.len()); - let mut raw_frames = [ptr::null_mut(); FRAME_LEN]; - let nb_frames = unsafe { - backtrace(raw_frames.as_mut_ptr(), raw_frames.len() as libc::c_int) - } as usize; - for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) { - *to = Frame { - exact_position: *from as *mut u8, - symbol_addr: *from as *mut u8, - inline_context: 0, - }; - } - Ok((nb_frames as usize, BacktraceContext)) -} - -extern { - fn backtrace(buf: *mut *mut libc::c_void, sz: libc::c_int) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs deleted file mode 100644 index e6379132ba..0000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::error::Error; -use crate::fmt; -use crate::io; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -use unwind as uw; - -struct Context<'a> { - idx: usize, - frames: &'a mut [Frame], -} - -#[derive(Debug)] -struct UnwindError(uw::_Unwind_Reason_Code); - -impl Error for UnwindError { - fn description(&self) -> &'static str { - "unexpected return value while unwinding" - } -} - -impl fmt::Display for UnwindError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}: {:?}", self.description(), self.0) - } -} - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - let mut cx = Context { - idx: 0, - frames, - }; - let result_unwind = unsafe { - uw::_Unwind_Backtrace(trace_fn, - &mut cx as *mut Context<'_> - as *mut libc::c_void) - }; - // See libunwind:src/unwind/Backtrace.c for the return values. - // No, there is no doc. - match result_unwind { - // These return codes seem to be benign and need to be ignored for backtraces - // to show up properly on all tested platforms. - uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { - Ok((cx.idx, BacktraceContext)) - } - _ => { - Err(io::Error::new(io::ErrorKind::Other, - UnwindError(result_unwind))) - } - } -} - -extern fn trace_fn(ctx: *mut uw::_Unwind_Context, - arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { - let cx = unsafe { &mut *(arg as *mut Context<'_>) }; - if cx.idx >= cx.frames.len() { - return uw::_URC_NORMAL_STOP; - } - - let mut ip_before_insn = 0; - let mut ip = unsafe { - uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void - }; - if !ip.is_null() && ip_before_insn == 0 { - // this is a non-signaling frame, so `ip` refers to the address - // after the calling instruction. account for that. - ip = (ip as usize - 1) as *mut _; - } - - // dladdr() on osx gets whiny when we use FindEnclosingFunction, and - // it appears to work fine without it, so we only use - // FindEnclosingFunction on non-osx platforms. In doing so, we get a - // slightly more accurate stack trace in the process. - // - // This is often because panic involves the last instruction of a - // function being "call std::rt::begin_unwind", with no ret - // instructions after it. This means that the return instruction - // pointer points *outside* of the calling function, and by - // unwinding it we go back to the original function. - let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { - ip - } else { - unsafe { uw::_Unwind_FindEnclosingFunction(ip) } - }; - - cx.frames[cx.idx] = Frame { - symbol_addr: symaddr as *mut u8, - exact_position: ip as *mut u8, - inline_context: 0, - }; - cx.idx += 1; - - uw::_URC_NO_REASON -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs deleted file mode 100644 index 11863e6454..0000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub use self::imp::*; - -#[cfg(not(all(target_os = "ios", target_arch = "arm")))] -#[path = "gcc_s.rs"] -mod imp; -#[cfg(all(target_os = "ios", target_arch = "arm"))] -#[path = "backtrace_fn.rs"] -mod imp; diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs index f5a2e263d2..8b55939b8e 100644 --- a/src/libstd/sys/vxworks/fast_thread_local.rs +++ b/src/libstd/sys/vxworks/fast_thread_local.rs @@ -1,33 +1,8 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -// Since what appears to be glibc 2.18 this symbol has been shipped which -// GCC and clang both use to invoke destructors in thread_local globals, so -// let's do the same! -// -// Note, however, that we run on lots older linuxes, as well as cross -// compiling from a newer linux to an older linux, so we also have a -// fallback implementation to use as well. -// -// Due to rust-lang/rust#18804, make sure this is not generic! pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use crate::mem; use crate::sys_common::thread_local::register_dtor_fallback; - - extern { - #[linkage = "extern_weak"] - static __dso_handle: *mut u8; - #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; - } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) - (dtor, t, &__dso_handle as *const _ as *mut _); - return - } register_dtor_fallback(t, dtor); } diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs index d537d2258f..51fdb1c0e5 100644 --- a/src/libstd/sys/vxworks/fs.rs +++ b/src/libstd/sys/vxworks/fs.rs @@ -529,7 +529,7 @@ pub fn stat(p: &Path) -> io::Result { let p = cstr(p)?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _) + libc::stat(p.as_ptr(), &mut stat as *mut _ as *mut _) })?; Ok(FileAttr { stat }) } diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs index 5dc35a6176..f4798da187 100644 --- a/src/libstd/sys/vxworks/os.rs +++ b/src/libstd/sys/vxworks/os.rs @@ -287,28 +287,7 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - return crate::env::var_os("HOME").or_else(|| unsafe { - fallback() - }).map(PathBuf::from); - - unsafe fn fallback() -> Option { - let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { - n if n < 0 => 512 as usize, - n => n as usize, - }; - let mut buf = Vec::with_capacity(amt); - let mut passwd: libc::passwd = mem::zeroed(); - let mut result = ptr::null_mut(); - match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(), - buf.capacity(), &mut result) { - 0 if !result.is_null() => { - let ptr = passwd.pw_dir as *const _; - let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); - Some(OsStringExt::from_vec(bytes)) - }, - _ => None, - } - } + None } pub fn exit(code: i32) -> ! { diff --git a/src/libstd/sys/vxworks/process/mod.rs b/src/libstd/sys/vxworks/process/mod.rs index 4dc706006f..3ecbe4e3b2 100644 --- a/src/libstd/sys/vxworks/process/mod.rs +++ b/src/libstd/sys/vxworks/process/mod.rs @@ -1,7 +1,7 @@ pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; +pub use crate::ffi::OsString as EnvKey; mod process_common; #[path = "process_vxworks.rs"] mod process_inner; -mod rtp; diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index 397200c39c..13648abd1e 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -7,7 +7,7 @@ use crate::ptr; use crate::sys::fd::FileDesc; use crate::sys::fs::{File, OpenOptions}; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; @@ -37,7 +37,7 @@ pub struct Command { program: CString, args: Vec, argv: Argv, - env: CommandEnv, + env: CommandEnv, cwd: Option, uid: Option, @@ -155,7 +155,7 @@ impl Command { _f: Box io::Result<()> + Send + Sync>, ) { // Fork() is not supported in vxWorks so no way to run the closure in the new procecss. - unimplemented!();; + unimplemented!(); } pub fn stdin(&mut self, stdin: Stdio) { @@ -170,7 +170,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -240,7 +240,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs index b07966fa20..7446471ae3 100644 --- a/src/libstd/sys/vxworks/process/process_vxworks.rs +++ b/src/libstd/sys/vxworks/process/process_vxworks.rs @@ -3,8 +3,8 @@ use libc::{self, c_int, c_char}; use libc::{RTP_ID}; use crate::sys; use crate::sys::cvt; -use crate::sys::process::rtp; use crate::sys::process::process_common::*; +use crate::sys_common::thread; //////////////////////////////////////////////////////////////////////////////// // Command @@ -52,13 +52,12 @@ impl Command { t!(cvt(libc::chdir(cwd.as_ptr()))); } - let ret = rtp::rtpSpawn( + let ret = libc::rtpSpawn( self.get_argv()[0], // executing program - self.get_argv().as_ptr() as *const _, // argv - *sys::os::environ() as *const *const c_char, + self.get_argv().as_ptr() as *mut *const c_char, // argv + *sys::os::environ() as *mut *const c_char, 100 as c_int, // initial priority - 0x16000, // initial stack size. 0 defaults - // to 0x4000 in 32 bit and 0x8000 in 64 bit + thread::min_stack(), // initial stack size. 0, // options 0 // task options ); @@ -78,7 +77,7 @@ impl Command { libc::close(orig_stderr); } - if ret != rtp::RTP_ID_ERROR { + if ret != libc::RTP_ID_ERROR { p.pid = ret; Ok((p, ours)) } else { diff --git a/src/libstd/sys/vxworks/process/rtp.rs b/src/libstd/sys/vxworks/process/rtp.rs deleted file mode 100644 index 3e6e0017ab..0000000000 --- a/src/libstd/sys/vxworks/process/rtp.rs +++ /dev/null @@ -1,298 +0,0 @@ -#![allow(non_camel_case_types, unused)] - -use libc::{self, c_int, size_t, c_char, BOOL, RTP_DESC, RTP_ID, TASK_ID}; - - -// Copied directly from rtpLibCommon.h, rtpLib.h, signal.h and taskLibCommon.h (for task options) - -// **** definitions for rtpLibCommon.h **** - -pub const RTP_GLOBAL_SYMBOLS : c_int = 0x01; // register global symbols for RTP -pub const RTP_LOCAL_SYMBOLS : c_int = 0x02; // idem for local symbols -pub const RTP_ALL_SYMBOLS : c_int = (RTP_GLOBAL_SYMBOLS | RTP_LOCAL_SYMBOLS); -pub const RTP_DEBUG : c_int = 0x10; // set RTP in debug mode when created -pub const RTP_BUFFER_VAL_OFF : c_int = 0x20; // disable buffer validation for all - // system calls issued from the RTP -pub const RTP_LOADED_WAIT : c_int = 0x40; // Wait until the RTP is loaded -pub const RTP_CPU_AFFINITY_NONE : c_int = 0x80; // Remove any CPU affinity (SMP) - -// Error Status codes - -pub const M_rtpLib : c_int = 178 << 16; - -pub const S_rtpLib_INVALID_FILE : c_int = (M_rtpLib | 1); -pub const S_rtpLib_INVALID_OPTION : c_int = (M_rtpLib | 2); -pub const S_rtpLib_ACCESS_DENIED : c_int = (M_rtpLib | 3); -pub const S_rtpLib_INVALID_RTP_ID : c_int = (M_rtpLib | 4); -pub const S_rtpLib_NO_SYMBOL_TABLE : c_int = (M_rtpLib | 5); -pub const S_rtpLib_INVALID_SEGMENT_START_ADDRESS : c_int = (M_rtpLib | 6); -pub const S_rtpLib_INVALID_SYMBOL_REGISTR_POLICY : c_int = (M_rtpLib | 7); -pub const S_rtpLib_INSTANTIATE_FAILED : c_int = (M_rtpLib | 8); -pub const S_rtpLib_INVALID_TASK_OPTION : c_int = (M_rtpLib | 9); -pub const S_rtpLib_RTP_NAME_LENGTH_EXCEEDED : c_int = (M_rtpLib | 10); // rtpInfoGet - -pub const VX_RTP_NAME_LENGTH : c_int = 255; // max name length for diplay - - -// The 'status' field (32 bit integer) of a RTP holds the RTP state and status. -// -// NOTE: RTP_STATE_GET() : read the RTP state(s) -// RTP_STATE_PUT() : write the RTP state(s) -// RTP_STATE_SET() : set a RTP state -// RTP_STATE_UNSET() : unset a RTP state -// -// RTP_STATUS_GET() : read the RTP status -// RTP_STATUS_PUT() : write the RTP status -// RTP_STATUS_SET() : set a RTP status -// RTP_STATUS_UNSET() : unset a RTP status -// -// The PUT/SET/UNSET macros are available only in the kernel headers. - - -// RTP states - -pub const RTP_STATE_CREATE : c_int = 0x0001; // RrtpStructTP is under construction -pub const RTP_STATE_NORMAL : c_int = 0x0002; // RrtpStructTP is ready -pub const RTP_STATE_DELETE : c_int = 0x0004; // RrtpStructTP is being deleted - -pub const RTP_STATUS_STOP : c_int = 0x0100; // RTP hrtpStructas recieved stopped signal -pub const RTP_STATUS_ELECTED_DELETER : c_int = 0x0200; // RTP drtpStructelete has started - -pub const RTP_STATE_MASK : c_int = (RTP_STATE_CREATE | RTP_STATE_NORMAL | - RTP_STATE_DELETE); -pub const RTP_STATUS_MASK : c_int = (RTP_STATUS_STOP | RTP_STATUS_ELECTED_DELETER); - -pub fn RTP_STATE_GET (value : c_int) -> c_int { - value & RTP_STATE_MASK -} -pub fn RTP_STATUS_GET (value : c_int) -> c_int { - value & RTP_STATUS_MASK -} - -// Indicates that the RTP_ID returned is not valid. - -// RTP_ID_ERROR is supposed to be set to -1, but you can't set -// an unsigned value to a negative without casting, and you -// can't cast unless the size of the integer types are the same, -// but the size of RTP_ID may differ between kernel and user space. -// Bitwise or-ing min and max should get the same result. -pub const RTP_ID_ERROR : RTP_ID = RTP_ID::min_value() | RTP_ID::max_value(); - -// IS_RTP_ C macros - -pub fn IS_RTP_STATE_NORMAL (value : c_int) -> bool { - (RTP_STATE_GET(value) & RTP_STATE_NORMAL) == RTP_STATE_NORMAL -} -pub fn IS_RTP_STATE_CREATE (value : c_int) -> bool { - (RTP_STATE_GET(value) & RTP_STATE_CREATE) == RTP_STATE_CREATE -} -pub fn IS_RTP_STATE_DELETE (value : c_int) -> bool { - (RTP_STATE_GET(value) & RTP_STATE_DELETE) == RTP_STATE_DELETE -} -pub fn IS_RTP_STATUS_STOP (value : c_int) -> bool { - (RTP_STATUS_GET(value) & RTP_STATUS_STOP ) == RTP_STATUS_STOP -} -pub fn IS_RTP_STATUS_ELECTED_DELETER (value : c_int) -> bool { - (RTP_STATUS_GET(value) & RTP_STATUS_ELECTED_DELETER) == RTP_STATUS_ELECTED_DELETER -} - -// **** end of definitions for rtpLibCommon.h **** - - - - -// **** definitions for rtpLib.h **** - -pub fn rtpExit(exitCode : c_int) -> ! { - unsafe{ libc::exit (exitCode) } -} - -/* rtpLib.h in the kernel -pub const RTP_DEL_VIA_TASK_DELETE : c_int = 0x1; // rtpDelete() via taskDestroy() -pub const RTP_DEL_FORCE : c_int = 0x2; // Forceful rtpDelete() -pub const RTP_ID_ANY : RTP_ID = 0; // used for when a kernel task - // wants to wait for the next - // RTP to finish - - -// Function pointers - -pub type RTP_PRE_CREATE_HOOK = size_t; -pub type RTP_POST_CREATE_HOOK = size_t; -pub type RTP_INIT_COMPLETE_HOOK = size_t; -pub type RTP_DELETE_HOOK = size_t; -*/ - -// **** end of definitions for rtpLib.h **** - - - - - -// **** definitions for signal.h **** -pub fn rtpKill(rtpId : RTP_ID, signo : c_int) -> c_int { - unsafe{ libc::kill(rtpId as c_int, signo) } -} - -pub fn rtpSigqueue(rtpId : RTP_ID, signo : c_int, value : size_t) -> c_int { - unsafe{ libc::sigqueue(rtpId as c_int, signo, value) } -} - -pub fn _rtpSigqueue(rtpId : RTP_ID, signo : c_int, value : *mut size_t, code : c_int) -> c_int { - unsafe{ libc::_sigqueue(rtpId, signo, value, code) } -} - -pub fn taskRaise(signo : c_int) -> c_int { - unsafe{ libc::taskKill(libc::taskIdSelf(), signo) } -} -pub fn rtpRaise(signo : c_int) -> c_int { - unsafe{ libc::raise(signo) } -} - -// **** end of definitions for signal.h **** - - - -// **** definitions for taskLibCommon.h **** -pub const VX_PRIVATE_ENV : c_int = 0x0080; // 1 = private environment variables -pub const VX_NO_STACK_FILL : c_int = 0x0100; // 1 = avoid stack fill of 0xee -pub const VX_PRIVATE_UMASK : c_int = 0x0400; // 1 = private file creation mode mask -pub const VX_TASK_NOACTIVATE : c_int = 0x2000; // taskOpen() does not taskActivate() -pub const VX_NO_STACK_PROTECT : c_int = 0x4000; // no over/underflow stack protection, - // stack space remains executable - -// define for all valid user task options - -pub const VX_USR_TASK_OPTIONS_BASE: c_int = (VX_PRIVATE_ENV | - VX_NO_STACK_FILL | - VX_TASK_NOACTIVATE | - VX_NO_STACK_PROTECT | - VX_PRIVATE_UMASK); - -// **** end of definitions for taskLibCommon.h **** - - - -extern "C" { -// functions in rtpLibCommon.h - -// forward declarations - pub fn rtpSpawn ( - pubrtpFileName : *const c_char, - argv : *const *const c_char, - envp : *const *const c_char, - priority : c_int, - uStackSize : size_t, - options : c_int, - taskOptions : c_int, - ) -> RTP_ID; - - pub fn rtpInfoGet ( - rtpId : RTP_ID, - rtpStruct : *mut RTP_DESC, - ) -> c_int; - -/* functions in rtpLib.h for kernel - - - // function declarations - - pub fn rtpDelete ( - id : RTP_ID, - options : c_int, - status : c_int, - ) -> c_int; - - pub fn rtpDeleteForce ( - rtpId : RTP_ID - ) -> c_int; - - pub fn rtpShow ( - rtpNameOrId : *mut c_char, - level : c_int, - ) -> BOOL; - - // RTP signals are always present when RTPs are included. The public RTP - // signal APIs are declared here. - - - pub fn rtpKill ( - rtpId : RTP_ID, - signo : c_int, - ) -> c_int; - - pub fn rtpSigqueue ( - rtpId : RTP_ID, - signo : c_int, - value : size_t, // Actual type is const union sigval value, - // which is a union of int and void * - ) -> c_int; - - pub fn rtpTaskKill ( - tid : TASK_ID, - signo : c_int, - ) -> c_int; - - pub fn rtpTaskSigqueue ( - tid : TASK_ID, - signo : c_int, - value : const size_t, // Actual type is const union sigval, - // which is a union of int and void * - ) -> c_int; - - pub fn rtpWait ( - rtpWaitId : RTP_ID, - timeout : libc::alloc_jemalloc_Vx_ticks_t, - pRtpId : *mut RTP_ID, - pStatus : *mut c_int, - ) -> c_int; - - // Other public functions - - - pub fn rtpPreCreateHookAdd ( - hook : RTP_PRE_CREATE_HOOK, - addToHead : BOOL, - ) -> c_int; - - pub fn rtpPreCreateHookDelete ( - hook : RTP_POST_CREATE_HOOK, - ) -> c_int; - - pub fn rtpPostCreateHookAdd ( - hook : RTP_POST_CREATE_HOOK, - addToHead : BOOL, - ) -> c_int; - - pub fn rtpPostCreateHookDelete ( - hook : RTP_POST_CREATE_HOOK, - ) -> c_int; - - pub fn rtpInitCompleteHookAdd ( - hook : RTP_INIT_COMPLETE_HOOK, - addToHead : BOOL, - ) -> c_int; - - pub fn rtpInitCompleteHookDelete ( - hook : RTP_INIT_COMPLETE_HOOK, - ) -> c_int; - - pub fn rtpDeleteHookAdd ( - hook : RTP_DELETE_HOOK, - addToHead : BOOL, - ) -> c_int; - - pub fn rtpDeleteHookDelete ( - hook : RTP_DELETE_HOOK, - ) -> c_int; - - pub fn rtpMemShow ( - rtpNameOrId : *mut c_char, - level : c_int, - ) -> c_int; - - pub fn rtpHookShow ( - - ); -*/ -} diff --git a/src/libstd/sys/vxworks/rand.rs b/src/libstd/sys/vxworks/rand.rs index 1ec0cbe4dc..c22880db2b 100644 --- a/src/libstd/sys/vxworks/rand.rs +++ b/src/libstd/sys/vxworks/rand.rs @@ -14,17 +14,24 @@ pub fn hashmap_random_keys() -> (u64, u64) { mod imp { use libc; use crate::io; - - extern "C" { - fn randBytes (randBuf: *mut libc::c_uchar, - numOfBytes: libc::c_int) -> libc::c_int; - } + use core::sync::atomic::{AtomicBool, Ordering::Relaxed}; pub fn fill_bytes(v: &mut [u8]) { + static RNG_INIT: AtomicBool = AtomicBool::new(false); + while !RNG_INIT.load(Relaxed) { + let ret = unsafe { libc::randSecure() }; + if ret < 0 { + panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); + } else if ret > 0 { + RNG_INIT.store(true, Relaxed); + break; + } + unsafe { libc::usleep(10) }; + } let ret = unsafe { - randBytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) + libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) }; - if ret == -1 { + if ret < 0 { panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); } } diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 58af8cbe48..e4396b05c0 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -8,7 +8,7 @@ use crate::time::Duration; use crate::sys_common::thread::*; -pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; +pub const DEFAULT_MIN_STACK_SIZE: usize = 0x40000; // 256K pub struct Thread { id: libc::pthread_t, @@ -77,7 +77,7 @@ impl Thread { } pub fn set_name(_name: &CStr) { - assert!(false, "FIXME: set_name"); + // VxWorks does not provide a way to set the task name except at creation time } pub fn sleep(dur: Duration) { diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 8b4b354d9f..3280c4990d 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -1,11 +1,10 @@ -use crate::ffi::CStr; -use crate::io; -use crate::sys::cvt_wasi; use crate::ffi::OsString; use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStringExt; use crate::vec; +use ::wasi::wasi_unstable as wasi; + pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } @@ -19,31 +18,17 @@ pub struct Args { /// Returns the command line arguments pub fn args() -> Args { - maybe_args().unwrap_or_else(|_| { - Args { - iter: Vec::new().into_iter(), - _dont_send_or_sync_me: PhantomData - } - }) -} - -fn maybe_args() -> io::Result { - unsafe { - let (mut argc, mut argv_buf_size) = (0, 0); - cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?; - - let mut argc = vec![core::ptr::null_mut::(); argc]; - let mut argv_buf = vec![0; argv_buf_size]; - cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?; - - let args = argc.into_iter() - .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec()) - .map(|bytes| OsString::from_vec(bytes)) - .collect::>(); - Ok(Args { - iter: args.into_iter(), - _dont_send_or_sync_me: PhantomData, - }) + let buf = wasi::args_sizes_get().and_then(|args_sizes| { + let mut buf = Vec::with_capacity(args_sizes.get_count()); + wasi::args_get(args_sizes, |arg| { + let arg = OsString::from_vec(arg.to_vec()); + buf.push(arg); + })?; + Ok(buf) + }).unwrap_or(vec![]); + Args { + iter: buf.into_iter(), + _dont_send_or_sync_me: PhantomData } } diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs index 0ec4122f38..9fa4abfd17 100644 --- a/src/libstd/sys/wasi/ext/fs.rs +++ b/src/libstd/sys/wasi/ext/fs.rs @@ -8,6 +8,8 @@ use crate::os::wasi::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; +use ::wasi::wasi_unstable as wasi; + /// WASI-specific extensions to [`File`]. /// /// [`File`]: ../../../../std/fs/struct.File.html @@ -336,16 +338,16 @@ pub trait FileTypeExt { impl FileTypeExt for fs::FileType { fn is_block_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE + self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE } fn is_character_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE + self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE } fn is_socket_dgram(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM } fn is_socket_stream(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM } } diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs index 12afd1d42d..f1839df380 100644 --- a/src/libstd/sys/wasi/ext/io.rs +++ b/src/libstd/sys/wasi/ext/io.rs @@ -8,6 +8,8 @@ use crate::sys; use crate::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; +use ::wasi::wasi_unstable as wasi; + /// Raw file descriptors. pub type RawFd = u32; @@ -125,18 +127,18 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as u32 + wasi::STDIN_FD } } impl AsRawFd for io::Stdout { fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as u32 + wasi::STDOUT_FD } } impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as u32 + wasi::STDERR_FD } } diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 25692ec086..5b7a8678b6 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -3,348 +3,248 @@ use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; -use crate::sys::cvt_wasi; -use libc::{self, c_char, c_void}; +use super::err2io; +use ::wasi::wasi_unstable as wasi; #[derive(Debug)] pub struct WasiFd { - fd: libc::__wasi_fd_t, + fd: wasi::Fd, } -// FIXME: these should probably all be fancier structs, builders, enums, etc -pub type LookupFlags = u32; -pub type FdFlags = u16; -pub type Advice = u8; -pub type Rights = u64; -pub type Oflags = u16; -pub type DirCookie = u64; -pub type Timestamp = u64; -pub type FstFlags = u16; -pub type RiFlags = u16; -pub type RoFlags = u16; -pub type SiFlags = u16; - -fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) { +fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] { assert_eq!( mem::size_of::>(), - mem::size_of::() + mem::size_of::() ); assert_eq!( mem::align_of::>(), - mem::align_of::() + mem::align_of::() ); - (a.as_ptr() as *const libc::__wasi_iovec_t, a.len()) + /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } -fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) { +fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] { assert_eq!( mem::size_of::>(), - mem::size_of::() + mem::size_of::() ); assert_eq!( mem::align_of::>(), - mem::align_of::() + mem::align_of::() ); - (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len()) + /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } impl WasiFd { - pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd { + pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> libc::__wasi_fd_t { + pub fn into_raw(self) -> wasi::Fd { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> libc::__wasi_fd_t { + pub fn as_raw(&self) -> wasi::Fd { self.fd } pub fn datasync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) }) + unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?; - Ok(read) + unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?; - Ok(read) + unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result { let (whence, offset) = match pos { - SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64), - SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos), - SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos), + SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64), + SeekFrom::End(pos) => (wasi::WHENCE_END, pos), + SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?; - Ok(pos) + unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result { - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?; - Ok(pos) + unsafe { wasi::fd_tell(self.fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get - pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) }) + pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> { + unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } } - pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) }) + pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { + unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } } pub fn sync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) }) + unsafe { wasi::fd_sync(self.fd).map_err(err2io) } } - pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) }) + pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { + unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) }) + unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } } pub fn link( &self, - old_flags: LookupFlags, + old_flags: wasi::LookupFlags, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8], ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_link( - self.fd, - old_flags, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { + wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) + .map_err(err2io) + } } pub fn open( &self, - dirflags: LookupFlags, + dirflags: wasi::LookupFlags, path: &[u8], - oflags: Oflags, - fs_rights_base: Rights, - fs_rights_inheriting: Rights, - fs_flags: FdFlags, + oflags: wasi::OFlags, + fs_rights_base: wasi::Rights, + fs_rights_inheriting: wasi::Rights, + fs_flags: wasi::FdFlags, ) -> io::Result { unsafe { - let mut fd = 0; - cvt_wasi(libc::__wasi_path_open( + wasi::path_open( self.fd, dirflags, - path.as_ptr() as *const c_char, - path.len(), + path, oflags, fs_rights_base, fs_rights_inheriting, fs_flags, - &mut fd, - ))?; - Ok(WasiFd::from_raw(fd)) + ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io) } } - pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_fd_readdir( - self.fd, - buf.as_mut_ptr() as *mut c_void, - buf.len(), - cookie, - &mut used, - ) - })?; - Ok(used) + pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result { + unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) } } pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_path_readlink( - self.fd, - path.as_ptr() as *const c_char, - path.len(), - buf.as_mut_ptr() as *mut c_char, - buf.len(), - &mut used, - ) - })?; - Ok(used) + unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) } } pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_rename( - self.fd, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { + wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) + } } - pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) }) + pub fn filestat_get(&self) -> io::Result { + unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } } pub fn filestat_set_times( &self, - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) }) + unsafe { + wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) }) + unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } } pub fn path_filestat_get( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - buf: *mut libc::__wasi_filestat_t, - ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_get( - self.fd, - flags, - path.as_ptr() as *const c_char, - path.len(), - buf, - ) - }) + ) -> io::Result { + unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_set_times( + unsafe { + wasi::path_filestat_set_times( self.fd, flags, - path.as_ptr() as *const c_char, - path.len(), + path, atim, mtim, fstflags, - ) - }) + ).map_err(err2io) + } } pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_symlink( - old_path.as_ptr() as *const c_char, - old_path.len(), - self.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } } pub fn sock_recv( &self, ri_data: &mut [IoSliceMut<'_>], - ri_flags: RiFlags, - ) -> io::Result<(usize, RoFlags)> { - let mut ro_datalen = 0; - let mut ro_flags = 0; - let (ptr, len) = iovec(ri_data); - cvt_wasi(unsafe { - libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags) - })?; - Ok((ro_datalen, ro_flags)) + ri_flags: wasi::RiFlags, + ) -> io::Result<(usize, wasi::RoFlags)> { + unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } } - pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result { - let mut so_datalen = 0; - let (ptr, len) = ciovec(si_data); - cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?; - Ok(so_datalen) + pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result { + unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { let how = match how { - Shutdown::Read => libc::__WASI_SHUT_RD, - Shutdown::Write => libc::__WASI_SHUT_WR, - Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD, + Shutdown::Read => wasi::SHUT_RD, + Shutdown::Write => wasi::SHUT_WR, + Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD, }; - cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?; - Ok(()) + unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } } } impl Drop for WasiFd { fn drop(&mut self) { - unsafe { - // FIXME: can we handle the return code here even though we can't on - // unix? - libc::__wasi_fd_close(self.fd); - } + // FIXME: can we handle the return code here even though we can't on + // unix? + let _ = unsafe { wasi::fd_close(self.fd) }; } } diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index 172c60385b..4113f6a2e0 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -7,7 +7,7 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Arc; -use crate::sys::fd::{DirCookie, WasiFd}; +use crate::sys::fd::WasiFd; use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; @@ -15,18 +15,20 @@ use crate::sys_common::FromInner; pub use crate::sys_common::fs::copy; pub use crate::sys_common::fs::remove_dir_all; +use ::wasi::wasi_unstable as wasi; + pub struct File { fd: WasiFd, } #[derive(Clone)] pub struct FileAttr { - meta: libc::__wasi_filestat_t, + meta: wasi::FileStat, } pub struct ReadDir { inner: Arc, - cookie: Option, + cookie: Option, buf: Vec, offset: usize, cap: usize, @@ -38,7 +40,7 @@ struct ReadDirInner { } pub struct DirEntry { - meta: libc::__wasi_dirent_t, + meta: wasi::Dirent, name: Vec, inner: Arc, } @@ -47,11 +49,11 @@ pub struct DirEntry { pub struct OpenOptions { read: bool, write: bool, - dirflags: libc::__wasi_lookupflags_t, - fdflags: libc::__wasi_fdflags_t, - oflags: libc::__wasi_oflags_t, - rights_base: Option, - rights_inheriting: Option, + dirflags: wasi::LookupFlags, + fdflags: wasi::FdFlags, + oflags: wasi::OFlags, + rights_base: Option, + rights_inheriting: Option, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -61,19 +63,13 @@ pub struct FilePermissions { #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub struct FileType { - bits: libc::__wasi_filetype_t, + bits: wasi::FileType, } #[derive(Debug)] pub struct DirBuilder {} impl FileAttr { - fn zero() -> FileAttr { - FileAttr { - meta: unsafe { mem::zeroed() }, - } - } - pub fn size(&self) -> u64 { self.meta.st_size } @@ -101,7 +97,7 @@ impl FileAttr { Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim)) } - pub fn as_wasi(&self) -> &libc::__wasi_filestat_t { + pub fn as_wasi(&self) -> &wasi::FileStat { &self.meta } } @@ -118,18 +114,18 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_DIRECTORY + self.bits == wasi::FILETYPE_DIRECTORY } pub fn is_file(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_REGULAR_FILE + self.bits == wasi::FILETYPE_REGULAR_FILE } pub fn is_symlink(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK + self.bits == wasi::FILETYPE_SYMBOLIC_LINK } - pub fn bits(&self) -> libc::__wasi_filetype_t { + pub fn bits(&self) -> wasi::FileType { self.bits } } @@ -173,7 +169,7 @@ impl Iterator for ReadDir { // must have been truncated at the end of the buffer, so reset our // offset so we can go back and reread into the buffer, picking up // where we last left off. - let dirent_size = mem::size_of::(); + let dirent_size = mem::size_of::(); if data.len() < dirent_size { assert!(self.cookie.is_some()); assert!(self.buf.len() >= dirent_size); @@ -182,7 +178,7 @@ impl Iterator for ReadDir { } let (dirent, data) = data.split_at(dirent_size); let dirent = - unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) }; + unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) }; // If the file name was truncated, then we need to reinvoke // `readdir` so we truncate our buffer to start over and reread this @@ -241,7 +237,7 @@ impl DirEntry { }) } - pub fn ino(&self) -> libc::__wasi_inode_t { + pub fn ino(&self) -> wasi::Inode { self.meta.d_ino } } @@ -249,7 +245,7 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { let mut base = OpenOptions::default(); - base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW; + base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW; return base; } @@ -262,23 +258,23 @@ impl OpenOptions { } pub fn truncate(&mut self, truncate: bool) { - self.oflag(libc::__WASI_O_TRUNC, truncate); + self.oflag(wasi::O_TRUNC, truncate); } pub fn create(&mut self, create: bool) { - self.oflag(libc::__WASI_O_CREAT, create); + self.oflag(wasi::O_CREAT, create); } pub fn create_new(&mut self, create_new: bool) { - self.oflag(libc::__WASI_O_EXCL, create_new); - self.oflag(libc::__WASI_O_CREAT, create_new); + self.oflag(wasi::O_EXCL, create_new); + self.oflag(wasi::O_CREAT, create_new); } pub fn directory(&mut self, directory: bool) { - self.oflag(libc::__WASI_O_DIRECTORY, directory); + self.oflag(wasi::O_DIRECTORY, directory); } - fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) { + fn oflag(&mut self, bit: wasi::OFlags, set: bool) { if set { self.oflags |= bit; } else { @@ -287,26 +283,26 @@ impl OpenOptions { } pub fn append(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_APPEND, set); + self.fdflag(wasi::FDFLAG_APPEND, set); } pub fn dsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_DSYNC, set); + self.fdflag(wasi::FDFLAG_DSYNC, set); } pub fn nonblock(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set); + self.fdflag(wasi::FDFLAG_NONBLOCK, set); } pub fn rsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_RSYNC, set); + self.fdflag(wasi::FDFLAG_RSYNC, set); } pub fn sync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_SYNC, set); + self.fdflag(wasi::FDFLAG_SYNC, set); } - fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) { + fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) { if set { self.fdflags |= bit; } else { @@ -314,15 +310,15 @@ impl OpenOptions { } } - pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_base(&mut self, rights: wasi::Rights) { self.rights_base = Some(rights); } - pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_inheriting(&mut self, rights: wasi::Rights) { self.rights_inheriting = Some(rights); } - fn rights_base(&self) -> libc::__wasi_rights_t { + fn rights_base(&self) -> wasi::Rights { if let Some(rights) = self.rights_base { return rights; } @@ -334,52 +330,52 @@ impl OpenOptions { // based on that. let mut base = 0; if self.read { - base |= libc::__WASI_RIGHT_FD_READ; - base |= libc::__WASI_RIGHT_FD_READDIR; + base |= wasi::RIGHT_FD_READ; + base |= wasi::RIGHT_FD_READDIR; } if self.write { - base |= libc::__WASI_RIGHT_FD_WRITE; - base |= libc::__WASI_RIGHT_FD_DATASYNC; - base |= libc::__WASI_RIGHT_FD_ALLOCATE; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE; + base |= wasi::RIGHT_FD_WRITE; + base |= wasi::RIGHT_FD_DATASYNC; + base |= wasi::RIGHT_FD_ALLOCATE; + base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE; } // FIXME: some of these should probably be read-only or write-only... - base |= libc::__WASI_RIGHT_FD_ADVISE; - base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES; - base |= libc::__WASI_RIGHT_FD_SEEK; - base |= libc::__WASI_RIGHT_FD_SYNC; - base |= libc::__WASI_RIGHT_FD_TELL; - base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_CREATE_FILE; - base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET; - base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE; - base |= libc::__WASI_RIGHT_PATH_LINK_TARGET; - base |= libc::__WASI_RIGHT_PATH_OPEN; - base |= libc::__WASI_RIGHT_PATH_READLINK; - base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE; - base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET; - base |= libc::__WASI_RIGHT_PATH_SYMLINK; - base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE; - base |= libc::__WASI_RIGHT_POLL_FD_READWRITE; + base |= wasi::RIGHT_FD_ADVISE; + base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS; + base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES; + base |= wasi::RIGHT_FD_SEEK; + base |= wasi::RIGHT_FD_SYNC; + base |= wasi::RIGHT_FD_TELL; + base |= wasi::RIGHT_PATH_CREATE_DIRECTORY; + base |= wasi::RIGHT_PATH_CREATE_FILE; + base |= wasi::RIGHT_PATH_FILESTAT_GET; + base |= wasi::RIGHT_PATH_LINK_SOURCE; + base |= wasi::RIGHT_PATH_LINK_TARGET; + base |= wasi::RIGHT_PATH_OPEN; + base |= wasi::RIGHT_PATH_READLINK; + base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY; + base |= wasi::RIGHT_PATH_RENAME_SOURCE; + base |= wasi::RIGHT_PATH_RENAME_TARGET; + base |= wasi::RIGHT_PATH_SYMLINK; + base |= wasi::RIGHT_PATH_UNLINK_FILE; + base |= wasi::RIGHT_POLL_FD_READWRITE; return base; } - fn rights_inheriting(&self) -> libc::__wasi_rights_t { + fn rights_inheriting(&self) -> wasi::Rights { self.rights_inheriting.unwrap_or_else(|| self.rights_base()) } - pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) { + pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) { self.dirflags = flags; } } impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { - let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?; + let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?; open_at(&dir, &file, opts) } @@ -388,14 +384,12 @@ impl File { } pub fn file_attr(&self) -> io::Result { - let mut ret = FileAttr::zero(); - self.fd.filestat_get(&mut ret.meta)?; - Ok(ret) + self.fd.filestat_get().map(|meta| FileAttr { meta }) } pub fn metadata_at( &self, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result { metadata_at(&self.fd, flags, path) @@ -477,7 +471,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?; dir.create_directory(file.as_os_str().as_bytes()) } } @@ -508,13 +502,13 @@ pub fn readdir(p: &Path) -> io::Result { } pub fn unlink(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?; dir.unlink_file(file.as_os_str().as_bytes()) } pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?; - let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?; + let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?; + let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?; old.rename( old_file.as_os_str().as_bytes(), &new, @@ -529,12 +523,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?; dir.remove_directory(file.as_os_str().as_bytes()) } pub fn readlink(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?; read_link(&dir, &file) } @@ -570,15 +564,15 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?; dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes()) } pub fn link(src: &Path, dst: &Path) -> io::Result<()> { - let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?; - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?; + let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?; src.link( - libc::__WASI_LOOKUP_SYMLINK_FOLLOW, + wasi::LOOKUP_SYMLINK_FOLLOW, src_file.as_os_str().as_bytes(), &dst, dst_file.as_os_str().as_bytes(), @@ -586,23 +580,22 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { } pub fn stat(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; - metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file) + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; + metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file) } pub fn lstat(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; metadata_at(&dir, 0, &file) } fn metadata_at( fd: &WasiFd, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result { - let mut ret = FileAttr::zero(); - fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?; - Ok(ret) + fd.path_filestat_get(flags, path.as_os_str().as_bytes()) + .map(|meta| FileAttr { meta }) } pub fn canonicalize(_p: &Path) -> io::Result { @@ -652,12 +645,12 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result { /// to any preopened file descriptor. fn open_parent( p: &Path, - rights: libc::__wasi_rights_t, + rights: wasi::Rights, ) -> io::Result<(ManuallyDrop, PathBuf)> { let p = CString::new(p.as_os_str().as_bytes())?; unsafe { let mut ret = ptr::null(); - let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); + let fd = libc::__wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); if fd == -1 { let msg = format!( "failed to find a preopened file descriptor \ @@ -677,15 +670,4 @@ fn open_parent( return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path)); } - - // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API - // there is published - extern "C" { - pub fn __wasilibc_find_relpath( - path: *const libc::c_char, - rights_base: libc::__wasi_rights_t, - rights_inheriting: libc::__wasi_rights_t, - relative_path: *mut *const libc::c_char, - ) -> libc::c_int; - } } diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ffecca5d1b..4be92faed3 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,11 +1,12 @@ use crate::marker::PhantomData; use crate::slice; -use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void}; +use ::wasi::wasi_unstable as wasi; +use core::ffi::c_void; #[repr(transparent)] pub struct IoSlice<'a> { - vec: __wasi_ciovec_t, + vec: wasi::CIoVec, _p: PhantomData<&'a [u8]>, } @@ -13,7 +14,7 @@ impl<'a> IoSlice<'a> { #[inline] pub fn new(buf: &'a [u8]) -> IoSlice<'a> { IoSlice { - vec: __wasi_ciovec_t { + vec: wasi::CIoVec { buf: buf.as_ptr() as *const c_void, buf_len: buf.len(), }, @@ -43,7 +44,7 @@ impl<'a> IoSlice<'a> { #[repr(transparent)] pub struct IoSliceMut<'a> { - vec: __wasi_iovec_t, + vec: wasi::IoVec, _p: PhantomData<&'a mut [u8]>, } @@ -51,7 +52,7 @@ impl<'a> IoSliceMut<'a> { #[inline] pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { IoSliceMut { - vec: __wasi_iovec_t { + vec: wasi::IoVec { buf: buf.as_mut_ptr() as *mut c_void, buf_len: buf.len() }, diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index f842869e08..517e3be9cb 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -14,10 +14,10 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use libc; -use crate::io::{Error, ErrorKind}; +use crate::io as std_io; use crate::mem; use crate::os::raw::c_char; +use ::wasi::wasi_unstable as wasi; pub mod alloc; pub mod args; @@ -56,16 +56,43 @@ pub mod ext; pub fn init() { } -pub fn unsupported() -> crate::io::Result { +pub fn unsupported() -> std_io::Result { Err(unsupported_err()) } -pub fn unsupported_err() -> Error { - Error::new(ErrorKind::Other, "operation not supported on wasm yet") +pub fn unsupported_err() -> std_io::Error { + std_io::Error::new( + std_io::ErrorKind::Other, + "operation not supported on wasm yet", + ) } -pub fn decode_error_kind(_code: i32) -> ErrorKind { - ErrorKind::Other +pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { + use std_io::ErrorKind::*; + if errno > u16::max_value() as i32 || errno < 0 { + return Other; + } + let code = match wasi::Error::new(errno as u16) { + Some(code) => code, + None => return Other, + }; + match code { + wasi::ECONNREFUSED => ConnectionRefused, + wasi::ECONNRESET => ConnectionReset, + wasi::EPERM | wasi::EACCES => PermissionDenied, + wasi::EPIPE => BrokenPipe, + wasi::ENOTCONN => NotConnected, + wasi::ECONNABORTED => ConnectionAborted, + wasi::EADDRNOTAVAIL => AddrNotAvailable, + wasi::EADDRINUSE => AddrInUse, + wasi::ENOENT => NotFound, + wasi::EINTR => Interrupted, + wasi::EINVAL => InvalidInput, + wasi::ETIMEDOUT => TimedOut, + wasi::EEXIST => AlreadyExists, + wasi::EAGAIN => WouldBlock, + _ => Other, + } } // This enum is used as the storage for a bunch of types which can't actually @@ -89,40 +116,16 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { let mut ret = (0u64, 0u64); unsafe { - let base = &mut ret as *mut (u64, u64) as *mut libc::c_void; + let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void; let len = mem::size_of_val(&ret); - cvt_wasi(libc::__wasi_random_get(base, len)).unwrap(); - } - return ret -} - -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 + let ret = wasi::raw::__wasi_random_get(base, len); + if ret != 0 { + panic!("__wasi_random_get failure") } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -pub fn cvt(t: T) -> crate::io::Result { - if t.is_minus_one() { - Err(Error::last_os_error()) - } else { - Ok(t) } + return ret } -pub fn cvt_wasi(r: u16) -> crate::io::Result<()> { - if r != libc::__WASI_ESUCCESS { - Err(Error::from_raw_os_error(r as i32)) - } else { - Ok(()) - } +fn err2io(err: wasi::Error) -> std_io::Error { + std_io::Error::from_raw_os_error(err.get() as i32) } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 822ea02a11..feee840782 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -9,7 +9,7 @@ use crate::path::{self, PathBuf}; use crate::ptr; use crate::str; use crate::sys::memchr; -use crate::sys::{cvt, unsupported, Void}; +use crate::sys::{unsupported, Void}; use crate::vec; #[cfg(not(target_feature = "atomics"))] @@ -28,16 +28,11 @@ pub fn errno() -> i32 { } pub fn error_string(errno: i32) -> String { - extern { - fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char, - buflen: libc::size_t) -> libc::c_int; - } - let mut buf = [0 as libc::c_char; 1024]; let p = buf.as_mut_ptr(); unsafe { - if strerror_r(errno as libc::c_int, p, buf.len()) < 0 { + if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 { panic!("strerror_r failure"); } str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() @@ -89,7 +84,6 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result { unsupported() } - pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, @@ -182,3 +176,26 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("unsupported"); } + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +fn cvt(t: T) -> io::Result { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs index 788b829f4b..1c4d028b76 100644 --- a/src/libstd/sys/wasi/process.rs +++ b/src/libstd/sys/wasi/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 2bf8d803c0..1d57b9922e 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -1,8 +1,9 @@ use crate::io::{self, IoSlice, IoSliceMut}; -use crate::libc; use crate::mem::ManuallyDrop; use crate::sys::fd::WasiFd; +use ::wasi::wasi_unstable as wasi; + pub struct Stdin; pub struct Stdout; pub struct Stderr; @@ -17,7 +18,7 @@ impl Stdin { } pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) }) .read(data) } } @@ -32,7 +33,7 @@ impl Stdout { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) }) .write(data) } @@ -51,7 +52,7 @@ impl Stderr { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) }) .write(data) } @@ -73,7 +74,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - err.raw_os_error() == Some(libc::__WASI_EBADF as i32) + err.raw_os_error() == Some(wasi::EBADF.get() as i32) } pub fn panic_output() -> Option { diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 5e69e4d948..28a504f197 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -1,10 +1,10 @@ -use crate::cmp; use crate::ffi::CStr; use crate::io; -use crate::sys::cvt; +use crate::mem; use crate::sys::{unsupported, Void}; use crate::time::Duration; -use libc; + +use ::wasi::wasi_unstable as wasi; pub struct Thread(Void); @@ -19,8 +19,8 @@ impl Thread { } pub fn yield_now() { - let ret = unsafe { libc::__wasi_sched_yield() }; - debug_assert_eq!(ret, 0); + let ret = wasi::sched_yield(); + debug_assert_eq!(ret, Ok(())); } pub fn set_name(_name: &CStr) { @@ -28,19 +28,37 @@ impl Thread { } pub fn sleep(dur: Duration) { - let mut secs = dur.as_secs(); - let mut nsecs = dur.subsec_nanos() as i32; - - unsafe { - while secs > 0 || nsecs > 0 { - let mut ts = libc::timespec { - tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t, - tv_nsec: nsecs, - }; - secs -= ts.tv_sec as u64; - cvt(libc::nanosleep(&ts, &mut ts)).unwrap(); - nsecs = 0; - } + let nanos = dur.as_nanos(); + assert!(nanos <= u64::max_value() as u128); + + const CLOCK_ID: wasi::Userdata = 0x0123_45678; + + let clock = wasi::raw::__wasi_subscription_u_clock_t { + identifier: CLOCK_ID, + clock_id: wasi::CLOCK_MONOTONIC, + timeout: nanos as u64, + precision: 0, + flags: 0, + }; + + let in_ = [wasi::Subscription { + userdata: 0, + type_: wasi::EVENTTYPE_CLOCK, + u: wasi::raw::__wasi_subscription_u { clock: clock }, + }]; + let (res, event) = unsafe { + let mut out: [wasi::Event; 1] = mem::zeroed(); + let res = wasi::poll_oneoff(&in_, &mut out); + (res, out[0]) + }; + match (res, event) { + (Ok(1), wasi::Event { + userdata: CLOCK_ID, + error: 0, + type_: wasi::EVENTTYPE_CLOCK, + .. + }) => {} + _ => panic!("thread::sleep(): unexpected result of poll_oneoff"), } } diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs index 3f14c80928..4394a22f9c 100644 --- a/src/libstd/sys/wasi/time.rs +++ b/src/libstd/sys/wasi/time.rs @@ -1,7 +1,5 @@ use crate::time::Duration; -use crate::mem; -use crate::sys::cvt_wasi; -use libc; +use ::wasi::wasi_unstable as wasi; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -12,23 +10,19 @@ pub struct SystemTime(Duration); pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); fn current_time(clock: u32) -> Duration { - unsafe { - let mut ts = mem::zeroed(); - cvt_wasi(libc::__wasi_clock_time_get( - clock, - 1, // precision... seems ignored though? - &mut ts, - )).unwrap(); - Duration::new( - (ts / 1_000_000_000) as u64, - (ts % 1_000_000_000) as u32, - ) - } + let ts = wasi::clock_time_get( + clock, + 1, // precision... seems ignored though? + ).unwrap(); + Duration::new( + (ts / 1_000_000_000) as u64, + (ts % 1_000_000_000) as u32, + ) } impl Instant { pub fn now() -> Instant { - Instant(current_time(libc::__WASI_CLOCK_MONOTONIC)) + Instant(current_time(wasi::CLOCK_MONOTONIC)) } pub const fn zero() -> Instant { @@ -54,10 +48,10 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(current_time(libc::__WASI_CLOCK_REALTIME)) + SystemTime(current_time(wasi::CLOCK_REALTIME)) } - pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime { + pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { SystemTime(Duration::from_nanos(ts)) } diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index b3c77b8699..8279e5280e 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -1,7 +1,6 @@ use crate::ffi::OsString; use crate::marker::PhantomData; use crate::vec; -use crate::sys::ArgsSysCall; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { // On wasm these should always be null, so there's nothing for us to do here @@ -11,9 +10,8 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { - let v = ArgsSysCall::perform(); Args { - iter: v.into_iter(), + iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData, } } diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index 56cbafcfdb..de0bb38dc3 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -15,11 +15,6 @@ //! guaranteed to be a runtime error! use crate::os::raw::c_char; -use crate::ptr; -use crate::sys::os_str::Buf; -use crate::sys_common::{AsInner, FromInner}; -use crate::ffi::{OsString, OsStr}; -use crate::time::Duration; pub mod alloc; pub mod args; @@ -89,7 +84,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - ExitSysCall::perform(1) + crate::arch::wasm32::unreachable() } // We don't have randomness yet, but I totally used a random number generator to @@ -100,218 +95,3 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } - -// Implement a minimal set of system calls to enable basic IO -pub enum SysCallIndex { - Read = 0, - Write = 1, - Exit = 2, - Args = 3, - GetEnv = 4, - SetEnv = 5, - Time = 6, -} - -#[repr(C)] -pub struct ReadSysCall { - fd: usize, - ptr: *mut u8, - len: usize, - result: usize, -} - -impl ReadSysCall { - pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { - let mut call_record = ReadSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { - call_record.result - } else { - 0 - } - } -} - -#[repr(C)] -pub struct WriteSysCall { - fd: usize, - ptr: *const u8, - len: usize, -} - -impl WriteSysCall { - pub fn perform(fd: usize, buffer: &[u8]) { - let mut call_record = WriteSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_ptr() - }; - unsafe { syscall(SysCallIndex::Write, &mut call_record); } - } -} - -#[repr(C)] -pub struct ExitSysCall { - code: usize, -} - -impl ExitSysCall { - pub fn perform(code: usize) -> ! { - let mut call_record = ExitSysCall { - code - }; - unsafe { - syscall(SysCallIndex::Exit, &mut call_record); - crate::intrinsics::abort(); - } - } -} - -fn receive_buffer Result>(estimate: usize, mut f: F) - -> Result, E> -{ - let mut buffer = vec![0; estimate]; - loop { - let result = f(&mut buffer)?; - if result <= buffer.len() { - buffer.truncate(result); - break; - } - buffer.resize(result, 0); - } - Ok(buffer) -} - -#[repr(C)] -pub struct ArgsSysCall { - ptr: *mut u8, - len: usize, - result: usize -} - -impl ArgsSysCall { - pub fn perform() -> Vec { - receive_buffer(1024, |buffer| -> Result { - let mut call_record = ArgsSysCall { - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { - Ok(call_record.result) - } else { - Ok(0) - } - }) - .unwrap() - .split(|b| *b == 0) - .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) - .collect() - } -} - -#[repr(C)] -pub struct GetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *mut u8, - value_len: usize, - result: usize -} - -impl GetEnvSysCall { - pub fn perform(key: &OsStr) -> Option { - let key_buf = &AsInner::as_inner(key).inner; - receive_buffer(64, |buffer| { - let mut call_record = GetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: buffer.len(), - value_ptr: buffer.as_mut_ptr(), - result: !0usize - }; - if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { - if call_record.result == !0usize { - Err(()) - } else { - Ok(call_record.result) - } - } else { - Err(()) - } - }).ok().map(|s| { - FromInner::from_inner(Buf { inner: s }) - }) - } -} - -#[repr(C)] -pub struct SetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *const u8, - value_len: usize -} - -impl SetEnvSysCall { - pub fn perform(key: &OsStr, value: Option<&OsStr>) { - let key_buf = &AsInner::as_inner(key).inner; - let value_buf = value.map(|v| &AsInner::as_inner(v).inner); - let mut call_record = SetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), - value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) - }; - unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } - } -} - -pub enum TimeClock { - Monotonic = 0, - System = 1, -} - -#[repr(C)] -pub struct TimeSysCall { - clock: usize, - secs_hi: usize, - secs_lo: usize, - nanos: usize -} - -impl TimeSysCall { - pub fn perform(clock: TimeClock) -> Duration { - let mut call_record = TimeSysCall { - clock: clock as usize, - secs_hi: 0, - secs_lo: 0, - nanos: 0 - }; - if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { - Duration::new( - ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), - call_record.nanos as u32 - ) - } else { - panic!("Time system call is not implemented by WebAssembly host"); - } - } -} - -unsafe fn syscall(index: SysCallIndex, data: &mut T) -> bool { - #[cfg(feature = "wasm_syscall")] - extern { - #[no_mangle] - fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; - } - - #[cfg(not(feature = "wasm_syscall"))] - unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } - - rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 -} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs index 5d21999a99..890049e8bf 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/wasm/os.rs @@ -4,7 +4,7 @@ use crate::fmt; use crate::io; use crate::path::{self, PathBuf}; use crate::str; -use crate::sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; +use crate::sys::{unsupported, Void}; pub fn errno() -> i32 { 0 @@ -73,16 +73,16 @@ pub fn env() -> Env { panic!("not supported on web assembly") } -pub fn getenv(k: &OsStr) -> io::Result> { - Ok(GetEnvSysCall::perform(k)) +pub fn getenv(_: &OsStr) -> io::Result> { + Ok(None) } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, Some(v))) +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown")) } -pub fn unsetenv(k: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, None)) +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown")) } pub fn temp_dir() -> PathBuf { @@ -94,7 +94,9 @@ pub fn home_dir() -> Option { } pub fn exit(_code: i32) -> ! { - ExitSysCall::perform(_code as isize as usize) + unsafe { + crate::arch::wasm32::unreachable(); + } } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs index a02e009d95..edf933d10e 100644 --- a/src/libstd/sys/wasm/process.rs +++ b/src/libstd/sys/wasm/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index b8899a9c84..5a4e4505e9 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -1,5 +1,4 @@ use crate::io; -use crate::sys::{ReadSysCall, WriteSysCall}; pub struct Stdin; pub struct Stdout; @@ -12,8 +11,8 @@ impl Stdin { } impl io::Read for Stdin { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - Ok(ReadSysCall::perform(0, buf)) + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) } } @@ -25,7 +24,6 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - WriteSysCall::perform(1, buf); Ok(buf.len()) } @@ -42,7 +40,6 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - WriteSysCall::perform(2, buf); Ok(buf.len()) } @@ -57,10 +54,6 @@ pub fn is_ebadf(_err: &io::Error) -> bool { true } -pub fn panic_output() -> Option { - if cfg!(feature = "wasm_syscall") { - Stderr::new().ok() - } else { - None - } +pub fn panic_output() -> Option> { + None } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index 3f71461eea..dd9ad3760b 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -1,5 +1,4 @@ use crate::time::Duration; -use crate::sys::{TimeSysCall, TimeClock}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -11,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - Instant(TimeSysCall::perform(TimeClock::Monotonic)) + panic!("time not implemented on wasm32-unknown-unknown") } pub const fn zero() -> Instant { @@ -37,7 +36,7 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(TimeSysCall::perform(TimeClock::System)) + panic!("time not implemented on wasm32-unknown-unknown") } pub fn sub_time(&self, other: &SystemTime) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index f706709c9c..b1f9d9766f 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -714,7 +714,7 @@ if #[cfg(target_vendor = "uwp")] { pub struct FILE_STANDARD_INFO { pub AllocationSize: LARGE_INTEGER, pub EndOfFile: LARGE_INTEGER, - pub NumberOfLink: DWORD, + pub NumberOfLinks: DWORD, pub DeletePending: BOOLEAN, pub Directory: BOOLEAN, } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 5bae6ba474..204f6af5fc 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -357,7 +357,7 @@ impl File { size as c::DWORD))?; attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); - if attr.is_reparse_point() { + if attr.file_type().is_reparse_point() { let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if let Ok((_, buf)) = self.reparse_point(&mut b) { attr.reparse_tag = buf.ReparseTag; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 05e0ca6706..8658deb854 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -19,7 +19,7 @@ use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::sys_common::process::{CommandEnv, EnvKey}; +use crate::sys_common::process::CommandEnv; use crate::borrow::Borrow; use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; @@ -30,30 +30,28 @@ use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[doc(hidden)] -pub struct WindowsEnvKey(OsString); +pub struct EnvKey(OsString); -impl From for WindowsEnvKey { +impl From for EnvKey { fn from(k: OsString) -> Self { let mut buf = k.into_inner().into_inner(); buf.make_ascii_uppercase(); - WindowsEnvKey(FromInner::from_inner(FromInner::from_inner(buf))) + EnvKey(FromInner::from_inner(FromInner::from_inner(buf))) } } -impl From for OsString { - fn from(k: WindowsEnvKey) -> Self { k.0 } +impl From for OsString { + fn from(k: EnvKey) -> Self { k.0 } } -impl Borrow for WindowsEnvKey { +impl Borrow for EnvKey { fn borrow(&self) -> &OsStr { &self.0 } } -impl AsRef for WindowsEnvKey { +impl AsRef for EnvKey { fn as_ref(&self) -> &OsStr { &self.0 } } -impl EnvKey for WindowsEnvKey {} - fn ensure_no_nuls>(str: T) -> io::Result { if str.as_ref().encode_wide().any(|b| b == 0) { @@ -66,7 +64,7 @@ fn ensure_no_nuls>(str: T) -> io::Result { pub struct Command { program: OsString, args: Vec, - env: CommandEnv, + env: CommandEnv, cwd: Option, flags: u32, detach: bool, // not currently exposed in std::process @@ -110,7 +108,7 @@ impl Command { pub fn arg(&mut self, arg: &OsStr) { self.args.push(arg.to_os_string()) } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } pub fn cwd(&mut self, dir: &OsStr) { @@ -498,7 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { } } -fn make_envp(maybe_env: Option>) +fn make_envp(maybe_env: Option>) -> io::Result<(*mut c_void, Vec)> { // On Windows we pass an "environment block" which is not a char**, but // rather a concatenation of null-terminated k=v\0 sequences, with a final diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index bf37ff7ddb..01711d415d 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -2,25 +2,38 @@ /// supported platforms. use crate::env; +use crate::fmt; use crate::io; +use crate::borrow::Cow; use crate::io::prelude::*; -use crate::mem; -use crate::path::{self, Path}; -use crate::ptr; -use crate::sync::atomic::{self, Ordering}; +use crate::path::{self, Path, PathBuf}; use crate::sys::mutex::Mutex; -use backtrace::{BytesOrWideString, Frame, Symbol}; - -pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::(); +use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt}; /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; -/// Prints the current backtrace. -pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { +pub fn lock() -> impl Drop { + struct Guard; static LOCK: Mutex = Mutex::new(); + impl Drop for Guard { + fn drop(&mut self) { + unsafe { + LOCK.unlock(); + } + } + } + + unsafe { + LOCK.lock(); + return Guard; + } +} + +/// Prints the current backtrace. +pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { // There are issues currently linking libbacktrace into tests, and in // general during libstd's own unit tests we're not testing this path. In // test mode immediately return here to optimize away any references to the @@ -32,33 +45,69 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { // Use a lock to prevent mixed output in multithreading context. // Some platforms also requires it, like `SymFromAddr` on Windows. unsafe { - LOCK.lock(); - let res = _print(w, format); - LOCK.unlock(); - res + let _lock = lock(); + _print(w, format) + } +} + +unsafe fn _print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { + struct DisplayBacktrace { + format: PrintFmt, } + impl fmt::Display for DisplayBacktrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + _print_fmt(fmt, self.format) + } + } + } + write!(w, "{}", DisplayBacktrace { format }) } -fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { - writeln!(w, "stack backtrace:")?; +unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result { + let cwd = env::current_dir().ok(); + let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { + output_filename(fmt, bows, print_fmt, cwd.as_ref()) + }; + let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); + bt_fmt.add_context()?; + let mut idx = 0; + let mut res = Ok(()); + backtrace_rs::trace_unsynchronized(|frame| { + if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { + return false; + } - let mut printer = Printer::new(format, w); - unsafe { - backtrace::trace_unsynchronized(|frame| { - let mut hit = false; - backtrace::resolve_frame_unsynchronized(frame, |symbol| { - hit = true; - printer.output(frame, Some(symbol)); - }); - if !hit { - printer.output(frame, None); + let mut hit = false; + let mut stop = false; + backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| { + hit = true; + if print_fmt == PrintFmt::Short { + if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { + if sym.contains("__rust_begin_short_backtrace") { + stop = true; + return; + } + } } - !printer.done + + res = bt_fmt.frame().symbol(frame, symbol); }); - } - if printer.skipped { + if stop { + return false; + } + if !hit { + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); + } + + idx += 1; + res.is_ok() + }); + res?; + bt_fmt.finish()?; + if print_fmt == PrintFmt::Short { writeln!( - w, + fmt, "note: Some details are omitted, \ run with `RUST_BACKTRACE=full` for a verbose backtrace." )?; @@ -77,33 +126,32 @@ where f() } -/// Controls how the backtrace should be formatted. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum PrintFormat { - /// Show only relevant data from the backtrace. - Short = 2, - /// Show all the frames with absolute path for files. - Full = 3, -} - // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. -pub fn log_enabled() -> Option { +pub fn log_enabled() -> Option { + use crate::sync::atomic::{self, Ordering}; + + // Setting environment variables for Fuchsia components isn't a standard + // or easily supported workflow. For now, always display backtraces. + if cfg!(target_os = "fuchsia") { + return Some(PrintFmt::Full); + } + static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Short), - _ => return Some(PrintFormat::Full), + 2 => return Some(PrintFmt::Short), + _ => return Some(PrintFmt::Full), } let val = env::var_os("RUST_BACKTRACE").and_then(|x| { if &x == "0" { None } else if &x == "full" { - Some(PrintFormat::Full) + Some(PrintFmt::Full) } else { - Some(PrintFormat::Short) + Some(PrintFmt::Short) } }); ENABLED.store( @@ -116,130 +164,43 @@ pub fn log_enabled() -> Option { val } -struct Printer<'a, 'b> { - format: PrintFormat, - done: bool, - skipped: bool, - idx: usize, - out: &'a mut (dyn Write + 'b), -} - -impl<'a, 'b> Printer<'a, 'b> { - fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> { - Printer { format, done: false, skipped: false, idx: 0, out } - } - - /// Prints the symbol of the backtrace frame. - /// - /// These output functions should now be used everywhere to ensure consistency. - /// You may want to also use `output_fileline`. - fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) { - if self.idx > MAX_NB_FRAMES { - self.done = true; - self.skipped = true; - return; - } - if self._output(frame, symbol).is_err() { - self.done = true; - } - self.idx += 1; - } - - fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> { - if self.format == PrintFormat::Short { - if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) { - if sym.contains("__rust_begin_short_backtrace") { - self.skipped = true; - self.done = true; - return Ok(()); - } - } - - // Remove the `17: 0x0 - ` line. - if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() { - self.skipped = true; - return Ok(()); - } - } - - match self.format { - PrintFormat::Full => { - write!(self.out, " {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)? - } - PrintFormat::Short => write!(self.out, " {:2}: ", self.idx)?, - } - - match symbol.and_then(|s| s.name()) { - Some(symbol) => { - match self.format { - PrintFormat::Full => write!(self.out, "{}", symbol)?, - // Strip the trailing hash if short mode. - PrintFormat::Short => write!(self.out, "{:#}", symbol)?, - } - } - None => self.out.write_all(b"")?, +/// Prints the filename of the backtrace frame. +/// +/// See also `output`. +pub fn output_filename( + fmt: &mut fmt::Formatter<'_>, + bows: BytesOrWideString<'_>, + print_fmt: PrintFmt, + cwd: Option<&PathBuf>, +) -> fmt::Result { + let file: Cow<'_, Path> = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use crate::os::unix::prelude::*; + Path::new(crate::ffi::OsStr::from_bytes(bytes)).into() } - self.out.write_all(b"\n")?; - if let Some(sym) = symbol { - self.output_fileline(sym)?; + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(crate::str::from_utf8(bytes).unwrap_or("")).into() } - Ok(()) - } - - /// Prints the filename and line number of the backtrace frame. - /// - /// See also `output`. - fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> { #[cfg(windows)] - let path_buf; - let file = match symbol.filename_raw() { - #[cfg(unix)] - Some(BytesOrWideString::Bytes(bytes)) => { - use crate::os::unix::prelude::*; - Path::new(crate::ffi::OsStr::from_bytes(bytes)) - } - #[cfg(not(unix))] - Some(BytesOrWideString::Bytes(bytes)) => { - Path::new(crate::str::from_utf8(bytes).unwrap_or("")) - } - #[cfg(windows)] - Some(BytesOrWideString::Wide(wide)) => { - use crate::os::windows::prelude::*; - path_buf = crate::ffi::OsString::from_wide(wide); - Path::new(&path_buf) - } - #[cfg(not(windows))] - Some(BytesOrWideString::Wide(_wide)) => { - Path::new("") - } - None => return Ok(()), - }; - let line = match symbol.lineno() { - Some(line) => line, - None => return Ok(()), - }; - // prior line: " ##: {:2$} - func" - self.out.write_all(b"")?; - match self.format { - PrintFormat::Full => write!(self.out, " {:1$}", "", HEX_WIDTH)?, - PrintFormat::Short => write!(self.out, " ")?, + BytesOrWideString::Wide(wide) => { + use crate::os::windows::prelude::*; + Cow::Owned(crate::ffi::OsString::from_wide(wide).into()) } - - let mut already_printed = false; - if self.format == PrintFormat::Short && file.is_absolute() { - if let Ok(cwd) = env::current_dir() { - if let Ok(stripped) = file.strip_prefix(&cwd) { - if let Some(s) = stripped.to_str() { - write!(self.out, " at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?; - already_printed = true; - } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => { + Path::new("").into() + } + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Some(cwd) = cwd { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); } } } - if !already_printed { - write!(self.out, " at {}:{}", file.display(), line)?; - } - - self.out.write_all(b"\n") } + fmt::Display::fmt(&file.display(), fmt) } diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 9190a3b0d5..cba3eca538 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -41,7 +41,6 @@ macro_rules! rtunwrap { pub mod alloc; pub mod at_exit_imp; -#[cfg(feature = "backtrace")] pub mod backtrace; pub mod condvar; pub mod io; diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index 4d40dec972..bdf66fca35 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -1,47 +1,20 @@ #![allow(dead_code)] #![unstable(feature = "process_internals", issue = "0")] -use crate::ffi::{OsStr, OsString}; -use crate::env; use crate::collections::BTreeMap; -use crate::borrow::Borrow; - -pub trait EnvKey: - From + Into + - Borrow + Borrow + AsRef + - Ord + Clone {} - -// Implement a case-sensitive environment variable key -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct DefaultEnvKey(OsString); - -impl From for DefaultEnvKey { - fn from(k: OsString) -> Self { DefaultEnvKey(k) } -} - -impl From for OsString { - fn from(k: DefaultEnvKey) -> Self { k.0 } -} - -impl Borrow for DefaultEnvKey { - fn borrow(&self) -> &OsStr { &self.0 } -} - -impl AsRef for DefaultEnvKey { - fn as_ref(&self) -> &OsStr { &self.0 } -} - -impl EnvKey for DefaultEnvKey {} +use crate::env; +use crate::ffi::{OsStr, OsString}; +use crate::sys::process::EnvKey; // Stores a set of changes to an environment #[derive(Clone, Debug)] -pub struct CommandEnv { +pub struct CommandEnv { clear: bool, saw_path: bool, - vars: BTreeMap> + vars: BTreeMap> } -impl Default for CommandEnv { +impl Default for CommandEnv { fn default() -> Self { CommandEnv { clear: false, @@ -51,10 +24,10 @@ impl Default for CommandEnv { } } -impl CommandEnv { +impl CommandEnv { // Capture the current environment with these changes applied - pub fn capture(&self) -> BTreeMap { - let mut result = BTreeMap::::new(); + pub fn capture(&self) -> BTreeMap { + let mut result = BTreeMap::::new(); if !self.clear { for (k, v) in env::vars_os() { result.insert(k.into(), v); @@ -90,7 +63,7 @@ impl CommandEnv { !self.clear && self.vars.is_empty() } - pub fn capture_if_changed(&self) -> Option> { + pub fn capture_if_changed(&self) -> Option> { if self.is_unchanged() { None } else { @@ -103,6 +76,7 @@ impl CommandEnv { self.maybe_saw_path(&key); self.vars.insert(key.to_owned().into(), Some(value.to_owned())); } + pub fn remove(&mut self, key: &OsStr) { self.maybe_saw_path(&key); if self.clear { @@ -111,13 +85,16 @@ impl CommandEnv { self.vars.insert(key.to_owned().into(), None); } } + pub fn clear(&mut self) { self.clear = true; self.vars.clear(); } + pub fn have_changed_path(&self) -> bool { self.saw_path || self.clear } + fn maybe_saw_path(&mut self, key: &OsStr) { if !self.saw_path && key == "PATH" { self.saw_path = true; diff --git a/src/libstd/tests/env.rs b/src/libstd/tests/env.rs index 06fb5533af..f8014cb2ad 100644 --- a/src/libstd/tests/env.rs +++ b/src/libstd/tests/env.rs @@ -5,7 +5,7 @@ use rand::{thread_rng, Rng}; use rand::distributions::Alphanumeric; fn make_rand_name() -> OsString { - let mut rng = thread_rng(); + let rng = thread_rng(); let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10) .collect::()); let n = OsString::from(n); diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 98371b9ba3..3bf2b8be1f 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -59,6 +59,30 @@ pub use core::time::Duration; /// println!("{}", now.elapsed().as_secs()); /// } /// ``` +/// +/// # Underlying System calls +/// Currently, the following system calls are being used to get the current time using `now()`: +/// +/// | Platform | System call | +/// |:---------:|:--------------------------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Monotonic Clock)] | +/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | +/// | UNIX | [clock_time_get (Monotonic Clock)] | +/// | Darwin | [mach_absolute_time] | +/// | VXWorks | [clock_gettime (Monotonic Clock)] | +/// | WASI | [__wasi_clock_time_get (Monotonic Clock)] | +/// | Windows | [QueryPerformanceCounter] | +/// +/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter +/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time +/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode +/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get +/// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime +/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html +/// [clock_time_get (Monotonic Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt +/// +/// **Disclaimer:** These system calls might change over time. +/// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct Instant(time::Instant); @@ -114,6 +138,28 @@ pub struct Instant(time::Instant); /// } /// } /// ``` +/// +/// # Underlying System calls +/// Currently, the following system calls are being used to get the current time using `now()`: +/// +/// | Platform | System call | +/// |:---------:|:--------------------------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Realtime Clock)] | +/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | +/// | UNIX | [clock_gettime (Realtime Clock)] | +/// | DARWIN | [gettimeofday] | +/// | VXWorks | [clock_gettime (Realtime Clock)] | +/// | WASI | [__wasi_clock_time_get (Realtime Clock)] | +/// | Windows | [GetSystemTimeAsFileTime] | +/// +/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt +/// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html +/// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime +/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get +/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime +/// +/// **Disclaimer:** These system calls might change over time. +/// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTime(time::SystemTime); @@ -216,12 +262,11 @@ impl Instant { } /// Returns the amount of time elapsed from another instant to this one, - /// or None if that instant is earlier than this one. + /// or None if that instant is later than this one. /// /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -231,7 +276,7 @@ impl Instant { /// println!("{:?}", new_now.checked_duration_since(now)); /// println!("{:?}", now.checked_duration_since(new_now)); // None /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn checked_duration_since(&self, earlier: Instant) -> Option { self.0.checked_sub_instant(&earlier.0) } @@ -242,7 +287,6 @@ impl Instant { /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -252,7 +296,7 @@ impl Instant { /// println!("{:?}", new_now.saturating_duration_since(now)); /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0)) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 052eb55b40..b634dcca7f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -5,7 +5,7 @@ pub use UnsafeSource::*; pub use crate::symbol::{Ident, Symbol as Name}; pub use crate::util::parser::ExprPrecedence; -use crate::ext::hygiene::{ExpnId, SyntaxContext}; +use crate::ext::hygiene::ExpnId; use crate::parse::token::{self, DelimToken}; use crate::print::pprust; use crate::ptr::P; @@ -352,7 +352,7 @@ pub struct GenericParam { pub ident: Ident, pub attrs: ThinVec, pub bounds: GenericBounds, - + pub is_placeholder: bool, pub kind: GenericParamKind, } @@ -413,11 +413,11 @@ impl WherePredicate { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereBoundPredicate { pub span: Span, - /// Any generics from a `for` binding + /// Any generics from a `for` binding. pub bound_generic_params: Vec, - /// The type being bounded + /// The type being bounded. pub bounded_ty: P, - /// Trait and lifetime bounds (`Clone+Send+'static`) + /// Trait and lifetime bounds (`Clone + Send + 'static`). pub bounds: GenericBounds, } @@ -495,15 +495,15 @@ pub enum MetaItemKind { NameValue(Lit), } -/// A Block (`{ .. }`). +/// A block (`{ .. }`). /// /// E.g., `{ .. }` as in `fn foo() { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Block { - /// Statements in a block + /// The statements in the block. pub stmts: Vec, pub id: NodeId, - /// Distinguishes between `unsafe { ... }` and `{ ... }` + /// Distinguishes between `unsafe { ... }` and `{ ... }`. pub rules: BlockCheckMode, pub span: Span, } @@ -561,28 +561,31 @@ impl Pat { })) } - pub fn walk(&self, it: &mut F) -> bool - where - F: FnMut(&Pat) -> bool, - { + /// Walk top-down and call `it` in each place where a pattern occurs + /// starting with the root pattern `walk` is called on. If `it` returns + /// false then we will descend no further but siblings will be processed. + pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) { if !it(self) { - return false; + return; } match &self.node { PatKind::Ident(_, _, Some(p)) => p.walk(it), - PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)), - PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => { - s.iter().all(|p| p.walk(it)) - } - PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it), + PatKind::Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)), + PatKind::TupleStruct(_, s) + | PatKind::Tuple(s) + | PatKind::Slice(s) + | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)), + PatKind::Box(s) + | PatKind::Ref(s, _) + | PatKind::Paren(s) => s.walk(it), PatKind::Wild | PatKind::Rest | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) - | PatKind::Mac(_) => true, + | PatKind::Mac(_) => {}, } } @@ -608,6 +611,9 @@ pub struct FieldPat { pub pat: P, pub is_shorthand: bool, pub attrs: ThinVec, + pub id: NodeId, + pub span: Span, + pub is_placeholder: bool, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] @@ -641,11 +647,15 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(Path, Vec>, /* recovered */ bool), + Struct(Path, Vec, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). TupleStruct(Path, Vec>), + /// An or-pattern `A | B | C`. + /// Invariant: `pats.len() >= 2`. + Or(Vec>), + /// A possibly qualified path pattern. /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Qualified path patterns `::B::C`/`::B::C` can @@ -899,11 +909,11 @@ pub enum MacStmtStyle { /// Local represents a `let` statement, e.g., `let : = ;`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Local { + pub id: NodeId, pub pat: P, pub ty: Option>, /// Initializer expression to set the value, if any. pub init: Option>, - pub id: NodeId, pub span: Span, pub attrs: ThinVec, } @@ -921,10 +931,12 @@ pub struct Local { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Arm { pub attrs: Vec, - pub pats: Vec>, + pub pat: P, pub guard: Option>, pub body: P, pub span: Span, + pub id: NodeId, + pub is_placeholder: bool, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -934,10 +946,10 @@ pub struct Field { pub span: Span, pub is_shorthand: bool, pub attrs: ThinVec, + pub id: NodeId, + pub is_placeholder: bool, } -pub type SpannedIdent = Spanned; - #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BlockCheckMode { Default, @@ -961,7 +973,7 @@ pub struct AnonConst { pub value: P, } -/// An expression +/// An expression. #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Expr { pub id: NodeId, @@ -975,26 +987,26 @@ pub struct Expr { static_assert_size!(Expr, 96); impl Expr { - /// Whether this expression would be valid somewhere that expects a value; for example, an `if` - /// condition. + /// Returns `true` if this expression would be valid somewhere that expects a value; + /// for example, an `if` condition. pub fn returns(&self) -> bool { if let ExprKind::Block(ref block, _) = self.node { match block.stmts.last().map(|last_stmt| &last_stmt.node) { - // implicit return + // Implicit return Some(&StmtKind::Expr(_)) => true, Some(&StmtKind::Semi(ref expr)) => { if let ExprKind::Ret(_) = expr.node { - // last statement is explicit return + // Last statement is explicit return. true } else { false } } - // This is a block that doesn't end in either an implicit or explicit return + // This is a block that doesn't end in either an implicit or explicit return. _ => false, } } else { - // This is not a block, it is a value + // This is not a block, it is a value. true } } @@ -1139,12 +1151,9 @@ pub enum ExprKind { Cast(P, P), /// A type ascription (e.g., `42: usize`). Type(P, P), - /// A `let pats = expr` expression that is only semantically allowed in the condition + /// A `let pat = expr` expression that is only semantically allowed in the condition /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`). - /// - /// The `Vec>` is for or-patterns at the top level. - /// FIXME(54883): Change this to just `P`. - Let(Vec>, P), + Let(P, P), /// An `if` block, with an optional `else` block. /// /// `if expr { block } else { expr }` @@ -1284,8 +1293,6 @@ pub enum Movability { Movable, } -pub type Mac = Spanned; - /// Represents a macro invocation. The `Path` indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. @@ -1293,10 +1300,11 @@ pub type Mac = Spanned; /// N.B., the additional ident for a `macro_rules`-style macro is actually /// stored in the enclosing item. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Mac_ { +pub struct Mac { pub path: Path, pub delim: MacDelimiter, pub tts: TokenStream, + pub span: Span, pub prior_type_ascription: Option<(Span, bool)>, } @@ -1307,7 +1315,7 @@ pub enum MacDelimiter { Brace, } -impl Mac_ { +impl Mac { pub fn stream(&self) -> TokenStream { self.tts.clone() } @@ -1781,19 +1789,19 @@ pub struct InlineAsm { pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, - pub ctxt: SyntaxContext, } -/// An argument in a function header. +/// A parameter in a function header. /// /// E.g., `bar: usize` as in `fn foo(bar: usize)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Arg { +pub struct Param { pub attrs: ThinVec, pub ty: P, pub pat: P, pub id: NodeId, pub span: Span, + pub is_placeholder: bool, } /// Alternative representation for `Arg`s describing `self` parameter of methods. @@ -1811,7 +1819,7 @@ pub enum SelfKind { pub type ExplicitSelf = Spanned; -impl Arg { +impl Param { pub fn to_self(&self) -> Option { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { if ident.name == kw::SelfLower { @@ -1838,14 +1846,14 @@ impl Arg { } } - pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Arg { + pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Param { let span = eself.span.to(eself_ident.span); let infer_ty = P(Ty { id: DUMMY_NODE_ID, node: TyKind::ImplicitSelf, span, }); - let arg = |mutbl, ty| Arg { + let param = |mutbl, ty| Param { attrs, pat: P(Pat { id: DUMMY_NODE_ID, @@ -1855,11 +1863,12 @@ impl Arg { span, ty, id: DUMMY_NODE_ID, + is_placeholder: false }; match eself.node { - SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), - SelfKind::Value(mutbl) => arg(mutbl, infer_ty), - SelfKind::Region(lt, mutbl) => arg( + SelfKind::Explicit(ty, mutbl) => param(mutbl, ty), + SelfKind::Value(mutbl) => param(mutbl, infer_ty), + SelfKind::Region(lt, mutbl) => param( Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, @@ -1882,17 +1891,17 @@ impl Arg { /// E.g., `fn foo(bar: baz)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FnDecl { - pub inputs: Vec, + pub inputs: Vec, pub output: FunctionRetTy, pub c_variadic: bool, } impl FnDecl { pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) + self.inputs.get(0).and_then(Param::to_self) } pub fn has_self(&self) -> bool { - self.inputs.get(0).map(Arg::is_self).unwrap_or(false) + self.inputs.get(0).map(Param::is_self).unwrap_or(false) } } @@ -2029,7 +2038,6 @@ pub struct ForeignMod { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct GlobalAsm { pub asm: Symbol, - pub ctxt: SyntaxContext, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2038,7 +2046,7 @@ pub struct EnumDef { } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Variant_ { +pub struct Variant { /// Name of the variant. pub ident: Ident, /// Attributes of the variant. @@ -2049,10 +2057,12 @@ pub struct Variant_ { pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, + /// Span + pub span: Span, + /// Is a macro placeholder + pub is_placeholder: bool, } -pub type Variant = Spanned; - /// Part of `use` item to the right of its prefix. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum UseTreeKind { @@ -2213,6 +2223,7 @@ pub struct StructField { pub id: NodeId, pub ty: P, pub attrs: Vec, + pub is_placeholder: bool, } /// Fields and constructor ids of enum variants and structs. @@ -2304,37 +2315,37 @@ impl Default for FnHeader { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ItemKind { - /// An `extern crate` item, with optional *original* crate name if the crate was renamed. + /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. ExternCrate(Option), - /// A use declaration (`use` or `pub use`) item. + /// A use declaration item (`use`). /// /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. Use(P), - /// A static item (`static` or `pub static`). + /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. Static(P, Mutability, P), - /// A constant item (`const` or `pub const`). + /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. Const(P, P), - /// A function declaration (`fn` or `pub fn`). + /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. Fn(P, FnHeader, Generics, P), - /// A module declaration (`mod` or `pub mod`). + /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. Mod(Mod), - /// An external module (`extern` or `pub extern`). + /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. ForeignMod(ForeignMod), /// Module-level inline assembly (from `global_asm!()`). GlobalAsm(P), - /// A type alias (`type` or `pub type`). + /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. TyAlias(P, Generics), @@ -2342,19 +2353,19 @@ pub enum ItemKind { /// /// E.g., `type Foo = impl Bar + Boo;`. OpaqueTy(GenericBounds, Generics), - /// An enum definition (`enum` or `pub enum`). + /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. Enum(EnumDef, Generics), - /// A struct definition (`struct` or `pub struct`). + /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. Struct(VariantData, Generics), - /// A union definition (`union` or `pub union`). + /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. Union(VariantData, Generics), - /// A Trait declaration (`trait` or `pub trait`). + /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), @@ -2376,7 +2387,7 @@ pub enum ItemKind { ), /// A macro invocation. /// - /// E.g., `macro_rules! foo { .. }` or `foo!(..)`. + /// E.g., `foo!(..)`. Mac(Mac), /// A macro definition. diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index a9d3227b3a..9d06b926f9 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -1,4 +1,4 @@ -//! Functions dealing with attributes and meta items +//! Functions dealing with attributes and meta items. mod builtin; @@ -13,10 +13,10 @@ use crate::ast::{AttrId, AttrStyle, Name, Ident, Path, PathSegment}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; -use crate::source_map::{BytePos, Spanned, dummy_spanned}; +use crate::source_map::{BytePos, Spanned, DUMMY_SP}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::parser::Parser; -use crate::parse::{self, ParseSess, PResult}; +use crate::parse::{ParseSess, PResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; use crate::symbol::{sym, Symbol}; @@ -25,7 +25,7 @@ use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; use log::debug; -use syntax_pos::{FileName, Span}; +use syntax_pos::Span; use std::iter; use std::ops::DerefMut; @@ -61,7 +61,7 @@ pub fn is_known_lint_tool(m_item: Ident) -> bool { } impl NestedMetaItem { - /// Returns the MetaItem if self is a NestedMetaItem::MetaItem. + /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { match *self { NestedMetaItem::MetaItem(ref item) => Some(item), @@ -69,7 +69,7 @@ impl NestedMetaItem { } } - /// Returns the Lit if self is a NestedMetaItem::Literal. + /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s. pub fn literal(&self) -> Option<&Lit> { match *self { NestedMetaItem::Literal(ref lit) => Some(lit), @@ -82,7 +82,7 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// For a single-segment meta-item returns its name, otherwise returns `None`. + /// For a single-segment meta item, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) } @@ -90,13 +90,13 @@ impl NestedMetaItem { self.ident().unwrap_or(Ident::invalid()).name } - /// Gets the string value if self is a MetaItem and the MetaItem is a - /// MetaItemKind::NameValue variant containing a string, otherwise None. + /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a + /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`. pub fn value_str(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.value_str()) } - /// Returns a name and single literal value tuple of the MetaItem. + /// Returns a name and single literal value tuple of the `MetaItem`. pub fn name_value_literal(&self) -> Option<(Name, &Lit)> { self.meta_item().and_then( |meta_item| meta_item.meta_item_list().and_then( @@ -112,32 +112,32 @@ impl NestedMetaItem { })) } - /// Gets a list of inner meta items from a list MetaItem type. + /// Gets a list of inner meta items from a list `MetaItem` type. pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { self.meta_item().and_then(|meta_item| meta_item.meta_item_list()) } - /// Returns `true` if the variant is MetaItem. + /// Returns `true` if the variant is `MetaItem`. pub fn is_meta_item(&self) -> bool { self.meta_item().is_some() } - /// Returns `true` if the variant is Literal. + /// Returns `true` if the variant is `Literal`. pub fn is_literal(&self) -> bool { self.literal().is_some() } - /// Returns `true` if self is a MetaItem and the meta item is a word. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a word. pub fn is_word(&self) -> bool { self.meta_item().map_or(false, |meta_item| meta_item.is_word()) } - /// Returns `true` if self is a MetaItem and the meta item is a ValueString. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`. pub fn is_value_str(&self) -> bool { self.value_str().is_some() } - /// Returns `true` if self is a MetaItem and the meta item is a list. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a list. pub fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() } @@ -156,7 +156,7 @@ impl Attribute { matches } - /// For a single-segment attribute returns its name, otherwise returns `None`. + /// For a single-segment attribute, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) @@ -187,14 +187,14 @@ impl Attribute { self.meta_item_list().is_some() } - /// Indicates if the attribute is a Value String. + /// Indicates if the attribute is a `ValueString`. pub fn is_value_str(&self) -> bool { self.value_str().is_some() } } impl MetaItem { - /// For a single-segment meta-item returns its name, otherwise returns `None`. + /// For a single-segment meta item, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) @@ -206,8 +206,9 @@ impl MetaItem { self.ident().unwrap_or(Ident::invalid()).name } - // #[attribute(name = "value")] - // ^^^^^^^^^^^^^^ + // Example: + // #[attribute(name = "value")] + // ^^^^^^^^^^^^^^ pub fn name_value_literal(&self) -> Option<&Lit> { match &self.node { MetaItemKind::NameValue(v) => Some(v), @@ -255,7 +256,7 @@ impl MetaItem { } impl Attribute { - /// Extracts the MetaItem from inside this Attribute. + /// Extracts the `MetaItem` from inside this `Attribute`. pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { @@ -318,8 +319,8 @@ impl Attribute { }) } - /// Converts self to a normal #[doc="foo"] comment, if it is a - /// comment like `///` or `/** */`. (Returns self unchanged for + /// Converts `self` to a normal `#[doc="foo"]` comment, if it is a + /// comment like `///` or `/** */`. (Returns `self` unchanged for /// non-sugared doc attributes.) pub fn with_desugared_doc(&self, f: F) -> T where F: FnOnce(&Attribute) -> T, @@ -327,8 +328,10 @@ impl Attribute { if self.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( - Ident::with_empty_ctxt(sym::doc), - dummy_spanned(Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())))); + Ident::with_dummy_span(sym::doc), + Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())), + DUMMY_SP, + ); f(&Attribute { id: self.id, style: self.style, @@ -345,9 +348,9 @@ impl Attribute { /* Constructors */ -pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { - let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked); - mk_name_value_item(ident, lit_kind, value.span) +pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem { + let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked); + mk_name_value_item(ident, lit_kind, str_span) } pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { @@ -379,28 +382,25 @@ crate fn mk_attr_id() -> AttrId { AttrId(id) } -/// Returns an inner attribute with the given value and span. -pub fn mk_attr_inner(item: MetaItem) -> Attribute { +pub fn mk_attr(style: AttrStyle, path: Path, tokens: TokenStream, span: Span) -> Attribute { Attribute { id: mk_attr_id(), - style: ast::AttrStyle::Inner, - path: item.path, - tokens: item.node.tokens(item.span), + style, + path, + tokens, is_sugared_doc: false, - span: item.span, + span, } } +/// Returns an inner attribute with the given value and span. +pub fn mk_attr_inner(item: MetaItem) -> Attribute { + mk_attr(AttrStyle::Inner, item.path, item.node.tokens(item.span), item.span) +} + /// Returns an outer attribute with the given value and span. pub fn mk_attr_outer(item: MetaItem) -> Attribute { - Attribute { - id: mk_attr_id(), - style: ast::AttrStyle::Outer, - path: item.path, - tokens: item.node.tokens(item.span), - is_sugared_doc: false, - span: item.span, - } + mk_attr(AttrStyle::Outer, item.path, item.node.tokens(item.span), item.span) } pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute { @@ -410,7 +410,7 @@ pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute { Attribute { id: mk_attr_id(), style, - path: Path::from_ident(Ident::with_empty_ctxt(sym::doc).with_span_pos(span)), + path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)), tokens: MetaItemKind::NameValue(lit).tokens(span), is_sugared_doc: true, span, @@ -433,6 +433,30 @@ pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> { attrs.iter().find(|attr| attr.check_name(name)) } +pub fn allow_internal_unstable<'a>( + attrs: &[Attribute], + span_diagnostic: &'a errors::Handler, +) -> Option + 'a> { + find_by_name(attrs, sym::allow_internal_unstable).and_then(|attr| { + attr.meta_item_list().or_else(|| { + span_diagnostic.span_err( + attr.span, + "allow_internal_unstable expects list of feature names" + ); + None + }).map(|features| features.into_iter().filter_map(move |it| { + let name = it.ident().map(|ident| ident.name); + if name.is_none() { + span_diagnostic.span_err( + it.span(), + "`allow_internal_unstable` expects feature names", + ) + } + name + })) + }) +} + pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator { attrs.iter().filter(move |attr| attr.check_name(name)) @@ -712,35 +736,5 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_, ast::Arg -} - -pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { - for raw_attr in attrs { - let mut parser = parse::new_parser_from_source_str( - parse_sess, - FileName::cli_crate_attr_source_code(&raw_attr), - raw_attr.clone(), - ); - - let start_span = parser.token.span; - let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted()); - let end_span = parser.token.span; - if parser.token != token::Eof { - parse_sess.span_diagnostic - .span_err(start_span.to(end_span), "invalid crate attribute"); - continue; - } - - krate.attrs.push(Attribute { - id: mk_attr_id(), - style: AttrStyle::Inner, - path, - tokens, - is_sugared_doc: false, - span: start_span.to(end_span), - }); - } - - krate + ast::Field, ast::FieldPat, ast::Variant, ast::Param } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 1ab367f73c..7eeea4e7bd 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -260,7 +260,7 @@ impl<'a> StripUnconfigured<'a> { ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => { variants.flat_map_in_place(|variant| self.configure(variant)); for variant in variants { - self.configure_variant_data(&mut variant.node.data); + self.configure_variant_data(&mut variant.data); } } _ => {} diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b754d08337..c95c5bd5d0 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -1,13 +1,14 @@ #[macro_export] -macro_rules! register_diagnostic { - ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); - ($code:tt) => (__register_diagnostic! { $code }) +macro_rules! diagnostic_used { + ($code:ident) => ( + let _ = crate::error_codes::$code; + ) } #[macro_export] macro_rules! span_fatal { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_fatal_with_code( $span, &format!($($message)*), @@ -19,7 +20,7 @@ macro_rules! span_fatal { #[macro_export] macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_err_with_code( $span, &format!($($message)*), @@ -31,7 +32,7 @@ macro_rules! span_err { #[macro_export] macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_warn_with_code( $span, &format!($($message)*), @@ -43,7 +44,7 @@ macro_rules! span_warn { #[macro_export] macro_rules! struct_err { ($session:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_err_with_code( &format!($($message)*), $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), @@ -54,7 +55,7 @@ macro_rules! struct_err { #[macro_export] macro_rules! span_err_or_warn { ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); if $is_warning { $session.span_warn_with_code( $span, @@ -74,7 +75,7 @@ macro_rules! span_err_or_warn { #[macro_export] macro_rules! struct_span_fatal { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_fatal_with_code( $span, &format!($($message)*), @@ -86,7 +87,7 @@ macro_rules! struct_span_fatal { #[macro_export] macro_rules! struct_span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_err_with_code( $span, &format!($($message)*), @@ -98,7 +99,7 @@ macro_rules! struct_span_err { #[macro_export] macro_rules! stringify_error_code { ($code:ident) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()) }) } @@ -117,7 +118,7 @@ macro_rules! type_error_struct { #[macro_export] macro_rules! struct_span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_warn_with_code( $span, &format!($($message)*), @@ -129,7 +130,7 @@ macro_rules! struct_span_warn { #[macro_export] macro_rules! struct_span_err_or_warn { ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); if $is_warning { $session.struct_span_warn_with_code( $span, @@ -169,20 +170,22 @@ macro_rules! help { #[macro_export] macro_rules! register_diagnostics { - ($($code:tt),*) => ( - $($crate::register_diagnostic! { $code })* + ($($ecode:ident: $message:expr,)*) => ( + $crate::register_diagnostics!{$($ecode:$message,)* ;} ); - ($($code:tt),*,) => ( - $($crate::register_diagnostic! { $code })* - ) -} -#[macro_export] -macro_rules! register_long_diagnostics { - ($($code:tt: $description:tt),*) => ( - $($crate::register_diagnostic! { $code, $description })* - ); - ($($code:tt: $description:tt),*,) => ( - $($crate::register_diagnostic! { $code, $description })* + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + pub static DIAGNOSTICS: &[(&str, &str)] = &[ + $( (stringify!($ecode), $message), )* + ]; + + $( + #[deny(unused)] + pub(crate) const $ecode: &str = $message; + )* + $( + #[deny(unused)] + pub(crate) const $code: () = (); + )* ) } diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs deleted file mode 100644 index 53f37bb10b..0000000000 --- a/src/libsyntax/diagnostics/metadata.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! This module contains utilities for outputting metadata for diagnostic errors. -//! -//! Each set of errors is mapped to a metadata file by a name, which is -//! currently always a crate name. - -use std::collections::BTreeMap; -use std::env; -use std::fs::{remove_file, create_dir_all, File}; -use std::io::Write; -use std::path::PathBuf; -use std::error::Error; -use rustc_serialize::json::as_json; - -use syntax_pos::{Span, FileName}; - -use crate::ext::base::ExtCtxt; -use crate::diagnostics::plugin::{ErrorMap, ErrorInfo}; - -/// JSON encodable/decodable version of `ErrorInfo`. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorMetadata { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata that can be (de)serialized. -pub type ErrorMetadataMap = BTreeMap; - -/// JSON encodable error location type with filename and line number. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorLocation { - pub filename: FileName, - pub line: usize -} - -impl ErrorLocation { - /// Creates an error location from a span. - pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation { - let loc = ecx.source_map().lookup_char_pos(sp.lo()); - ErrorLocation { - filename: loc.file.name.clone(), - line: loc.line - } - } -} - -/// Gets the directory where metadata for a given `prefix` should be stored. -/// -/// See `output_metadata`. -pub fn get_metadata_dir(prefix: &str) -> PathBuf { - env::var_os("RUSTC_ERROR_METADATA_DST") - .map(PathBuf::from) - .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set") - .join(prefix) -} - -/// Map `name` to a path in the given directory: /.json -fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf { - directory.join(format!("{}.json", name)) -} - -/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`. -/// -/// For our current purposes the prefix is the target architecture and the name is a crate name. -/// If an error occurs steps will be taken to ensure that no file is created. -pub fn output_metadata(ecx: &ExtCtxt<'_>, prefix: &str, name: &str, err_map: &ErrorMap) - -> Result<(), Box> -{ - // Create the directory to place the file in. - let metadata_dir = get_metadata_dir(prefix); - create_dir_all(&metadata_dir)?; - - // Open the metadata file. - let metadata_path = get_metadata_path(metadata_dir, name); - let mut metadata_file = File::create(&metadata_path)?; - - // Construct a serializable map. - let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| { - let key = k.as_str().to_string(); - let value = ErrorMetadata { - description: description.map(|n| n.as_str().to_string()), - use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp)) - }; - (key, value) - }).collect::(); - - // Write the data to the file, deleting it if the write fails. - let result = write!(&mut metadata_file, "{}", as_json(&json_map)); - if result.is_err() { - remove_file(&metadata_path)?; - } - Ok(result?) -} diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs deleted file mode 100644 index 80591ad304..0000000000 --- a/src/libsyntax/diagnostics/plugin.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::collections::BTreeMap; -use std::env; - -use crate::ast::{self, Ident, Name}; -use crate::source_map; -use crate::ext::base::{ExtCtxt, MacEager, MacResult}; -use crate::parse::token::{self, Token}; -use crate::ptr::P; -use crate::symbol::kw; -use crate::tokenstream::{TokenTree}; - -use smallvec::smallvec; -use syntax_pos::Span; - -use crate::diagnostics::metadata::output_metadata; - -pub use errors::*; - -// Maximum width of any line in an extended error description (inclusive). -const MAX_DESCRIPTION_WIDTH: usize = 80; - -/// Error information type. -pub struct ErrorInfo { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata. -pub type ErrorMap = BTreeMap; - -pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - let code = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => code, - _ => unreachable!() - }; - - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - match diagnostics.get_mut(&code) { - // Previously used errors. - Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => { - ecx.struct_span_warn(span, &format!( - "diagnostic code {} already used", code - )).span_note(previous_span, "previous invocation") - .emit(); - } - // Newly used errors. - Some(ref mut info) => { - info.use_site = Some(span); - } - // Unregistered errors. - None => { - ecx.span_err(span, &format!( - "used diagnostic code {} not registered", code - )); - } - } - }); - MacEager::expr(ecx.expr_tuple(span, Vec::new())) -} - -pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - let (code, description) = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => { - (*code, None) - }, - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }), - TokenTree::Token(Token { kind: token::Comma, .. }), - TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..}) - ] => { - (*code, Some(*symbol)) - }, - _ => unreachable!() - }; - - // Check that the description starts and ends with a newline and doesn't - // overflow the maximum line width. - description.map(|raw_msg| { - let msg = raw_msg.as_str(); - if !msg.starts_with("\n") || !msg.ends_with("\n") { - ecx.span_err(span, &format!( - "description for error code {} doesn't start and end with a newline", - code - )); - } - - // URLs can be unavoidably longer than the line limit, so we allow them. - // Allowed format is: `[name]: https://www.rust-lang.org/` - let is_url = |l: &str| l.starts_with("[") && l.contains("]:") && l.contains("http"); - - if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) { - ecx.span_err(span, &format!( - "description for error code {} contains a line longer than {} characters.\n\ - if you're inserting a long URL use the footnote style to bypass this check.", - code, MAX_DESCRIPTION_WIDTH - )); - } - }); - // Add the error to the map. - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let info = ErrorInfo { - description, - use_site: None - }; - if diagnostics.insert(code, info).is_some() { - ecx.span_err(span, &format!( - "diagnostic code {} already registered", code - )); - } - }); - - MacEager::items(smallvec![]) -} - -pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - assert_eq!(token_tree.len(), 3); - let (crate_name, ident) = match (&token_tree[0], &token_tree[2]) { - ( - // Crate name. - &TokenTree::Token(Token { kind: token::Ident(crate_name, _), .. }), - // DIAGNOSTICS ident. - &TokenTree::Token(Token { kind: token::Ident(name, _), span }) - ) => (crate_name, Ident::new(name, span)), - _ => unreachable!() - }; - - // Output error metadata to `tmp/extended-errors//.json` - if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") { - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - if let Err(e) = output_metadata(ecx, - &target_triple, - &crate_name.as_str(), - diagnostics) { - ecx.span_bug(span, &format!( - "error writing metadata for triple `{}` and crate `{}`, error: {}, \ - cause: {:?}", - target_triple, crate_name, e.description(), e.source() - )); - } - }); - } else { - ecx.span_err(span, &format!( - "failed to write metadata for crate `{}` because $CFG_COMPILER_HOST_TRIPLE is not set", - crate_name)); - } - - // Construct the output expression. - let (count, expr) = - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let descriptions: Vec> = - diagnostics.iter().filter_map(|(&code, info)| { - info.description.map(|description| { - ecx.expr_tuple(span, vec![ - ecx.expr_str(span, code), - ecx.expr_str(span, description) - ]) - }) - }).collect(); - (descriptions.len(), ecx.expr_vec(span, descriptions)) - }); - - let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime)); - let ty_str = ecx.ty_rptr( - span, - ecx.ty_ident(span, ecx.ident_of("str")), - Some(static_), - ast::Mutability::Immutable, - ); - - let ty = ecx.ty( - span, - ast::TyKind::Array( - ecx.ty( - span, - ast::TyKind::Tup(vec![ty_str.clone(), ty_str]) - ), - ast::AnonConst { - id: ast::DUMMY_NODE_ID, - value: ecx.expr_usize(span, count), - }, - ), - ); - - MacEager::items(smallvec![ - P(ast::Item { - ident, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Const( - ty, - expr, - ), - vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Public), - span, - tokens: None, - }) - ]) -} diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 1ba29011f7..9925dd8ada 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -1,7 +1,8 @@ // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +register_diagnostics! { E0178: r##" In types, the `+` type operator has low precedence, so it is often necessary @@ -420,9 +421,8 @@ Delete the offending feature attribute, or add it to the list of allowed features in the `-Z allow_features` flag. "##, -} +; -register_diagnostics! { E0539, // incorrect meta item E0540, // multiple rustc_deprecated attributes E0542, // missing 'since' @@ -432,7 +432,9 @@ register_diagnostics! { E0546, // missing 'feature' E0547, // missing 'issue' // E0548, // replaced with a generic attribute input check - E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute + // rustc_deprecated attribute must be paired with either stable or unstable + // attribute + E0549, E0550, // multiple deprecated attributes E0551, // incorrect meta item E0553, // multiple rustc_const_unstable attributes @@ -440,9 +442,11 @@ register_diagnostics! { E0556, // malformed feature, expected just one word E0584, // file for module `..` found at both .. and .. E0629, // missing 'feature' (rustc_const_unstable) - E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute + // rustc_const_unstable attribute must be paired with stable/unstable + // attribute + E0630, E0693, // incorrect `repr(align)` attribute format - E0694, // an unknown tool name found in scoped attributes +// E0694, // an unknown tool name found in scoped attributes E0703, // invalid ABI E0717, // rustc_promotable without stability attribute } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 50ae052b4b..e189d8f863 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,21 +1,22 @@ -use crate::ast::{self, Attribute, Name, PatKind}; -use crate::attr::{HasAttrs, Stability, Deprecation}; -use crate::source_map::{SourceMap, Spanned, respan}; +use crate::ast::{self, NodeId, Attribute, Name, PatKind}; +use crate::attr::{self, HasAttrs, Stability, Deprecation}; +use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; -use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency}; +use crate::ext::hygiene::ExpnId; use crate::mut_visit::{self, MutVisitor}; -use crate::parse::{self, parser, DirectoryOwnership}; +use crate::parse::{self, parser, ParseSess, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; use crate::symbol::{kw, sym, Ident, Symbol}; use crate::{ThinVec, MACRO_ARGUMENTS}; -use crate::tokenstream::{self, TokenStream, TokenTree}; +use crate::tokenstream::{self, TokenStream}; +use crate::visit::Visitor; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnInfo, ExpnKind}; +use syntax_pos::hygiene::{AstPass, ExpnData, ExpnKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -34,6 +35,13 @@ pub enum Annotatable { ForeignItem(P), Stmt(P), Expr(P), + Arm(ast::Arm), + Field(ast::Field), + FieldPat(ast::FieldPat), + GenericParam(ast::GenericParam), + Param(ast::Param), + StructField(ast::StructField), + Variant(ast::Variant), } impl HasAttrs for Annotatable { @@ -45,6 +53,13 @@ impl HasAttrs for Annotatable { Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs, Annotatable::Stmt(ref stmt) => stmt.attrs(), Annotatable::Expr(ref expr) => &expr.attrs, + Annotatable::Arm(ref arm) => &arm.attrs, + Annotatable::Field(ref field) => &field.attrs, + Annotatable::FieldPat(ref fp) => &fp.attrs, + Annotatable::GenericParam(ref gp) => &gp.attrs, + Annotatable::Param(ref p) => &p.attrs, + Annotatable::StructField(ref sf) => &sf.attrs, + Annotatable::Variant(ref v) => &v.attrs(), } } @@ -56,6 +71,13 @@ impl HasAttrs for Annotatable { Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f), Annotatable::Stmt(stmt) => stmt.visit_attrs(f), Annotatable::Expr(expr) => expr.visit_attrs(f), + Annotatable::Arm(arm) => arm.visit_attrs(f), + Annotatable::Field(field) => field.visit_attrs(f), + Annotatable::FieldPat(fp) => fp.visit_attrs(f), + Annotatable::GenericParam(gp) => gp.visit_attrs(f), + Annotatable::Param(p) => p.visit_attrs(f), + Annotatable::StructField(sf) => sf.visit_attrs(f), + Annotatable::Variant(v) => v.visit_attrs(f), } } } @@ -69,6 +91,31 @@ impl Annotatable { Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, Annotatable::Stmt(ref stmt) => stmt.span, Annotatable::Expr(ref expr) => expr.span, + Annotatable::Arm(ref arm) => arm.span, + Annotatable::Field(ref field) => field.span, + Annotatable::FieldPat(ref fp) => fp.pat.span, + Annotatable::GenericParam(ref gp) => gp.ident.span, + Annotatable::Param(ref p) => p.span, + Annotatable::StructField(ref sf) => sf.span, + Annotatable::Variant(ref v) => v.span, + } + } + + pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { + match self { + Annotatable::Item(item) => visitor.visit_item(item), + Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item), + Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item), + Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item), + Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt), + Annotatable::Expr(expr) => visitor.visit_expr(expr), + Annotatable::Arm(arm) => visitor.visit_arm(arm), + Annotatable::Field(field) => visitor.visit_field(field), + Annotatable::FieldPat(fp) => visitor.visit_field_pattern(fp), + Annotatable::GenericParam(gp) => visitor.visit_generic_param(gp), + Annotatable::Param(p) => visitor.visit_param(p), + Annotatable::StructField(sf) =>visitor.visit_struct_field(sf), + Annotatable::Variant(v) => visitor.visit_variant(v), } } @@ -124,6 +171,55 @@ impl Annotatable { } } + pub fn expect_arm(self) -> ast::Arm { + match self { + Annotatable::Arm(arm) => arm, + _ => panic!("expected match arm") + } + } + + pub fn expect_field(self) -> ast::Field { + match self { + Annotatable::Field(field) => field, + _ => panic!("expected field") + } + } + + pub fn expect_field_pattern(self) -> ast::FieldPat { + match self { + Annotatable::FieldPat(fp) => fp, + _ => panic!("expected field pattern") + } + } + + pub fn expect_generic_param(self) -> ast::GenericParam { + match self { + Annotatable::GenericParam(gp) => gp, + _ => panic!("expected generic parameter") + } + } + + pub fn expect_param(self) -> ast::Param { + match self { + Annotatable::Param(param) => param, + _ => panic!("expected parameter") + } + } + + pub fn expect_struct_field(self) -> ast::StructField { + match self { + Annotatable::StructField(sf) => sf, + _ => panic!("expected struct field") + } + } + + pub fn expect_variant(self) -> ast::Variant { + match self { + Annotatable::Variant(v) => v, + _ => panic!("expected variant") + } + } + pub fn derive_allowed(&self) -> bool { match *self { Annotatable::Item(ref item) => match item.node { @@ -223,18 +319,18 @@ pub trait TTMacroExpander { } pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) + for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box; impl TTMacroExpander for F - where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) + where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box { fn expand<'cx>( &self, ecx: &'cx mut ExtCtxt<'_>, span: Span, - input: TokenStream, + mut input: TokenStream, ) -> Box { struct AvoidInterpolatedIdents; @@ -256,10 +352,8 @@ impl TTMacroExpander for F mut_visit::noop_visit_mac(mac, self) } } - - let input: Vec<_> = - input.trees().map(|mut tt| { AvoidInterpolatedIdents.visit_tt(&mut tt); tt }).collect(); - (*self)(ecx, span, &input) + AvoidInterpolatedIdents.visit_tts(&mut input); + (*self)(ecx, span, input) } } @@ -315,6 +409,34 @@ pub trait MacResult { fn make_ty(self: Box) -> Option> { None } + + fn make_arms(self: Box) -> Option> { + None + } + + fn make_fields(self: Box) -> Option> { + None + } + + fn make_field_patterns(self: Box) -> Option> { + None + } + + fn make_generic_params(self: Box) -> Option> { + None + } + + fn make_params(self: Box) -> Option> { + None + } + + fn make_struct_fields(self: Box) -> Option> { + None + } + + fn make_variants(self: Box) -> Option> { + None + } } macro_rules! make_MacEager { @@ -405,7 +527,6 @@ impl MacResult for MacEager { /// after hitting errors. #[derive(Copy, Clone)] pub struct DummyResult { - expr_only: bool, is_error: bool, span: Span, } @@ -416,21 +537,12 @@ impl DummyResult { /// Use this as a return value after hitting any errors and /// calling `span_err`. pub fn any(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: true, span }) + Box::new(DummyResult { is_error: true, span }) } /// Same as `any`, but must be a valid fragment, not error. pub fn any_valid(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: false, span }) - } - - /// Creates a default MacResult that can only be an expression. - /// - /// Use this for macros that must expand to an expression, so even - /// if an error is encountered internally, the user will receive - /// an error that they also used it in the wrong place. - pub fn expr(span: Span) -> Box { - Box::new(DummyResult { expr_only: true, is_error: true, span }) + Box::new(DummyResult { is_error: false, span }) } /// A plain dummy expression. @@ -472,36 +584,19 @@ impl MacResult for DummyResult { } fn make_items(self: Box) -> Option; 1]>> { - // this code needs a comment... why not always just return the Some() ? - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_impl_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_trait_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_foreign_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_stmts(self: Box) -> Option> { @@ -515,6 +610,34 @@ impl MacResult for DummyResult { fn make_ty(self: Box) -> Option> { Some(DummyResult::raw_ty(self.span, self.is_error)) } + + fn make_arms(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_fields(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_field_patterns(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_generic_params(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_params(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_struct_fields(self: Box) -> Option> { + Some(SmallVec::new()) + } + + fn make_variants(self: Box) -> Option> { + Some(SmallVec::new()) + } } /// A syntax extension kind. @@ -576,8 +699,6 @@ pub struct SyntaxExtension { pub kind: SyntaxExtensionKind, /// Span of the macro definition. pub span: Span, - /// Hygienic properties of spans produced by this macro by default. - pub default_transparency: Transparency, /// Whitelist of unstable features that are treated as stable inside this macro. pub allow_internal_unstable: Option>, /// Suppresses the `unsafe_code` lint for code produced by this macro. @@ -599,22 +720,6 @@ pub struct SyntaxExtension { pub is_derive_copy: bool, } -impl SyntaxExtensionKind { - /// When a syntax extension is constructed, - /// its transparency can often be inferred from its kind. - fn default_transparency(&self) -> Transparency { - match self { - SyntaxExtensionKind::Bang(..) | - SyntaxExtensionKind::Attr(..) | - SyntaxExtensionKind::Derive(..) | - SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque, - SyntaxExtensionKind::LegacyBang(..) | - SyntaxExtensionKind::LegacyAttr(..) | - SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent, - } - } -} - impl SyntaxExtension { /// Returns which kind of macro calls this syntax extension. pub fn macro_kind(&self) -> MacroKind { @@ -633,7 +738,6 @@ impl SyntaxExtension { pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { SyntaxExtension { span: DUMMY_SP, - default_transparency: kind.default_transparency(), allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, @@ -647,8 +751,47 @@ impl SyntaxExtension { } } + /// Constructs a syntax extension with the given properties + /// and other properties converted from attributes. + pub fn new( + sess: &ParseSess, + kind: SyntaxExtensionKind, + span: Span, + helper_attrs: Vec, + edition: Edition, + name: Name, + attrs: &[ast::Attribute], + ) -> SyntaxExtension { + let allow_internal_unstable = attr::allow_internal_unstable( + &attrs, &sess.span_diagnostic, + ).map(|features| features.collect::>().into()); + + let mut local_inner_macros = false; + if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) { + if let Some(l) = macro_export.meta_item_list() { + local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); + } + } + + let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro); + + SyntaxExtension { + kind, + span, + allow_internal_unstable, + allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe), + local_inner_macros, + stability: attr::find_stability(&sess, attrs, span), + deprecation: attr::find_deprecation(&sess, attrs, span), + helper_attrs, + edition, + is_builtin, + is_derive_copy: is_builtin && name == sym::Copy, + } + } + pub fn dummy_bang(edition: Edition) -> SyntaxExtension { - fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree]) + fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream) -> Box { DummyResult::any(span) } @@ -667,12 +810,12 @@ impl SyntaxExtension { SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition) } - pub fn expn_info(&self, call_site: Span, descr: Symbol) -> ExpnInfo { - ExpnInfo { - call_site, + pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnData { + ExpnData { kind: ExpnKind::Macro(self.macro_kind(), descr), + parent, + call_site, def_site: self.span, - default_transparency: self.default_transparency, allow_internal_unstable: self.allow_internal_unstable.clone(), allow_internal_unsafe: self.allow_internal_unsafe, local_inner_macros: self.local_inner_macros, @@ -683,6 +826,12 @@ impl SyntaxExtension { pub type NamedSyntaxExtension = (Name, SyntaxExtension); +/// Result of resolving a macro invocation. +pub enum InvocationRes { + Single(Lrc), + DeriveContainer(Vec>), +} + /// Error type that denotes indeterminacy. pub struct Indeterminate; @@ -697,19 +846,26 @@ bitflags::bitflags! { } pub trait Resolver { - fn next_node_id(&mut self) -> ast::NodeId; - - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId; + fn next_node_id(&mut self) -> NodeId; fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - derives: &[ExpnId]); + extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); + fn expansion_for_ast_pass( + &mut self, + call_site: Span, + pass: AstPass, + features: &[Symbol], + parent_module_id: Option, + ) -> ExpnId; + fn resolve_imports(&mut self); - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool) - -> Result>, Indeterminate>; + fn resolve_macro_invocation( + &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool + ) -> Result; fn check_unused_macros(&self); @@ -734,7 +890,7 @@ pub struct ExpansionData { /// One of these is made during expansion and incrementally updated as we go; /// when a macro expansion occurs, the resulting nodes have the `backtrace() -/// -> expn_info` of their expansion context stored into their span. +/// -> expn_data` of their expansion context stored into their span. pub struct ExtCtxt<'a> { pub parse_sess: &'a parse::ParseSess, pub ecfg: expand::ExpansionConfig<'a>, @@ -775,41 +931,42 @@ impl<'a> ExtCtxt<'a> { pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { expand::MacroExpander::new(self, true) } - - pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect(), MACRO_ARGUMENTS) + pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> { + parse::stream_to_parser(self.parse_sess, stream, MACRO_ARGUMENTS) } pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config } pub fn call_site(&self) -> Span { - match self.current_expansion.id.expn_info() { - Some(expn_info) => expn_info.call_site, - None => DUMMY_SP, - } + self.current_expansion.id.expn_data().call_site + } + + /// Equivalent of `Span::def_site` from the proc macro API, + /// except that the location is taken from the span passed as an argument. + pub fn with_def_site_ctxt(&self, span: Span) -> Span { + span.with_def_site_ctxt(self.current_expansion.id) } - pub fn backtrace(&self) -> SyntaxContext { - SyntaxContext::empty().apply_mark(self.current_expansion.id) + + /// Equivalent of `Span::call_site` from the proc macro API, + /// except that the location is taken from the span passed as an argument. + pub fn with_call_site_ctxt(&self, span: Span) -> Span { + span.with_call_site_ctxt(self.current_expansion.id) } /// Returns span for the macro which originally caused the current expansion to happen. /// /// Stops backtracing at include! boundary. pub fn expansion_cause(&self) -> Option { - let mut ctxt = self.backtrace(); + let mut expn_id = self.current_expansion.id; let mut last_macro = None; loop { - if ctxt.outer_expn_info().map_or(None, |info| { - if info.kind.descr() == sym::include { - // Stop going up the backtrace once include! is encountered - return None; - } - ctxt = info.call_site.ctxt(); - last_macro = Some(info.call_site); - Some(()) - }).is_none() { - break + let expn_data = expn_id.expn_data(); + // Stop going up the backtrace once include! is encountered + if expn_data.is_root() || expn_data.kind.descr() == sym::include { + break; } + expn_id = expn_data.call_site.ctxt().outer_expn(); + last_macro = Some(expn_data.call_site); } last_macro } @@ -867,9 +1024,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } - pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_unimpl(sp, msg); - } pub fn span_bug>(&self, sp: S, msg: &str) -> ! { self.parse_sess.span_diagnostic.span_bug(sp, msg); } @@ -893,13 +1047,13 @@ impl<'a> ExtCtxt<'a> { pub fn set_trace_macros(&mut self, x: bool) { self.ecfg.trace_mac = x } - pub fn ident_of(&self, st: &str) -> ast::Ident { - ast::Ident::from_str(st) + pub fn ident_of(&self, st: &str, sp: Span) -> ast::Ident { + ast::Ident::from_str_and_span(st, sp) } pub fn std_path(&self, components: &[Symbol]) -> Vec { - let def_site = DUMMY_SP.apply_mark(self.current_expansion.id); + let def_site = self.with_def_site_ctxt(DUMMY_SP); iter::once(Ident::new(kw::DollarCrate, def_site)) - .chain(components.iter().map(|&s| Ident::with_empty_ctxt(s))) + .chain(components.iter().map(|&s| Ident::with_dummy_span(s))) .collect() } pub fn name_of(&self, st: &str) -> ast::Name { @@ -910,7 +1064,7 @@ impl<'a> ExtCtxt<'a> { self.resolver.check_unused_macros(); } - /// Resolve a path mentioned inside Rust code. + /// Resolves a path mentioned inside Rust code. /// /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths. /// @@ -941,14 +1095,16 @@ impl<'a> ExtCtxt<'a> { /// compilation on error, merely emits a non-fatal error and returns `None`. pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, - mut expr: P, + expr: P, err_msg: &str, -) -> Result, Option>> { - // we want to be able to handle e.g., `concat!("foo", "bar")` - cx.expander().visit_expr(&mut expr); +) -> Result<(Symbol, ast::StrStyle, Span), Option>> { + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), + ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)), ast::LitKind::Err(_) => None, _ => Some(cx.struct_span_err(l.span, err_msg)) }, @@ -962,7 +1118,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt<'_>, expr: P, err_msg: &str) expr_to_spanned_string(cx, expr, err_msg) .map_err(|err| err.map(|mut err| err.emit())) .ok() - .map(|s| s.node) + .map(|(symbol, style, _)| (symbol, style)) } /// Non-fatally assert that `tts` is empty. Note that this function @@ -972,7 +1128,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt<'_>, expr: P, err_msg: &str) /// done as rarely as possible). pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, name: &str) { if !tts.is_empty() { cx.span_err(sp, &format!("{} takes no arguments", name)); @@ -983,7 +1139,7 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, /// expect exactly one string literal, or emit an error and return `None`. pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, name: &str) -> Option { let mut p = cx.new_parser_from_tts(tts); @@ -1006,12 +1162,16 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>, /// parsing error, emit a non-fatal error and return `None`. pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) -> Option>> { + tts: TokenStream) -> Option>> { let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let mut expr = panictry!(p.parse_expr()); - cx.expander().visit_expr(&mut expr); + let expr = panictry!(p.parse_expr()); + + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + es.push(expr); if p.eat(&token::Comma) { continue; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 22962499a2..f903b66e29 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1,33 +1,28 @@ -use crate::ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; +use crate::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind}; use crate::attr; -use crate::source_map::{dummy_spanned, respan, Spanned}; +use crate::source_map::{respan, Spanned}; use crate::ext::base::ExtCtxt; use crate::ptr::P; use crate::symbol::{kw, sym, Symbol}; use crate::ThinVec; -use rustc_target::spec::abi::Abi; use syntax_pos::{Pos, Span}; -// Left so that Cargo tests don't break, this can be removed once those no longer use it -pub trait AstBuilder {} - impl<'a> ExtCtxt<'a> { pub fn path(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, false, strs, vec![], vec![]) + self.path_all(span, false, strs, vec![]) } pub fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec![id]) } pub fn path_global(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, true, strs, vec![], vec![]) + self.path_all(span, true, strs, vec![]) } pub fn path_all(&self, span: Span, global: bool, mut idents: Vec , - args: Vec, - constraints: Vec ) + args: Vec) -> ast::Path { assert!(!idents.is_empty()); let add_root = global && !idents[0].is_path_segment_keyword(); @@ -39,8 +34,8 @@ impl<'a> ExtCtxt<'a> { segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); - let args = if !args.is_empty() || !constraints.is_empty() { - ast::AngleBracketedArgs { args, constraints, span }.into() + let args = if !args.is_empty() { + ast::AngleBracketedArgs { args, constraints: Vec::new(), span }.into() } else { None }; @@ -52,42 +47,6 @@ impl<'a> ExtCtxt<'a> { ast::Path { span, segments } } - /// Constructs a qualified path. - /// - /// Constructs a path like `::ident`. - pub fn qpath(&self, - self_type: P, - trait_path: ast::Path, - ident: ast::Ident) - -> (ast::QSelf, ast::Path) { - self.qpath_all(self_type, trait_path, ident, vec![], vec![]) - } - - /// Constructs a qualified path. - /// - /// Constructs a path like `::ident<'a, T, A = Bar>`. - pub fn qpath_all(&self, - self_type: P, - trait_path: ast::Path, - ident: ast::Ident, - args: Vec, - constraints: Vec) - -> (ast::QSelf, ast::Path) { - let mut path = trait_path; - let args = if !args.is_empty() || !constraints.is_empty() { - ast::AngleBracketedArgs { args, constraints, span: ident.span }.into() - } else { - None - }; - path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args }); - - (ast::QSelf { - ty: self_type, - path_span: path.span, - position: path.segments.len() - 1 - }, path) - } - pub fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { ast::MutTy { ty, @@ -149,10 +108,6 @@ impl<'a> ExtCtxt<'a> { ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) } - pub fn ty_infer(&self, span: Span) -> P { - self.ty(span, ast::TyKind::Infer) - } - pub fn typaram(&self, span: Span, ident: ast::Ident, @@ -166,7 +121,8 @@ impl<'a> ExtCtxt<'a> { bounds, kind: ast::GenericParamKind::Type { default, - } + }, + is_placeholder: false } } @@ -207,6 +163,7 @@ impl<'a> ExtCtxt<'a> { attrs: attrs.into(), bounds, kind: ast::GenericParamKind::Lifetime, + is_placeholder: false } } @@ -218,14 +175,6 @@ impl<'a> ExtCtxt<'a> { } } - pub fn stmt_semi(&self, expr: P) -> ast::Stmt { - ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: expr.span, - node: ast::StmtKind::Semi(expr), - } - } - pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P) -> ast::Stmt { let pat = if mutbl { @@ -249,34 +198,6 @@ impl<'a> ExtCtxt<'a> { } } - pub fn stmt_let_typed(&self, - sp: Span, - mutbl: bool, - ident: ast::Ident, - typ: P, - ex: P) - -> ast::Stmt { - let pat = if mutbl { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); - self.pat_ident_binding_mode(sp, ident, binding_mode) - } else { - self.pat_ident(sp, ident) - }; - let local = P(ast::Local { - pat, - ty: Some(typ), - init: Some(ex), - id: ast::DUMMY_NODE_ID, - span: sp, - attrs: ThinVec::new(), - }); - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Local(local), - span: sp, - } - } - // Generates `let _: Type;`, which is usually used for type assertions. pub fn stmt_let_type_only(&self, span: Span, ty: P) -> ast::Stmt { let local = P(ast::Local { @@ -331,16 +252,11 @@ impl<'a> ExtCtxt<'a> { self.expr(path.span, ast::ExprKind::Path(None, path)) } - /// Constructs a `QPath` expression. - pub fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P { - self.expr(span, ast::ExprKind::Path(Some(qself), path)) - } - pub fn expr_ident(&self, span: Span, id: ast::Ident) -> P { self.expr_path(self.path_ident(span, id)) } pub fn expr_self(&self, span: Span) -> P { - self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower)) + self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower)) } pub fn expr_binary(&self, sp: Span, op: ast::BinOpKind, @@ -349,27 +265,12 @@ impl<'a> ExtCtxt<'a> { } pub fn expr_deref(&self, sp: Span, e: P) -> P { - self.expr_unary(sp, UnOp::Deref, e) - } - pub fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P) -> P { - self.expr(sp, ast::ExprKind::Unary(op, e)) + self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e)) } - pub fn expr_field_access( - &self, sp: Span, expr: P, ident: ast::Ident, - ) -> P { - self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp))) - } - pub fn expr_tup_field_access(&self, sp: Span, expr: P, idx: usize) -> P { - let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp); - self.expr(sp, ast::ExprKind::Field(expr, ident)) - } pub fn expr_addr_of(&self, sp: Span, e: P) -> P { self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e)) } - pub fn expr_mut_addr_of(&self, sp: Span, e: P) -> P { - self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Mutable, e)) - } pub fn expr_call( &self, span: Span, expr: P, args: Vec>, @@ -403,6 +304,8 @@ impl<'a> ExtCtxt<'a> { span, is_shorthand: false, attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, } } pub fn expr_struct( @@ -423,28 +326,10 @@ impl<'a> ExtCtxt<'a> { self.expr_lit(span, ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize))) } - pub fn expr_isize(&self, sp: Span, i: isize) -> P { - if i < 0 { - let i = (-i) as u128; - let lit_ty = ast::LitIntType::Signed(ast::IntTy::Isize); - let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty)); - self.expr_unary(sp, ast::UnOp::Neg, lit) - } else { - self.expr_lit(sp, ast::LitKind::Int(i as u128, - ast::LitIntType::Signed(ast::IntTy::Isize))) - } - } pub fn expr_u32(&self, sp: Span, u: u32) -> P { self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32))) } - pub fn expr_u16(&self, sp: Span, u: u16) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, - ast::LitIntType::Unsigned(ast::UintTy::U16))) - } - pub fn expr_u8(&self, sp: Span, u: u8) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8))) - } pub fn expr_bool(&self, sp: Span, value: bool) -> P { self.expr_lit(sp, ast::LitKind::Bool(value)) } @@ -452,10 +337,6 @@ impl<'a> ExtCtxt<'a> { pub fn expr_vec(&self, sp: Span, exprs: Vec>) -> P { self.expr(sp, ast::ExprKind::Array(exprs)) } - pub fn expr_vec_ng(&self, sp: Span) -> P { - self.expr_call_global(sp, self.std_path(&[sym::vec, sym::Vec, sym::new]), - Vec::new()) - } pub fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P { self.expr_addr_of(sp, self.expr_vec(sp, exprs)) } @@ -472,16 +353,6 @@ impl<'a> ExtCtxt<'a> { self.expr_call_global(sp, some, vec![expr]) } - pub fn expr_none(&self, sp: Span) -> P { - let none = self.std_path(&[sym::option, sym::Option, sym::None]); - let none = self.path_global(sp, none); - self.expr_path(none) - } - - pub fn expr_break(&self, sp: Span) -> P { - self.expr(sp, ast::ExprKind::Break(None, None)) - } - pub fn expr_tuple(&self, sp: Span, exprs: Vec>) -> P { self.expr(sp, ast::ExprKind::Tup(exprs)) } @@ -510,18 +381,13 @@ impl<'a> ExtCtxt<'a> { self.expr_call_global(sp, ok, vec![expr]) } - pub fn expr_err(&self, sp: Span, expr: P) -> P { - let err = self.std_path(&[sym::result, sym::Result, sym::Err]); - self.expr_call_global(sp, err, vec![expr]) - } - pub fn expr_try(&self, sp: Span, head: P) -> P { let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); let ok_path = self.path_global(sp, ok); let err = self.std_path(&[sym::result, sym::Result, sym::Err]); let err_path = self.path_global(sp, err); - let binding_variable = self.ident_of("__try_var"); + let binding_variable = self.ident_of("__try_var", sp); let binding_pat = self.pat_ident(sp, binding_variable); let binding_expr = self.expr_ident(sp, binding_variable); @@ -536,9 +402,9 @@ impl<'a> ExtCtxt<'a> { let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); // `Ok(__try_var) => __try_var` - let ok_arm = self.arm(sp, vec![ok_pat], binding_expr); + let ok_arm = self.arm(sp, ok_pat, binding_expr); // `Err(__try_var) => return Err(__try_var)` - let err_arm = self.arm(sp, vec![err_pat], err_expr); + let err_arm = self.arm(sp, err_pat, err_expr); // `match head { Ok() => ..., Err() => ... }` self.expr_match(sp, head, vec![ok_arm, err_arm]) @@ -574,7 +440,7 @@ impl<'a> ExtCtxt<'a> { self.pat(span, PatKind::TupleStruct(path, subpats)) } pub fn pat_struct(&self, span: Span, path: ast::Path, - field_pats: Vec>) -> P { + field_pats: Vec) -> P { self.pat(span, PatKind::Struct(path, field_pats, false)) } pub fn pat_tuple(&self, span: Span, pats: Vec>) -> P { @@ -605,18 +471,20 @@ impl<'a> ExtCtxt<'a> { self.pat_tuple_struct(span, path, vec![pat]) } - pub fn arm(&self, span: Span, pats: Vec>, expr: P) -> ast::Arm { + pub fn arm(&self, span: Span, pat: P, expr: P) -> ast::Arm { ast::Arm { attrs: vec![], - pats, + pat, guard: None, body: expr, span, + id: ast::DUMMY_NODE_ID, + is_placeholder: false, } } pub fn arm_unreachable(&self, span: Span) -> ast::Arm { - self.arm(span, vec![self.pat_wild(span)], self.expr_unreachable(span)) + self.arm(span, self.pat_wild(span), self.expr_unreachable(span)) } pub fn expr_match(&self, span: Span, arg: P, arms: Vec) -> P { @@ -629,10 +497,6 @@ impl<'a> ExtCtxt<'a> { self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els)) } - pub fn expr_loop(&self, span: Span, block: P) -> P { - self.expr(span, ast::ExprKind::Loop(block, None)) - } - pub fn lambda_fn_decl(&self, span: Span, fn_decl: P, @@ -653,7 +517,7 @@ impl<'a> ExtCtxt<'a> { body: P) -> P { let fn_decl = self.fn_decl( - ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), + ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(), ast::FunctionRetTy::Default(span)); // FIXME -- We are using `span` as the span of the `|...|` @@ -676,34 +540,25 @@ impl<'a> ExtCtxt<'a> { self.lambda(span, vec![ident], body) } - pub fn lambda_stmts(&self, - span: Span, - ids: Vec, - stmts: Vec) - -> P { - self.lambda(span, ids, self.expr_block(self.block(span, stmts))) - } - pub fn lambda_stmts_0(&self, span: Span, stmts: Vec) -> P { - self.lambda0(span, self.expr_block(self.block(span, stmts))) - } pub fn lambda_stmts_1(&self, span: Span, stmts: Vec, ident: ast::Ident) -> P { self.lambda1(span, self.expr_block(self.block(span, stmts)), ident) } - pub fn arg(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Arg { + pub fn param(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Param { let arg_pat = self.pat_ident(span, ident); - ast::Arg { + ast::Param { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat: arg_pat, span, ty, + is_placeholder: false, } } // FIXME: unused `self` - pub fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { + pub fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { P(ast::FnDecl { inputs, output, @@ -726,43 +581,6 @@ impl<'a> ExtCtxt<'a> { }) } - pub fn item_fn_poly(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - generics: Generics, - body: P) -> P { - self.item(span, - name, - Vec::new(), - ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)), - ast::FnHeader { - unsafety: ast::Unsafety::Normal, - asyncness: dummy_spanned(ast::IsAsync::NotAsync), - constness: dummy_spanned(ast::Constness::NotConst), - abi: Abi::Rust, - }, - generics, - body)) - } - - pub fn item_fn(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - body: P - ) -> P { - self.item_fn_poly( - span, - name, - inputs, - output, - Generics::default(), - body) - } - pub fn variant(&self, span: Span, ident: Ident, tys: Vec> ) -> ast::Variant { let fields: Vec<_> = tys.into_iter().map(|ty| { ast::StructField { @@ -772,6 +590,7 @@ impl<'a> ExtCtxt<'a> { vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), attrs: Vec::new(), id: ast::DUMMY_NODE_ID, + is_placeholder: false, } }).collect(); @@ -781,60 +600,15 @@ impl<'a> ExtCtxt<'a> { ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID) }; - respan(span, - ast::Variant_ { - ident, - id: ast::DUMMY_NODE_ID, - attrs: Vec::new(), - data: vdata, - disr_expr: None, - }) - } - - pub fn item_enum_poly(&self, span: Span, name: Ident, - enum_definition: ast::EnumDef, - generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Enum(enum_definition, generics)) - } - - pub fn item_enum(&self, span: Span, name: Ident, - enum_definition: ast::EnumDef) -> P { - self.item_enum_poly(span, name, enum_definition, - Generics::default()) - } - - pub fn item_struct(&self, span: Span, name: Ident, - struct_def: ast::VariantData) -> P { - self.item_struct_poly( - span, - name, - struct_def, - Generics::default() - ) - } - - pub fn item_struct_poly(&self, span: Span, name: Ident, - struct_def: ast::VariantData, generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Struct(struct_def, generics)) - } - - pub fn item_mod(&self, span: Span, inner_span: Span, name: Ident, - attrs: Vec, - items: Vec>) -> P { - self.item( + ast::Variant { + attrs: Vec::new(), + data: vdata, + disr_expr: None, + id: ast::DUMMY_NODE_ID, + ident, span, - name, - attrs, - ast::ItemKind::Mod(ast::Mod { - inner: inner_span, - items, - inline: true - }) - ) - } - - pub fn item_extern_crate(&self, span: Span, name: Ident) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::ExternCrate(None)) + is_placeholder: false, + } } pub fn item_static(&self, @@ -856,15 +630,6 @@ impl<'a> ExtCtxt<'a> { self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr)) } - pub fn item_ty_poly(&self, span: Span, name: Ident, ty: P, - generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::TyAlias(ty, generics)) - } - - pub fn item_ty(&self, span: Span, name: Ident, ty: P) -> P { - self.item_ty_poly(span, name, ty, Generics::default()) - } - pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { attr::mk_attr_outer(mi) } @@ -872,70 +637,4 @@ impl<'a> ExtCtxt<'a> { pub fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem { attr::mk_word_item(Ident::new(w, sp)) } - - pub fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem { - attr::mk_nested_word_item(Ident::new(w, sp)) - } - - pub fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec) - -> ast::MetaItem { - attr::mk_list_item(Ident::new(name, sp), mis) - } - - pub fn meta_name_value(&self, span: Span, name: ast::Name, lit_kind: ast::LitKind) - -> ast::MetaItem { - attr::mk_name_value_item(Ident::new(name, span), lit_kind, span) - } - - pub fn item_use(&self, sp: Span, - vis: ast::Visibility, vp: P) -> P { - P(ast::Item { - id: ast::DUMMY_NODE_ID, - ident: Ident::invalid(), - attrs: vec![], - node: ast::ItemKind::Use(vp), - vis, - span: sp, - tokens: None, - }) - } - - pub fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P { - self.item_use_simple_(sp, vis, None, path) - } - - pub fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, - rename: Option, path: ast::Path) -> P { - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: path, - kind: ast::UseTreeKind::Simple(rename, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID), - })) - } - - pub fn item_use_list(&self, sp: Span, vis: ast::Visibility, - path: Vec, imports: &[ast::Ident]) -> P { - let imports = imports.iter().map(|id| { - (ast::UseTree { - span: sp, - prefix: self.path(sp, vec![*id]), - kind: ast::UseTreeKind::Simple(None, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID), - }, ast::DUMMY_NODE_ID) - }).collect(); - - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: self.path(sp, path), - kind: ast::UseTreeKind::Nested(imports), - })) - } - - pub fn item_use_glob(&self, sp: Span, - vis: ast::Visibility, path: Vec) -> P { - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: self.path(sp, path), - kind: ast::UseTreeKind::Glob, - })) - } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cf1ae3e316..b80c530731 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1,11 +1,11 @@ use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; use crate::attr::{self, HasAttrs}; -use crate::source_map::{dummy_spanned, respan}; +use crate::source_map::respan; use crate::config::StripUnconfigured; use crate::ext::base::*; -use crate::ext::proc_macro::collect_derives; -use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; +use crate::ext::proc_macro::{collect_derives, MarkAttrs}; +use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; @@ -25,9 +25,8 @@ use syntax_pos::{Span, DUMMY_SP, FileName}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use std::fs; use std::io::ErrorKind; -use std::{iter, mem}; +use std::{iter, mem, slice}; use std::ops::DerefMut; use std::rc::Rc; use std::path::PathBuf; @@ -116,18 +115,6 @@ macro_rules! ast_fragments { } } - impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> { - fn filter_map_expr(&mut self, expr: P) -> Option> { - self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() - } - $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) { - visit_clobber(ast, |ast| self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()); - })?)* - $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy { - self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() - })?)* - } - impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { $(fn $make_ast(self: Box>) -> Option<$AstTy> { @@ -154,7 +141,40 @@ ast_fragments! { "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items; } ForeignItems(SmallVec<[ast::ForeignItem; 1]>) { - "foreign item"; many fn flat_map_foreign_item; fn visit_foreign_item; fn make_foreign_items; + "foreign item"; + many fn flat_map_foreign_item; + fn visit_foreign_item; + fn make_foreign_items; + } + Arms(SmallVec<[ast::Arm; 1]>) { + "match arm"; many fn flat_map_arm; fn visit_arm; fn make_arms; + } + Fields(SmallVec<[ast::Field; 1]>) { + "field expression"; many fn flat_map_field; fn visit_field; fn make_fields; + } + FieldPats(SmallVec<[ast::FieldPat; 1]>) { + "field pattern"; + many fn flat_map_field_pattern; + fn visit_field_pattern; + fn make_field_patterns; + } + GenericParams(SmallVec<[ast::GenericParam; 1]>) { + "generic parameter"; + many fn flat_map_generic_param; + fn visit_generic_param; + fn make_generic_params; + } + Params(SmallVec<[ast::Param; 1]>) { + "function parameter"; many fn flat_map_param; fn visit_param; fn make_params; + } + StructFields(SmallVec<[ast::StructField; 1]>) { + "field"; + many fn flat_map_struct_field; + fn visit_struct_field; + fn make_struct_fields; + } + Variants(SmallVec<[ast::Variant; 1]>) { + "variant"; many fn flat_map_variant; fn visit_variant; fn make_variants; } } @@ -167,6 +187,21 @@ impl AstFragmentKind { -> AstFragment { let mut items = items.into_iter(); match self { + AstFragmentKind::Arms => + AstFragment::Arms(items.map(Annotatable::expect_arm).collect()), + AstFragmentKind::Fields => + AstFragment::Fields(items.map(Annotatable::expect_field).collect()), + AstFragmentKind::FieldPats => + AstFragment::FieldPats(items.map(Annotatable::expect_field_pattern).collect()), + AstFragmentKind::GenericParams => + AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect()), + AstFragmentKind::Params => + AstFragment::Params(items.map(Annotatable::expect_param).collect()), + AstFragmentKind::StructFields => AstFragment::StructFields( + items.map(Annotatable::expect_struct_field).collect() + ), + AstFragmentKind::Variants => + AstFragment::Variants(items.map(Annotatable::expect_variant).collect()), AstFragmentKind::Items => AstFragment::Items(items.map(Annotatable::expect_item).collect()), AstFragmentKind::ImplItems => @@ -190,7 +225,7 @@ impl AstFragmentKind { pub struct Invocation { pub kind: InvocationKind, - fragment_kind: AstFragmentKind, + pub fragment_kind: AstFragmentKind, pub expansion_data: ExpansionData, } @@ -265,7 +300,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { tokens: None, })]); - match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) { + match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => { krate.attrs = attrs; krate.module = module; @@ -285,8 +320,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { krate } - // Fully expand all macro invocations in this AST fragment. - fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { + // Recursively expand all macro invocations in this AST fragment. + pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let orig_expansion_data = self.cx.current_expansion.clone(); self.cx.current_expansion.depth = 0; @@ -304,7 +339,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut derives: FxHashMap> = FxHashMap::default(); + let mut all_derive_placeholders: FxHashMap> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -318,10 +353,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue }; - let scope = + let eager_expansion_root = if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id }; - let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) { - Ok(ext) => ext, + let res = match self.cx.resolver.resolve_macro_invocation( + &invoc, eager_expansion_root, force + ) { + Ok(res) => res, Err(Indeterminate) => { undetermined_invocations.push(invoc); continue @@ -333,53 +370,72 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.current_expansion = invoc.expansion_data.clone(); // FIXME(jseyfried): Refactor out the following logic - let (expanded_fragment, new_invocations) = if let Some(ext) = ext { - let fragment = self.expand_invoc(invoc, &ext.kind); - self.collect_invocations(fragment, &[]) - } else if let InvocationKind::DeriveContainer { derives: traits, item } = invoc.kind { - if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), sym::derive) - .expect("`derive` attribute should exist"); - let span = attr.span; - let mut err = self.cx.mut_span_err(span, - "`derive` may only be applied to \ - structs, enums and unions"); - if let ast::AttrStyle::Inner = attr.style { - let trait_list = traits.iter() - .map(|t| t.to_string()).collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, "try an outer attribute", suggestion, - // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT - Applicability::MaybeIncorrect - ); - } - err.emit(); + let (expanded_fragment, new_invocations) = match res { + InvocationRes::Single(ext) => { + let fragment = self.expand_invoc(invoc, &ext.kind); + self.collect_invocations(fragment, &[]) } + InvocationRes::DeriveContainer(exts) => { + let (derives, item) = match invoc.kind { + InvocationKind::DeriveContainer { derives, item } => (derives, item), + _ => unreachable!(), + }; + if !item.derive_allowed() { + let attr = attr::find_by_name(item.attrs(), sym::derive) + .expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self.cx.mut_span_err(span, + "`derive` may only be applied to structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = derives.iter() + .map(|t| t.to_string()).collect::>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion( + span, "try an outer attribute", suggestion, + // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT + Applicability::MaybeIncorrect + ); + } + err.emit(); + } - let mut item = self.fully_configure(item); - item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let derives = derives.entry(invoc.expansion_data.id).or_default(); - - derives.reserve(traits.len()); - invocations.reserve(traits.len()); - for path in traits { - let expn_id = ExpnId::fresh(self.cx.current_expansion.id, None); - derives.push(expn_id); - invocations.push(Invocation { - kind: InvocationKind::Derive { path, item: item.clone() }, - fragment_kind: invoc.fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - ..invoc.expansion_data.clone() - }, - }); + let mut item = self.fully_configure(item); + item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); + let mut helper_attrs = Vec::new(); + let mut has_copy = false; + for ext in exts { + helper_attrs.extend(&ext.helper_attrs); + has_copy |= ext.is_derive_copy; + } + // Mark derive helpers inside this item as known and used. + // FIXME: This is a hack, derive helpers should be integrated with regular name + // resolution instead. For example, helpers introduced by a derive container + // can be in scope for all code produced by that container's expansion. + item.visit_with(&mut MarkAttrs(&helper_attrs)); + if has_copy { + self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); + } + + let derive_placeholders = + all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); + derive_placeholders.reserve(derives.len()); + invocations.reserve(derives.len()); + for path in derives { + let expn_id = ExpnId::fresh(None); + derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); + invocations.push(Invocation { + kind: InvocationKind::Derive { path, item: item.clone() }, + fragment_kind: invoc.fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + ..invoc.expansion_data.clone() + }, + }); + } + let fragment = invoc.fragment_kind + .expect_from_annotatables(::std::iter::once(item)); + self.collect_invocations(fragment, derive_placeholders) } - let fragment = invoc.fragment_kind - .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derives) - } else { - unreachable!() }; if expanded_fragments.len() < depth { @@ -396,10 +452,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Finally incorporate all the expanded macros into the input AST fragment. let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { - for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_expn_id(mark), - expanded_fragment, derives); + for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { + let derive_placeholders = + all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); + placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), + expanded_fragment, derive_placeholders); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -416,7 +473,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s. /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and /// prepares data for resolving paths of macro invocations. - fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[ExpnId]) + fn collect_invocations(&mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId]) -> (AstFragment, Vec) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -435,9 +492,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { collector.invocations }; + // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, derives); + self.cx.current_expansion.id, &fragment, extra_placeholders); } (fragment, invocations) @@ -472,6 +530,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Expr(mut expr) => { Annotatable::Expr({ cfg.visit_expr(&mut expr); expr }) } + Annotatable::Arm(arm) => { + Annotatable::Arm(cfg.flat_map_arm(arm).pop().unwrap()) + } + Annotatable::Field(field) => { + Annotatable::Field(cfg.flat_map_field(field).pop().unwrap()) + } + Annotatable::FieldPat(fp) => { + Annotatable::FieldPat(cfg.flat_map_field_pattern(fp).pop().unwrap()) + } + Annotatable::GenericParam(param) => { + Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap()) + } + Annotatable::Param(param) => { + Annotatable::Param(cfg.flat_map_param(param).pop().unwrap()) + } + Annotatable::StructField(sf) => { + Annotatable::StructField(cfg.flat_map_struct_field(sf).pop().unwrap()) + } + Annotatable::Variant(v) => { + Annotatable::Variant(cfg.flat_map_variant(v).pop().unwrap()) + } } } @@ -486,11 +565,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - let info = self.cx.current_expansion.id.expn_info().unwrap(); + let expn_data = self.cx.current_expansion.id.expn_data(); let suggested_limit = self.cx.ecfg.recursion_limit * 2; - let mut err = self.cx.struct_span_err(info.call_site, + let mut err = self.cx.struct_span_err(expn_data.call_site, &format!("recursion limit reached while expanding the macro `{}`", - info.kind.descr())); + expn_data.kind.descr())); err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); @@ -503,22 +582,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); - let tok_result = expander.expand(self.cx, span, mac.node.stream()); + let tok_result = expander.expand(self.cx, span, mac.stream()); let result = - self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span); + self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span); self.gate_proc_macro_expansion(span, &result); result } SyntaxExtensionKind::LegacyBang(expander) => { let prev = self.cx.current_expansion.prior_type_ascription; - self.cx.current_expansion.prior_type_ascription = - mac.node.prior_type_ascription; - let tok_result = expander.expand(self.cx, span, mac.node.stream()); + self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription; + let tok_result = expander.expand(self.cx, span, mac.stream()); let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { let msg = format!("non-{kind} macro in {kind} position: {path}", - kind = fragment_kind.name(), path = mac.node.path); + kind = fragment_kind.name(), path = mac.path); self.cx.span_err(span, &msg); self.cx.trace_macros_diag(); fragment_kind.dummy(span) @@ -538,6 +616,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()), Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), Annotatable::Expr(expr) => token::NtExpr(expr), + Annotatable::Arm(..) + | Annotatable::Field(..) + | Annotatable::FieldPat(..) + | Annotatable::GenericParam(..) + | Annotatable::Param(..) + | Annotatable::StructField(..) + | Annotatable::Variant(..) + => panic!("unexpected annotatable"), })), DUMMY_SP).into(); let input = self.extract_proc_macro_attr_input(attr.tokens, span); let tok_result = expander.expand(self.cx, span, input, item_tok); @@ -574,7 +660,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return fragment_kind.dummy(span); } let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path }; - let span = span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item); fragment_kind.expect_from_annotatables(items) } @@ -617,6 +702,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return, Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene), Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene), + Annotatable::Arm(..) + | Annotatable::Field(..) + | Annotatable::FieldPat(..) + | Annotatable::GenericParam(..) + | Annotatable::Param(..) + | Annotatable::StructField(..) + | Annotatable::Variant(..) + => panic!("unexpected annotatable"), }; emit_feature_err( self.cx.parse_sess, @@ -673,6 +766,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { AstFragmentKind::TraitItems => return, AstFragmentKind::ImplItems => return, AstFragmentKind::ForeignItems => return, + AstFragmentKind::Arms + | AstFragmentKind::Fields + | AstFragmentKind::FieldPats + | AstFragmentKind::GenericParams + | AstFragmentKind::Params + | AstFragmentKind::StructFields + | AstFragmentKind::Variants + => panic!("unexpected AST fragment kind"), }; if self.cx.ecfg.proc_macro_hygiene() { return @@ -693,7 +794,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { path: &Path, span: Span, ) -> AstFragment { - let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); + let mut parser = self.cx.new_parser_from_tts(toks); match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { parser.ensure_complete_parse(path, kind.name(), span); @@ -763,6 +864,14 @@ impl<'a> Parser<'a> { }, AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?), AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?), + AstFragmentKind::Arms + | AstFragmentKind::Fields + | AstFragmentKind::FieldPats + | AstFragmentKind::GenericParams + | AstFragmentKind::Params + | AstFragmentKind::StructFields + | AstFragmentKind::Variants + => panic!("unexpected AST fragment kind"), }) } @@ -771,7 +880,7 @@ impl<'a> Parser<'a> { let msg = format!("macro expansion ignores token `{}` and any following", self.this_token_to_string()); // Avoid emitting backtrace info twice. - let def_site_span = self.token.span.with_ctxt(SyntaxContext::empty()); + let def_site_span = self.token.span.with_ctxt(SyntaxContext::root()); let mut err = self.diagnostic().struct_span_err(def_site_span, &msg); err.span_label(span, "caused by the macro expansion here"); let msg = format!( @@ -808,17 +917,20 @@ struct InvocationCollector<'a, 'b> { impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - // Expansion info for all the collected invocations is set upon their resolution, + // Expansion data for all the collected invocations is set upon their resolution, // with exception of the derive container case which is not resolved and can get - // its expansion info immediately. - let expn_info = match &kind { - InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default( - ExpnKind::Macro(MacroKind::Attr, sym::derive), - item.span(), self.cx.parse_sess.edition, - )), + // its expansion data immediately. + let expn_data = match &kind { + InvocationKind::DeriveContainer { item, .. } => Some(ExpnData { + parent: self.cx.current_expansion.id, + ..ExpnData::default( + ExpnKind::Macro(MacroKind::Attr, sym::derive), + item.span(), self.cx.parse_sess.edition, + ) + }), _ => None, }; - let expn_id = ExpnId::fresh(self.cx.current_expansion.id, expn_info); + let expn_id = ExpnId::fresh(expn_data); self.invocations.push(Invocation { kind, fragment_kind, @@ -907,7 +1019,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn check_attributes(&mut self, attrs: &[ast::Attribute]) { let features = self.cx.ecfg.features.unwrap(); for attr in attrs.iter() { - self.check_attribute_inner(attr, features); + feature_gate::check_attribute(attr, self.cx.parse_sess, features); // macros are expanded before any lint passes so this warning has to be hardcoded if attr.path == sym::derive { @@ -917,15 +1029,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } } } - - fn check_attribute(&mut self, at: &ast::Attribute) { - let features = self.cx.ecfg.features.unwrap(); - self.check_attribute_inner(at, features); - } - - fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) { - feature_gate::check_attribute(at, self.cx.parse_sess, features); - } } impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { @@ -961,6 +1064,84 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }); } + fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { + let mut arm = configure!(self, arm); + + let (attr, traits, after_derive) = self.classify_item(&mut arm); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::Arm(arm), + AstFragmentKind::Arms, after_derive) + .make_arms(); + } + + noop_flat_map_arm(arm, self) + } + + fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> { + let mut field = configure!(self, field); + + let (attr, traits, after_derive) = self.classify_item(&mut field); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::Field(field), + AstFragmentKind::Fields, after_derive) + .make_fields(); + } + + noop_flat_map_field(field, self) + } + + fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> { + let mut fp = configure!(self, fp); + + let (attr, traits, after_derive) = self.classify_item(&mut fp); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::FieldPat(fp), + AstFragmentKind::FieldPats, after_derive) + .make_field_patterns(); + } + + noop_flat_map_field_pattern(fp, self) + } + + fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { + let mut p = configure!(self, p); + + let (attr, traits, after_derive) = self.classify_item(&mut p); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::Param(p), + AstFragmentKind::Params, after_derive) + .make_params(); + } + + noop_flat_map_param(p, self) + } + + fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> { + let mut sf = configure!(self, sf); + + let (attr, traits, after_derive) = self.classify_item(&mut sf); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::StructField(sf), + AstFragmentKind::StructFields, after_derive) + .make_struct_fields(); + } + + noop_flat_map_struct_field(sf, self) + } + + fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { + let mut variant = configure!(self, variant); + + let (attr, traits, after_derive) = self.classify_item(&mut variant); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::Variant(variant), + AstFragmentKind::Variants, after_derive) + .make_variants(); + } + + noop_flat_map_variant(variant, self) + } + fn filter_map_expr(&mut self, expr: P) -> Option> { let expr = configure!(self, expr); expr.filter_map(|mut expr| { @@ -1216,9 +1397,21 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - fn visit_generic_params(&mut self, params: &mut Vec) { - self.cfg.configure_generic_params(params); - noop_visit_generic_params(params, self); + fn flat_map_generic_param( + &mut self, + param: ast::GenericParam + ) -> SmallVec<[ast::GenericParam; 1]> + { + let mut param = configure!(self, param); + + let (attr, traits, after_derive) = self.classify_item(&mut param); + if attr.is_some() || !traits.is_empty() { + return self.collect_attr(attr, traits, Annotatable::GenericParam(param), + AstFragmentKind::GenericParams, after_derive) + .make_generic_params(); + } + + noop_flat_map_generic_param(param, self) } fn visit_attribute(&mut self, at: &mut ast::Attribute) { @@ -1243,37 +1436,37 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { if let Some(file) = it.value_str() { let err_count = self.cx.parse_sess.span_diagnostic.err_count(); - self.check_attribute(&at); + self.check_attributes(slice::from_ref(at)); if self.cx.parse_sess.span_diagnostic.err_count() > err_count { // avoid loading the file if they haven't enabled the feature return noop_visit_attribute(at, self); } let filename = self.cx.resolve_path(&*file.as_str(), it.span()); - match fs::read_to_string(&filename) { - Ok(src) => { - let src_interned = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - self.cx.source_map().new_source_file(filename.into(), src); + match self.cx.source_map().load_file(&filename) { + Ok(source_file) => { + let src = source_file.src.as_ref() + .expect("freshly loaded file should have a source"); + let src_interned = Symbol::intern(src.as_str()); let include_info = vec![ ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::file), - dummy_spanned(file), + Ident::with_dummy_span(sym::file), + file, + DUMMY_SP, ), ), ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::contents), - dummy_spanned(src_interned), + Ident::with_dummy_span(sym::contents), + src_interned, + DUMMY_SP, ), ), ]; - let include_ident = Ident::with_empty_ctxt(sym::include); + let include_ident = Ident::with_dummy_span(sym::include); let item = attr::mk_list_item(include_ident, include_info); items.push(ast::NestedMetaItem::MetaItem(item)); } @@ -1335,7 +1528,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - let meta = attr::mk_list_item(Ident::with_empty_ctxt(sym::doc), items); + let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items); *at = attr::Attribute { span: at.span, id: at.id, @@ -1395,17 +1588,3 @@ impl<'feat> ExpansionConfig<'feat> { self.features.map_or(false, |features| features.custom_inner_attributes) } } - -// A Marker adds the given mark to the syntax context. -#[derive(Debug)] -pub struct Marker(pub ExpnId); - -impl MutVisitor for Marker { - fn visit_span(&mut self, span: &mut Span) { - *span = span.apply_mark(self.0) - } - - fn visit_mac(&mut self, mac: &mut ast::Mac) { - noop_visit_mac(mac, self) - } -} diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index b2b17b0fb2..52a0f95bce 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -2,7 +2,6 @@ use crate::ast::{self, NodeId}; use crate::source_map::{DUMMY_SP, dummy_spanned}; use crate::ext::base::ExtCtxt; use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::hygiene::ExpnId; use crate::tokenstream::TokenStream; use crate::mut_visit::*; use crate::ptr::P; @@ -14,12 +13,13 @@ use rustc_data_structures::fx::FxHashMap; pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { fn mac_placeholder() -> ast::Mac { - dummy_spanned(ast::Mac_ { + ast::Mac { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, tts: TokenStream::empty().into(), delim: ast::MacDelimiter::Brace, + span: DUMMY_SP, prior_type_ascription: None, - }) + } } let ident = ast::Ident::invalid(); @@ -32,6 +32,16 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { attrs: ThinVec::new(), node: ast::ExprKind::Mac(mac_placeholder()), }); + let ty = P(ast::Ty { + id, + node: ast::TyKind::Mac(mac_placeholder()), + span, + }); + let pat = P(ast::Pat { + id, + node: ast::PatKind::Mac(mac_placeholder()), + span, + }); match kind { AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), @@ -67,6 +77,81 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new())); ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) } }]), + AstFragmentKind::Arms => AstFragment::Arms(smallvec![ + ast::Arm { + attrs: Default::default(), + body: expr_placeholder(), + guard: None, + id, + pat, + span, + is_placeholder: true, + } + ]), + AstFragmentKind::Fields => AstFragment::Fields(smallvec![ + ast::Field { + attrs: Default::default(), + expr: expr_placeholder(), + id, + ident, + is_shorthand: false, + span, + is_placeholder: true, + } + ]), + AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ + ast::FieldPat { + attrs: Default::default(), + id, + ident, + is_shorthand: false, + pat, + span, + is_placeholder: true, + } + ]), + AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{ + ast::GenericParam { + attrs: Default::default(), + bounds: Default::default(), + id, + ident, + is_placeholder: true, + kind: ast::GenericParamKind::Lifetime, + } + }]), + AstFragmentKind::Params => AstFragment::Params(smallvec![ + ast::Param { + attrs: Default::default(), + id, + pat, + span, + ty, + is_placeholder: true, + } + ]), + AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ + ast::StructField { + attrs: Default::default(), + id, + ident: None, + span, + ty, + vis, + is_placeholder: true, + } + ]), + AstFragmentKind::Variants => AstFragment::Variants(smallvec![ + ast::Variant { + attrs: Default::default(), + data: ast::VariantData::Struct(Default::default(), false), + disr_expr: None, + id, + ident, + span, + is_placeholder: true, + } + ]) } } @@ -85,11 +170,11 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec) { fragment.mut_visit_with(self); if let AstFragment::Items(mut items) = fragment { - for derive in derives { - match self.remove(NodeId::placeholder_from_expn_id(derive)) { + for placeholder in placeholders { + match self.remove(placeholder) { AstFragment::Items(derived_items) => items.extend(derived_items), _ => unreachable!(), } @@ -105,6 +190,66 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { + fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { + if arm.is_placeholder { + self.remove(arm.id).make_arms() + } else { + noop_flat_map_arm(arm, self) + } + } + + fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> { + if field.is_placeholder { + self.remove(field.id).make_fields() + } else { + noop_flat_map_field(field, self) + } + } + + fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> { + if fp.is_placeholder { + self.remove(fp.id).make_field_patterns() + } else { + noop_flat_map_field_pattern(fp, self) + } + } + + fn flat_map_generic_param( + &mut self, + param: ast::GenericParam + ) -> SmallVec<[ast::GenericParam; 1]> + { + if param.is_placeholder { + self.remove(param.id).make_generic_params() + } else { + noop_flat_map_generic_param(param, self) + } + } + + fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { + if p.is_placeholder { + self.remove(p.id).make_params() + } else { + noop_flat_map_param(p, self) + } + } + + fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> { + if sf.is_placeholder { + self.remove(sf.id).make_struct_fields() + } else { + noop_flat_map_struct_field(sf, self) + } + } + + fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { + if variant.is_placeholder { + self.remove(variant.id).make_variants() + } else { + noop_flat_map_variant(variant, self) + } + } + fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { match item.node { ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(), diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs index c17b6f6b42..47b17ced81 100644 --- a/src/libsyntax/ext/proc_macro.rs +++ b/src/libsyntax/ext/proc_macro.rs @@ -78,7 +78,6 @@ pub struct ProcMacroDerive { pub client: proc_macro::bridge::client::Client< fn(proc_macro::TokenStream) -> proc_macro::TokenStream, >, - pub attrs: Vec, } impl MultiItemModifier for ProcMacroDerive { @@ -89,6 +88,14 @@ impl MultiItemModifier for ProcMacroDerive { item: Annotatable) -> Vec { let item = match item { + Annotatable::Arm(..) | + Annotatable::Field(..) | + Annotatable::FieldPat(..) | + Annotatable::GenericParam(..) | + Annotatable::Param(..) | + Annotatable::StructField(..) | + Annotatable::Variant(..) + => panic!("unexpected annotatable"), Annotatable::Item(item) => item, Annotatable::ImplItem(_) | Annotatable::TraitItem(_) | @@ -111,9 +118,6 @@ impl MultiItemModifier for ProcMacroDerive { } } - // Mark attributes as known, and used. - MarkAttrs(&self.attrs).visit_item(&item); - let token = token::Interpolated(Lrc::new(token::NtItem(item))); let input = tokenstream::TokenTree::token(token, DUMMY_SP).into(); @@ -164,7 +168,7 @@ impl MultiItemModifier for ProcMacroDerive { } } -struct MarkAttrs<'a>(&'a [ast::Name]); +crate struct MarkAttrs<'a>(crate &'a [ast::Name]); impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 36621ce777..dfec9ee288 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -4,10 +4,9 @@ use crate::parse::{self, token, ParseSess}; use crate::parse::lexer::comments; use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; -use errors::{Diagnostic, DiagnosticBuilder}; +use errors::Diagnostic; use rustc_data_structures::sync::Lrc; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; -use syntax_pos::hygiene::{SyntaxContext, Transparency}; use syntax_pos::symbol::{kw, sym, Symbol}; use proc_macro::{Delimiter, Level, LineColumn, Spacing}; @@ -323,8 +322,7 @@ impl Ident { fn is_valid(string: &str) -> bool { let mut chars = string.chars(); if let Some(start) = chars.next() { - (start == '_' || start.is_xid_start()) - && chars.all(|cont| cont == '_' || cont.is_xid_continue()) + rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue) } else { false } @@ -361,18 +359,11 @@ pub(crate) struct Rustc<'a> { impl<'a> Rustc<'a> { pub fn new(cx: &'a ExtCtxt<'_>) -> Self { - // No way to determine def location for a proc macro right now, so use call location. - let location = cx.current_expansion.id.expn_info().unwrap().call_site; - let to_span = |transparency| { - location.with_ctxt( - SyntaxContext::empty() - .apply_mark_with_transparency(cx.current_expansion.id, transparency), - ) - }; + let expn_data = cx.current_expansion.id.expn_data(); Rustc { sess: cx.parse_sess, - def_site: to_span(Transparency::Opaque), - call_site: to_span(Transparency::Transparent), + def_site: cx.with_def_site_ctxt(expn_data.def_site), + call_site: cx.with_call_site_ctxt(expn_data.call_site), } } @@ -659,7 +650,7 @@ impl server::Diagnostic for Rustc<'_> { diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None); } fn emit(&mut self, diag: Self::Diagnostic) { - DiagnosticBuilder::new_diagnostic(&self.sess.span_diagnostic, diag).emit() + self.sess.span_diagnostic.emit_diagnostic(&diag); } } @@ -677,7 +668,7 @@ impl server::Span for Rustc<'_> { self.sess.source_map().lookup_char_pos(span.lo()).file } fn parent(&mut self, span: Self::Span) -> Option { - span.ctxt().outer_expn_info().map(|i| i.call_site) + span.parent() } fn source(&mut self, span: Self::Span) -> Self::Span { span.source_callsite() diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b057a9ad44..b27e9c5433 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1,3 +1,5 @@ +use crate::ast; +use crate::attr::{self, TransparencyError}; use crate::edition::Edition; use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; @@ -15,10 +17,10 @@ use crate::parse::token::{self, NtTT, Token}; use crate::parse::{Directory, ParseSess}; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; -use crate::{ast, attr, attr::TransparencyError}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; +use syntax_pos::hygiene::Transparency; use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; @@ -128,6 +130,7 @@ impl<'a> ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: ast::Ident, span: Span, + transparency: Transparency, lhses: Vec, rhses: Vec, valid: bool, @@ -143,7 +146,9 @@ impl TTMacroExpander for MacroRulesMacroExpander { if !self.valid { return DummyResult::any(sp); } - generic_extension(cx, sp, self.span, self.name, input, &self.lhses, &self.rhses) + generic_extension( + cx, sp, self.span, self.name, self.transparency, input, &self.lhses, &self.rhses + ) } } @@ -158,6 +163,7 @@ fn generic_extension<'cx>( sp: Span, def_span: Span, name: ast::Ident, + transparency: Transparency, arg: TokenStream, lhses: &[quoted::TokenTree], rhses: &[quoted::TokenTree], @@ -187,7 +193,7 @@ fn generic_extension<'cx>( let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs); + let mut tts = transcribe(cx, &named_matches, rhs, transparency); // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. @@ -285,6 +291,7 @@ pub fn compile( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); let tt_spec = ast::Ident::new(sym::tt, def.span); @@ -415,75 +422,28 @@ pub fn compile( // that is not lint-checked and trigger the "failed to process buffered lint here" bug. valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses); - let expander: Box<_> = - Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid }); - - let (default_transparency, transparency_error) = - attr::find_transparency(&def.attrs, body.legacy); + let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => - sess.span_diagnostic.span_err( - span, &format!("unknown macro transparency: `{}`", value) - ), + diag.span_err(span, &format!("unknown macro transparency: `{}`", value)), Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => - sess.span_diagnostic.span_err( - vec![old_span, new_span], "multiple macro transparency attributes" - ), + diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"), None => {} } - let allow_internal_unstable = - attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| { - attr.meta_item_list() - .map(|list| { - list.iter() - .filter_map(|it| { - let name = it.ident().map(|ident| ident.name); - if name.is_none() { - sess.span_diagnostic.span_err( - it.span(), - "allow internal unstable expects feature names", - ) - } - name - }) - .collect::>() - .into() - }) - .unwrap_or_else(|| { - sess.span_diagnostic.span_warn( - attr.span, - "allow_internal_unstable expects list of feature names. In the \ - future this will become a hard error. Please use `allow_internal_unstable(\ - foo, bar)` to only allow the `foo` and `bar` features", - ); - vec![sym::allow_internal_unstable_backcompat_hack].into() - }) - }); - - let mut local_inner_macros = false; - if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) { - if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); - } - } + let expander: Box<_> = Box::new(MacroRulesMacroExpander { + name: def.ident, span: def.span, transparency, lhses, rhses, valid + }); - let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro); - - SyntaxExtension { - kind: SyntaxExtensionKind::LegacyBang(expander), - span: def.span, - default_transparency, - allow_internal_unstable, - allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), - local_inner_macros, - stability: attr::find_stability(&sess, &def.attrs, def.span), - deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), - helper_attrs: Vec::new(), + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), edition, - is_builtin, - is_derive_copy: is_builtin && def.ident.name == sym::Copy, - } + def.ident.name, + &def.attrs, + ) } fn check_lhs_nt_follows( @@ -917,9 +877,9 @@ fn check_matcher_core( // Now `last` holds the complete set of NT tokens that could // end the sequence before SUFFIX. Check that every one works with `suffix`. 'each_last: for token in &last.tokens { - if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token { + if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token { for next_token in &suffix_first.tokens { - match is_in_follow(next_token, &frag_spec.as_str()) { + match is_in_follow(next_token, frag_spec.name) { IsInFollow::Invalid(msg, help) => { sess.span_diagnostic .struct_span_err(next_token.span(), &msg) @@ -988,7 +948,7 @@ fn check_matcher_core( fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool { if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { - frag_can_be_followed_by_any(&frag_spec.as_str()) + frag_can_be_followed_by_any(frag_spec.name) } else { // (Non NT's can always be followed by anthing in matchers.) true @@ -1003,15 +963,15 @@ fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool { /// specifier which consumes at most one token tree can be followed by /// a fragment specifier (indeed, these fragments can be followed by /// ANYTHING without fear of future compatibility hazards). -fn frag_can_be_followed_by_any(frag: &str) -> bool { +fn frag_can_be_followed_by_any(frag: Symbol) -> bool { match frag { - "item" | // always terminated by `}` or `;` - "block" | // exactly one token tree - "ident" | // exactly one token tree - "literal" | // exactly one token tree - "meta" | // exactly one token tree - "lifetime" | // exactly one token tree - "tt" => // exactly one token tree + sym::item | // always terminated by `}` or `;` + sym::block | // exactly one token tree + sym::ident | // exactly one token tree + sym::literal | // exactly one token tree + sym::meta | // exactly one token tree + sym::lifetime | // exactly one token tree + sym::tt => // exactly one token tree true, _ => @@ -1033,7 +993,7 @@ enum IsInFollow { /// break macros that were relying on that binary operator as a /// separator. // when changing this do not forget to update doc/book/macros.md! -fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { +fn is_in_follow(tok: "ed::TokenTree, frag: Symbol) -> IsInFollow { use quoted::TokenTree; if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok { @@ -1042,17 +1002,17 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { IsInFollow::Yes } else { match frag { - "item" => { + sym::item => { // since items *must* be followed by either a `;` or a `}`, we can // accept anything after them IsInFollow::Yes } - "block" => { + sym::block => { // anything can follow block, the braces provide an easy boundary to // maintain IsInFollow::Yes } - "stmt" | "expr" => { + sym::stmt | sym::expr => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1062,7 +1022,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - "pat" => { + sym::pat => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1073,7 +1033,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - "path" | "ty" => { + sym::path | sym::ty => { const TOKENS: &[&str] = &[ "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`", "`where`", @@ -1101,20 +1061,20 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - "ident" | "lifetime" => { + sym::ident | sym::lifetime => { // being a single token, idents and lifetimes are harmless IsInFollow::Yes } - "literal" => { + sym::literal => { // literals may be of a single token, or two tokens (negative numbers) IsInFollow::Yes } - "meta" | "tt" => { + sym::meta | sym::tt => { // being either a single token or a delimited sequence, tt is // harmless IsInFollow::Yes } - "vis" => { + sym::vis => { // Explicitly disallow `priv`, on the off chance it comes back. const TOKENS: &[&str] = &["`,`", "an ident", "a type"]; match tok { @@ -1139,7 +1099,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - "" => IsInFollow::Yes, // kw::Invalid + kw::Invalid => IsInFollow::Yes, _ => IsInFollow::Invalid( format!("invalid fragment specifier `{}`", frag), VALID_FRAGMENT_NAMES_MSG, diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 214e721fd1..f9c07e3a2e 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -1,18 +1,41 @@ -use crate::ast::Ident; +use crate::ast::{Ident, Mac}; use crate::ext::base::ExtCtxt; -use crate::ext::expand::Marker; use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use crate::ext::tt::quoted; -use crate::mut_visit::noop_visit_tt; +use crate::mut_visit::{self, MutVisitor}; use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; +use errors::pluralise; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use syntax_pos::hygiene::{ExpnId, Transparency}; +use syntax_pos::Span; + use std::mem; +// A Marker adds the given mark to the syntax context. +struct Marker(ExpnId, Transparency); + +impl MutVisitor for Marker { + fn visit_span(&mut self, span: &mut Span) { + *span = span.apply_mark(self.0, self.1) + } + + fn visit_mac(&mut self, mac: &mut Mac) { + mut_visit::noop_visit_mac(mac, self) + } +} + +impl Marker { + fn visit_delim_span(&mut self, dspan: &mut DelimSpan) { + self.visit_span(&mut dspan.open); + self.visit_span(&mut dspan.close); + } +} + /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { Delimited { forest: Lrc, idx: usize, span: DelimSpan }, @@ -68,6 +91,7 @@ pub(super) fn transcribe( cx: &ExtCtxt<'_>, interp: &FxHashMap, src: Vec, + transparency: Transparency, ) -> TokenStream { // Nothing for us to transcribe... if src.is_empty() { @@ -96,6 +120,7 @@ pub(super) fn transcribe( // again, and we are done transcribing. let mut result: Vec = Vec::new(); let mut result_stack = Vec::new(); + let mut marker = Marker(cx.current_expansion.id, transparency); loop { // Look at the last frame on the stack. @@ -207,7 +232,7 @@ pub(super) fn transcribe( } // Replace the meta-var with the matched token tree from the invocation. - quoted::TokenTree::MetaVar(mut sp, ident) => { + quoted::TokenTree::MetaVar(mut sp, mut ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { @@ -218,7 +243,7 @@ pub(super) fn transcribe( if let NtTT(ref tt) = **nt { result.push(tt.clone().into()); } else { - sp = sp.apply_mark(cx.current_expansion.id); + marker.visit_span(&mut sp); let token = TokenTree::token(token::Interpolated(nt.clone()), sp); result.push(token.into()); } @@ -232,9 +257,8 @@ pub(super) fn transcribe( } else { // If we aren't able to match the meta-var, we push it back into the result but // with modified syntax context. (I believe this supports nested macros). - let ident = - Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.id)); - sp = sp.apply_mark(cx.current_expansion.id); + marker.visit_span(&mut sp); + marker.visit_ident(&mut ident); result.push(TokenTree::token(token::Dollar, sp).into()); result.push(TokenTree::Token(Token::from_ast_ident(ident)).into()); } @@ -246,7 +270,7 @@ pub(super) fn transcribe( // jump back out of the Delimited, pop the result_stack and add the new results back to // the previous results (from outside the Delimited). quoted::TokenTree::Delimited(mut span, delimited) => { - span = span.apply_mark(cx.current_expansion.id); + marker.visit_delim_span(&mut span); stack.push(Frame::Delimited { forest: delimited, idx: 0, span }); result_stack.push(mem::take(&mut result)); } @@ -254,9 +278,8 @@ pub(super) fn transcribe( // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. quoted::TokenTree::Token(token) => { - let mut marker = Marker(cx.current_expansion.id); let mut tt = TokenTree::Token(token); - noop_visit_tt(&mut tt, &mut marker); + marker.visit_tt(&mut tt); result.push(tt.into()); } @@ -323,8 +346,13 @@ impl LockstepIterSize { LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { let msg = format!( - "meta-variable `{}` repeats {} times, but `{}` repeats {} times", - l_id, l_len, r_id, r_len + "meta-variable `{}` repeats {} time{}, but `{}` repeats {} time{}", + l_id, + l_len, + pluralise!(l_len), + r_id, + r_len, + pluralise!(r_len), ); LockstepIterSize::Contradiction(msg) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs deleted file mode 100644 index 08a113b53d..0000000000 --- a/src/libsyntax/feature_gate.rs +++ /dev/null @@ -1,2525 +0,0 @@ -//! # Feature gating -//! -//! This module implements the gating necessary for preventing certain compiler -//! features from being used by default. This module will crawl a pre-expanded -//! AST to ensure that there are no features which are used that are not -//! enabled. -//! -//! Features are enabled in programs via the crate-level attributes of -//! `#![feature(...)]` with a comma-separated list of features. -//! -//! For the purpose of future feature-tracking, once code for detection of feature -//! gate usage is added, *do not remove it again* even once the feature -//! becomes stable. - -use AttributeType::*; -use AttributeGate::*; - -use crate::ast::{ - self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, - PatKind, RangeEnd, -}; -use crate::attr::{self, check_builtin_attribute, AttributeTemplate}; -use crate::source_map::Spanned; -use crate::edition::{ALL_EDITIONS, Edition}; -use crate::visit::{self, FnKind, Visitor}; -use crate::parse::{token, ParseSess}; -use crate::parse::parser::Parser; -use crate::symbol::{Symbol, sym}; -use crate::tokenstream::TokenTree; - -use errors::{Applicability, DiagnosticBuilder, Handler}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lock; -use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -use log::debug; -use lazy_static::lazy_static; - -use std::env; - -macro_rules! set { - ($field: ident) => {{ - fn f(features: &mut Features, _: Span) { - features.$field = true; - } - f as fn(&mut Features, Span) - }} -} - -macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { - /// Represents active features that are currently being implemented or - /// currently being considered for addition/removal. - const ACTIVE_FEATURES: - &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = - &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; - - /// A set of features to be used by later passes. - #[derive(Clone)] - pub struct Features { - /// `#![feature]` attrs for language features, for error reporting - pub declared_lang_features: Vec<(Symbol, Span, Option)>, - /// `#![feature]` attrs for non-language (library) features - pub declared_lib_features: Vec<(Symbol, Span)>, - $(pub $feature: bool),+ - } - - impl Features { - pub fn new() -> Features { - Features { - declared_lang_features: Vec::new(), - declared_lib_features: Vec::new(), - $($feature: false),+ - } - } - - pub fn walk_feature_fields(&self, mut f: F) - where F: FnMut(&str, bool) - { - $(f(stringify!($feature), self.$feature);)+ - } - } - }; - - ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { - /// Represents unstable features which have since been removed (it was once Active) - const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, $reason)),+ - ]; - }; - - ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Represents stable features which have since been removed (it was once Accepted) - const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - }; - - ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Those language feature has since been Accepted (it was once Active) - const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - } -} - -// If you change this, please modify `src/doc/unstable-book` as well. -// -// Don't ever remove anything from this list; set them to 'Removed'. -// -// The version numbers here correspond to the version in which the current status -// was set. This is most important for knowing when a particular feature became -// stable (active). -// -// Note that the features are grouped into internal/user-facing and then -// sorted by version inside those groups. This is inforced with tidy. -// -// N.B., `tools/tidy/src/features.rs` parses this information directly out of the -// source, so take care when modifying it. - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: internal feature gates - // ------------------------------------------------------------------------- - - // no-tracking-issue-start - - // Allows using compiler's own crates. - (active, rustc_private, "1.0.0", Some(27812), None), - - // Allows using the `rust-intrinsic`'s "ABI". - (active, intrinsics, "1.0.0", None, None), - - // Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. - (active, lang_items, "1.0.0", None, None), - - // Allows using the `#[stable]` and `#[unstable]` attributes. - (active, staged_api, "1.0.0", None, None), - - // Allows using `#[allow_internal_unstable]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unstable, "1.0.0", None, None), - - // Allows using `#[allow_internal_unsafe]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unsafe, "1.0.0", None, None), - - // Allows using the macros: - // + `__diagnostic_used` - // + `__register_diagnostic` - // +`__build_diagnostic_array` - (active, rustc_diagnostic_macros, "1.0.0", None, None), - - // Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which - // lets a function to be `const` when opted into with `#![feature(foo)]`. - (active, rustc_const_unstable, "1.0.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - - // Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", Some(29642), None), - - // Allows using `#[on_unimplemented(..)]` on traits. - (active, on_unimplemented, "1.0.0", Some(29628), None), - - // Allows using the `box $expr` syntax. - (active, box_syntax, "1.0.0", Some(49733), None), - - // Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - - // Allows using `#[start]` on a function indicating that it is the program entrypoint. - (active, start, "1.0.0", Some(29633), None), - - // Allows using the `#[fundamental]` attribute. - (active, fundamental, "1.0.0", Some(29635), None), - - // Allows using the `rust-call` ABI. - (active, unboxed_closures, "1.0.0", Some(29625), None), - - // Allows using the `#[linkage = ".."]` attribute. - (active, linkage, "1.0.0", Some(29603), None), - - // Allows features specific to OIBIT (auto traits). - (active, optin_builtin_traits, "1.0.0", Some(13231), None), - - // Allows using `box` in patterns (RFC 469). - (active, box_patterns, "1.0.0", Some(29641), None), - - // no-tracking-issue-start - - // Allows using `#[prelude_import]` on glob `use` items. - (active, prelude_import, "1.2.0", None, None), - - // no-tracking-issue-end - - // no-tracking-issue-start - - // Allows using `#[omit_gdb_pretty_printer_section]`. - (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - - // Allows using the `vectorcall` ABI. - (active, abi_vectorcall, "1.7.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[structural_match]` which indicates that a type is structurally matchable. - (active, structural_match, "1.8.0", Some(31434), None), - - // Allows using the `may_dangle` attribute (RFC 1327). - (active, dropck_eyepatch, "1.10.0", Some(34761), None), - - // Allows using the `#![panic_runtime]` attribute. - (active, panic_runtime, "1.10.0", Some(32837), None), - - // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. - (active, needs_panic_runtime, "1.10.0", Some(32837), None), - - // no-tracking-issue-start - - // Allows identifying the `compiler_builtins` crate. - (active, compiler_builtins, "1.13.0", None, None), - - // Allows using the `unadjusted` ABI; perma-unstable. - (active, abi_unadjusted, "1.16.0", None, None), - - // Allows identifying crates that contain sanitizer runtimes. - (active, sanitizer_runtime, "1.17.0", None, None), - - // Used to identify crates that contain the profiler runtime. - (active, profiler_runtime, "1.18.0", None, None), - - // Allows using the `thiscall` ABI. - (active, abi_thiscall, "1.19.0", None, None), - - // Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. - (active, allocator_internals, "1.20.0", None, None), - - // no-tracking-issue-end - - // Added for testing E0705; perma-unstable. - (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), - - // ------------------------------------------------------------------------- - // feature-group-end: internal feature gates - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // FIXME: Document these and merge with the list below. - - // Unstable `#[target_feature]` directives. - (active, arm_target_feature, "1.27.0", Some(44839), None), - (active, aarch64_target_feature, "1.27.0", Some(44839), None), - (active, hexagon_target_feature, "1.27.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), - (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, avx512_target_feature, "1.27.0", Some(44839), None), - (active, mmx_target_feature, "1.27.0", Some(44839), None), - (active, sse4a_target_feature, "1.27.0", Some(44839), None), - (active, tbm_target_feature, "1.27.0", Some(44839), None), - (active, wasm_target_feature, "1.30.0", Some(44839), None), - (active, adx_target_feature, "1.32.0", Some(44839), None), - (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, rtm_target_feature, "1.35.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates - // ------------------------------------------------------------------------- - - // Allows using the `#[link_args]` attribute. - (active, link_args, "1.0.0", Some(29596), None), - - // Allows defining identifiers beyond ASCII. - (active, non_ascii_idents, "1.0.0", Some(55467), None), - - // Allows using `#[plugin_registrar]` on functions. - (active, plugin_registrar, "1.0.0", Some(29597), None), - - // Allows using `#![plugin(myplugin)]`. - (active, plugin, "1.0.0", Some(29597), None), - - // Allows using `#[thread_local]` on `static` items. - (active, thread_local, "1.0.0", Some(29594), None), - - // Allows the use of SIMD types in functions declared in `extern` blocks. - (active, simd_ffi, "1.0.0", Some(27731), None), - - // Allows using custom attributes (RFC 572). - (active, custom_attribute, "1.0.0", Some(29642), None), - - // Allows using non lexical lifetimes (RFC 2094). - (active, nll, "1.0.0", Some(43234), None), - - // Allows using slice patterns. - (active, slice_patterns, "1.0.0", Some(62254), None), - - // Allows the definition of `const` functions with some advanced features. - (active, const_fn, "1.2.0", Some(57563), None), - - // Allows associated type defaults. - (active, associated_type_defaults, "1.2.0", Some(29661), None), - - // Allows `#![no_core]`. - (active, no_core, "1.3.0", Some(29639), None), - - // Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - - // Allows `repr(simd)` and importing the various simd intrinsics. - (active, repr_simd, "1.4.0", Some(27731), None), - - // Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), - - // Allows `#[unwind(..)]`. - // - // Permits specifying whether a function should permit unwinding or abort on unwind. - (active, unwind_attributes, "1.4.0", Some(58760), None), - - // Allows `#[no_debug]`. - (active, no_debug, "1.5.0", Some(29721), None), - - // Allows attributes on expressions and non-item statements. - (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - - // Allows the use of type ascription in expressions. - (active, type_ascription, "1.6.0", Some(23416), None), - - // Allows `cfg(target_thread_local)`. - (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - - // Allows specialization of implementations (RFC 1210). - (active, specialization, "1.7.0", Some(31844), None), - - // Allows using `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408), None), - - // Allows `cfg(target_has_atomic = "...")`. - (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - - // Allows `X..Y` patterns. - (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - - // Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. - (active, never_type, "1.13.0", Some(35121), None), - - // Allows exhaustive pattern matching on types that contain uninhabited types. - (active, exhaustive_patterns, "1.13.0", Some(51085), None), - - // Allows untagged unions `union U { ... }`. - (active, untagged_unions, "1.13.0", Some(32836), None), - - // Allows `#[link(..., cfg(..))]`. - (active, link_cfg, "1.14.0", Some(37406), None), - - // Allows `extern "ptx-*" fn()`. - (active, abi_ptx, "1.15.0", Some(38788), None), - - // Allows the `#[repr(i128)]` attribute for enums. - (active, repr128, "1.16.0", Some(35118), None), - - // Allows `#[link(kind="static-nobundle"...)]`. - (active, static_nobundle, "1.16.0", Some(37403), None), - - // Allows `extern "msp430-interrupt" fn()`. - (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - - // Allows declarative macros 2.0 (`macro`). - (active, decl_macro, "1.17.0", Some(39412), None), - - // Allows `extern "x86-interrupt" fn()`. - (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - - // Allows overlapping impls of marker traits. - (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - - // Allows a test to fail without failing the whole suite. - (active, allow_fail, "1.19.0", Some(46488), None), - - // Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - - // Allows defining generators. - (active, generators, "1.21.0", Some(43122), None), - - // Allows `#[doc(cfg(...))]`. - (active, doc_cfg, "1.21.0", Some(43781), None), - - // Allows `#[doc(masked)]`. - (active, doc_masked, "1.21.0", Some(44027), None), - - // Allows `#[doc(spotlight)]`. - (active, doc_spotlight, "1.22.0", Some(45040), None), - - // Allows `#[doc(include = "some-file")]`. - (active, external_doc, "1.22.0", Some(44732), None), - - // Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). - (active, non_exhaustive, "1.22.0", Some(44109), None), - - // Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - - // Allows defining `extern type`s. - (active, extern_types, "1.23.0", Some(43467), None), - - // Allows trait methods with arbitrary self types. - (active, arbitrary_self_types, "1.23.0", Some(44874), None), - - // Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (active, in_band_lifetimes, "1.23.0", Some(44524), None), - - // Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). - (active, generic_associated_types, "1.23.0", Some(44265), None), - - // Allows defining `trait X = A + B;` alias items. - (active, trait_alias, "1.24.0", Some(41517), None), - - // Allows infering `'static` outlives requirements (RFC 2093). - (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - - // Allows macro invocations in `extern {}` blocks. - (active, macros_in_extern, "1.27.0", Some(49476), None), - - // Allows accessing fields of unions inside `const` functions. - (active, const_fn_union, "1.27.0", Some(51909), None), - - // Allows casting raw pointers to `usize` during const eval. - (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - - // Allows dereferencing raw pointers during const eval. - (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - - // Allows comparing raw pointers during const eval. - (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - - // Allows `#[doc(alias = "...")]`. - (active, doc_alias, "1.27.0", Some(50146), None), - - // Allows inconsistent bounds in where clauses. - (active, trivial_bounds, "1.28.0", Some(48214), None), - - // Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), - - // Allows using `#[doc(keyword = "...")]`. - (active, doc_keyword, "1.28.0", Some(51315), None), - - // Allows async and await syntax. - (active, async_await, "1.28.0", Some(50547), None), - - // Allows reinterpretation of the bits of a value of one type as another type during const eval. - (active, const_transmute, "1.29.0", Some(53605), None), - - // Allows using `try {...}` expressions. - (active, try_blocks, "1.29.0", Some(31436), None), - - // Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), - - // Allows using the `amdgpu-kernel` ABI. - (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - - // Allows panicking during const eval (producing compile-time errors). - (active, const_panic, "1.30.0", Some(51999), None), - - // Allows `#[marker]` on certain traits allowing overlapping implementations. - (active, marker_trait_attr, "1.30.0", Some(29864), None), - - // Allows macro invocations on modules expressions and statements and - // procedural macros to expand to non-items. - (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - - // Allows unsized rvalues at arguments and parameters. - (active, unsized_locals, "1.30.0", Some(48055), None), - - // Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. - (active, custom_test_frameworks, "1.30.0", Some(50297), None), - - // Allows non-builtin attributes in inner attribute position. - (active, custom_inner_attributes, "1.30.0", Some(54726), None), - - // Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - - // Allows `impl Trait` in bindings (`let`, `const`, `static`). - (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), - - // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. - (active, lint_reasons, "1.31.0", Some(54503), None), - - // Allows exhaustive integer pattern matching on `usize` and `isize`. - (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - - // Allows relaxing the coherence rules such that - // `impl ForeignTrait for ForeignType is permitted. - (active, re_rebalance_coherence, "1.32.0", Some(55437), None), - - // Allows using `#[ffi_returns_twice]` on foreign functions. - (active, ffi_returns_twice, "1.34.0", Some(58314), None), - - // Allows const generic types (e.g. `struct Foo(...);`). - (active, const_generics, "1.34.0", Some(44580), None), - - // Allows using `#[optimize(X)]`. - (active, optimize_attribute, "1.34.0", Some(54882), None), - - // Allows using C-variadics. - (active, c_variadic, "1.34.0", Some(44930), None), - - // Allows the user of associated type bounds. - (active, associated_type_bounds, "1.34.0", Some(52662), None), - - // Attributes on formal function params. - (active, param_attrs, "1.36.0", Some(60406), None), - - // Allows calling constructor functions in `const fn`. - (active, const_constructor, "1.37.0", Some(61456), None), - - // Allows `if/while p && let q = r && ...` chains. - (active, let_chains, "1.37.0", Some(53667), None), - - // Allows #[repr(transparent)] on enums (RFC 2645). - (active, transparent_enums, "1.37.0", Some(60405), None), - - // Allows #[repr(transparent)] on unions (RFC 2645). - (active, transparent_unions, "1.37.0", Some(60405), None), - - // Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - - // Allows `impl Trait` with multiple unrelated lifetimes. - (active, member_constraints, "1.37.0", Some(61977), None), - - // Allows `async || body` closures. - (active, async_closure, "1.37.0", Some(62290), None), - - // Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests - (active, cfg_doctest, "1.37.0", Some(62210), None), - - // Allows `[x; N]` where `x` is a constant (RFC 2203). - (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), - - // Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates - // ------------------------------------------------------------------------- -); - -/// Some features are known to be incomplete and using them is likely to have -/// unanticipated results, such as compiler crashes. We warn the user about these -/// to alert them. -pub const INCOMPLETE_FEATURES: &[Symbol] = &[ - sym::impl_trait_in_bindings, - sym::generic_associated_types, - sym::const_generics, - sym::let_chains, -]; - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: removed features - // ------------------------------------------------------------------------- - - (removed, import_shadowing, "1.0.0", None, None, None), - (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645), None, None), - (removed, reflect, "1.0.0", Some(27749), None, None), - // A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None, None), - (removed, quad_precision_float, "1.0.0", None, None, None), - (removed, struct_inherit, "1.0.0", None, None, None), - (removed, test_removed_feature, "1.0.0", None, None, None), - (removed, visible_private_types, "1.0.0", None, None, None), - (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), - // Allows using items which are missing stability attributes - (removed, unmarked_api, "1.0.0", None, None, None), - (removed, allocator, "1.0.0", None, None, None), - (removed, simd, "1.0.0", Some(27731), None, - Some("removed in favor of `#[repr(simd)]`")), - (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, - Some("merged into `#![feature(slice_patterns)]`")), - (removed, macro_reexport, "1.0.0", Some(29638), None, - Some("subsumed by `pub use`")), - (removed, pushpop_unsafe, "1.2.0", None, None, None), - (removed, needs_allocator, "1.4.0", Some(27389), None, - Some("subsumed by `#![feature(allocator_internals)]`")), - (removed, proc_macro_mod, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_expr, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_non_items, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_gen, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, panic_implementation, "1.28.0", Some(44489), None, - Some("subsumed by `#[panic_handler]`")), - // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.32.0", Some(29644), None, - Some("subsumed by `#[proc_macro_derive]`")), - // Paths of the form: `extern::foo::bar` - (removed, extern_in_paths, "1.33.0", Some(55600), None, - Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.33.0", Some(29601), None, None), - // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). - (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), - (removed, await_macro, "1.38.0", Some(50547), None, - Some("subsumed by `.await` syntax")), - // Allows defining `existential type`s. - (removed, existential_type, "1.38.0", Some(63063), None, - Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), - - // ------------------------------------------------------------------------- - // feature-group-end: removed features - // ------------------------------------------------------------------------- -); - -declare_features! ( - (stable_removed, no_stack_check, "1.0.0", None, None), -); - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: for testing purposes - // ------------------------------------------------------------------------- - - // A temporary feature gate used to enable parser extensions needed - // to bootstrap fix for #5723. - (accepted, issue_5723_bootstrap, "1.0.0", None, None), - // These are used to test this portion of the compiler, - // they don't actually mean anything. - (accepted, test_accepted_feature, "1.0.0", None, None), - - // ------------------------------------------------------------------------- - // feature-group-end: for testing purposes - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: accepted features - // ------------------------------------------------------------------------- - - // Allows using associated `type`s in `trait`s. - (accepted, associated_types, "1.0.0", None, None), - // Allows using assigning a default type to type parameters in algebraic data type definitions. - (accepted, default_type_params, "1.0.0", None, None), - // FIXME: explain `globs`. - (accepted, globs, "1.0.0", None, None), - // Allows `macro_rules!` items. - (accepted, macro_rules, "1.0.0", None, None), - // Allows use of `&foo[a..b]` as a slicing syntax. - (accepted, slicing_syntax, "1.0.0", None, None), - // Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). - (accepted, struct_variant, "1.0.0", None, None), - // Allows indexing tuples. - (accepted, tuple_indexing, "1.0.0", None, None), - // Allows the use of `if let` expressions. - (accepted, if_let, "1.0.0", None, None), - // Allows the use of `while let` expressions. - (accepted, while_let, "1.0.0", None, None), - // Allows using `#![no_std]`. - (accepted, no_std, "1.6.0", None, None), - // Allows overloading augmented assignment operations like `a += b`. - (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // Allows empty structs and enum variants with braces. - (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - // Allows `#[deprecated]` attribute. - (accepted, deprecated, "1.9.0", Some(29935), None), - // Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245), None), - // Allows use of the postfix `?` operator in expressions. - (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns. - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - // Allows some increased flexibility in the name resolution rules, - // especially around globs and shadowing (RFC 1560). - (accepted, item_like_imports, "1.15.0", Some(35120), None), - // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // Allows elision of `'static` lifetimes in `static`s and `const`s. - (accepted, static_in_const, "1.17.0", Some(35897), None), - // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - // Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719), None), - // Allows `pub(restricted)` visibilities (RFC 1422). - (accepted, pub_restricted, "1.18.0", Some(32409), None), - // Allows `#![windows_subsystem]`. - (accepted, windows_subsystem, "1.18.0", Some(37499), None), - // Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339), None), - // Allows numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Allows coercing non capturing closures to function pointers. - (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - // Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` blocks. - (accepted, associated_consts, "1.20.0", Some(29646), None), - // Allows usage of the `compile_error!` macro. - (accepted, compile_error, "1.20.0", Some(40872), None), - // Allows code like `let x: &'static u32 = &42` to work (RFC 1414). - (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allows `Drop` types in constants (RFC 1440). - (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI. - (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358). - (accepted, repr_align, "1.25.0", Some(33626), None), - // Allows '|' at beginning of match arms (RFC 1925). - (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - // Allows nested groups in `use` items (RFC 2128). - (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // Allows indexing into constant arrays. - (accepted, const_indexing, "1.26.0", Some(29947), None), - // Allows using `a..=b` and `..=b` as inclusive range syntaxes. - (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // Allows `..=` in patterns (RFC 1192). - (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - // Allows `fn main()` with return types which implements `Termination` (RFC 1937). - (accepted, termination_trait, "1.26.0", Some(43301), None), - // Allows implementing `Clone` for closures where possible (RFC 2132). - (accepted, clone_closures, "1.26.0", Some(44490), None), - // Allows implementing `Copy` for closures where possible (RFC 2132). - (accepted, copy_closures, "1.26.0", Some(44490), None), - // Allows `impl Trait` in function arguments. - (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - // Allows `impl Trait` in function return types. - (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - // Allows using the `u128` and `i128` types. - (accepted, i128_type, "1.26.0", Some(35118), None), - // Allows default match binding modes (RFC 2005). - (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // Allows `'_` placeholder lifetimes. - (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). - (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows `cfg(target_feature = "...")`. - (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows `#[target_feature(...)]`. - (accepted, target_feature, "1.27.0", None, None), - // Allows using `dyn Trait` as a syntax for trait objects. - (accepted, dyn_trait, "1.27.0", Some(44662), None), - // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). - (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the `:lifetime` macro fragment specifier. - (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - // Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). - (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // Allows the `#[global_allocator]` attribute. - (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs. - (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Allows procedural macros in `proc-macro` crates. - (accepted, proc_macro, "1.29.0", Some(38356), None), - // Allows `foo.rs` as an alternative to `foo/mod.rs`. - (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the `:vis` macro fragment specifier - (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - // Allows importing and reexporting macros with `use`, - // enables macro modularization in general. - (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers. - (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Allows attributes scoped to tools. - (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives. - (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - // Allows all literals in attribute lists and values of key-value pairs. - (accepted, attr_literals, "1.30.0", Some(34981), None), - // Allows inferring outlives requirements (RFC 2093). - (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - // Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - // This defines the behavior of panics. - (accepted, panic_handler, "1.30.0", Some(44489), None), - // Allows `#[used]` to preserve symbols (see llvm.used). - (accepted, used, "1.30.0", Some(40289), None), - // Allows `crate` in paths. - (accepted, crate_in_paths, "1.30.0", Some(45477), None), - // Allows resolving absolute paths as paths from other crates. - (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), - // Allows access to crate names passed via `--extern` through prelude. - (accepted, extern_prelude, "1.30.0", Some(44660), None), - // Allows parentheses in patterns. - (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions. - (accepted, min_const_fn, "1.31.0", Some(53555), None), - // Allows scoped lints. - (accepted, tool_lints, "1.31.0", Some(44690), None), - // Allows lifetime elision in `impl` headers. For example: - // + `impl Iterator for &mut Iterator` - // + `impl Debug for Foo<'_>` - (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. - (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - // Allows use of `?` as the Kleene "at most one" operator in macros. - (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - // Allows `Self` struct constructor (RFC 2302). - (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - // Allows `Self` in type definitions (RFC 2300). - (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - // Allows `use x::y;` to search `x` in the current scope. - (accepted, uniform_paths, "1.32.0", Some(53130), None), - // Allows integer match exhaustiveness checking (RFC 2591). - (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - // Allows `use path as _;` and `extern crate c as _;`. - (accepted, underscore_imports, "1.33.0", Some(48216), None), - // Allows `#[repr(packed(N))]` attribute on structs. - (accepted, repr_packed, "1.33.0", Some(33158), None), - // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). - (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - // Allows let bindings, assignments and destructuring in `const` functions and constants. - // As long as control flow is not implemented in const eval, `&&` and `||` may not be used - // at the same time as let bindings. - (accepted, const_let, "1.33.0", Some(48821), None), - // Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. - (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - // Allows top level or-patterns (`p | q`) in `if let` and `while let`. - (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - // Allows `cfg(target_vendor = "...")`. - (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - // Allows `extern crate self as foo;`. - // This puts local crate root into extern prelude under name `foo`. - (accepted, extern_crate_self, "1.34.0", Some(56409), None), - // Allows arbitrary delimited token streams in non-macro attributes. - (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - // Allows paths to enum variants on type aliases including `Self`. - (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - // Allows using `#[repr(align(X))]` on enums with equivalent semantics - // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. - (accepted, repr_align_enum, "1.37.0", Some(57996), None), - // Allows `const _: TYPE = VALUE`. - (accepted, underscore_const_names, "1.37.0", Some(54912), None), - - // ------------------------------------------------------------------------- - // feature-group-end: accepted features - // ------------------------------------------------------------------------- -); - -// If you change this, please modify `src/doc/unstable-book` as well. You must -// move that documentation into the relevant place in the other docs, and -// remove the chapter on the flag. - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AttributeType { - /// Normal, builtin attribute that is consumed - /// by the compiler before the unused_attribute check - Normal, - - /// Builtin attribute that may not be consumed by the compiler - /// before the unused_attribute check. These attributes - /// will be ignored by the unused_attribute lint - Whitelisted, - - /// Builtin attribute that is only allowed at the crate level - CrateLevel, -} - -pub enum AttributeGate { - /// Is gated by a given feature gate, reason - /// and function to check if enabled - Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), - - /// Ungated attribute, can be used on all release channels - Ungated, -} - -/// A convenience macro for constructing attribute templates. -/// E.g., `template!(Word, List: "description")` means that the attribute -/// supports forms `#[attr]` and `#[attr(description)]`. -macro_rules! template { - (Word) => { template!(@ true, None, None) }; - (List: $descr: expr) => { template!(@ false, Some($descr), None) }; - (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; - (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; - (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; - (List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ false, Some($descr1), Some($descr2)) - }; - (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ true, Some($descr1), Some($descr2)) - }; - (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { - word: $word, list: $list, name_value_str: $name_value_str - } }; -} - -impl AttributeGate { - fn is_deprecated(&self) -> bool { - match *self { - Gated(Stability::Deprecated(_, _), ..) => true, - _ => false, - } - } -} - -#[derive(Copy, Clone, Debug)] -pub enum Stability { - Unstable, - // First argument is tracking issue link; second argument is an optional - // help message, which defaults to "remove this attribute" - Deprecated(&'static str, Option<&'static str>), -} - -// fn() is not Debug -impl std::fmt::Debug for AttributeGate { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Gated(ref stab, name, expl, _) => - write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), - Ungated => write!(fmt, "Ungated") - } - } -} - -macro_rules! cfg_fn { - ($field: ident) => {{ - fn f(features: &Features) -> bool { - features.$field - } - f as fn(&Features) -> bool - }} -} - -pub fn deprecated_attributes() -> Vec<&'static (Symbol, AttributeType, - AttributeTemplate, AttributeGate)> { - BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() -} - -pub fn is_builtin_attr_name(name: ast::Name) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() -} - -pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some() -} - -/// Attributes that have a special meaning to rustc or rustdoc -pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ - // Normal attributes - - ( - sym::warn, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::allow, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::forbid, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::deny, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - - (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), - (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), - (sym::plugin_registrar, Normal, template!(Word), Ungated), - - (sym::cfg, Normal, template!(List: "predicate"), Ungated), - (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), - (sym::main, Normal, template!(Word), Ungated), - (sym::start, Normal, template!(Word), Ungated), - (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), - (sym::path, Normal, template!(NameValueStr: "file"), Ungated), - (sym::automatically_derived, Normal, template!(Word), Ungated), - (sym::no_mangle, Whitelisted, template!(Word), Ungated), - (sym::no_link, Normal, template!(Word), Ungated), - (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), - ( - sym::should_panic, - Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), - Ungated - ), - (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), - (sym::no_implicit_prelude, Normal, template!(Word), Ungated), - (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), - (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, - sym::link_args, - "the `link_args` attribute is experimental and not \ - portable across platforms, it is recommended to \ - use `#[link(name = \"foo\")] instead", - cfg_fn!(link_args))), - (sym::macro_escape, Normal, template!(Word), Ungated), - - // RFC #1445. - (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::structural_match, - "the semantics of constant patterns is \ - not yet settled", - cfg_fn!(structural_match))), - - // RFC #2008 - (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::non_exhaustive, - "non exhaustive is an experimental feature", - cfg_fn!(non_exhaustive))), - - // RFC #1268 - (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::marker_trait_attr, - "marker traits is an experimental feature", - cfg_fn!(marker_trait_attr))), - - (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, - sym::plugin, - "compiler plugins are experimental \ - and possibly buggy", - cfg_fn!(plugin))), - - (sym::no_std, CrateLevel, template!(Word), Ungated), - (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, - sym::no_core, - "no_core is experimental", - cfg_fn!(no_core))), - (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, - sym::lang_items, - "language items are subject to change", - cfg_fn!(lang_items))), - (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), - Gated(Stability::Unstable, - sym::linkage, - "the `linkage` attribute is experimental \ - and not portable across platforms", - cfg_fn!(linkage))), - (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::thread_local, - "`#[thread_local]` is an experimental feature, and does \ - not currently handle destructors", - cfg_fn!(thread_local))), - - (sym::rustc_on_unimplemented, Whitelisted, template!(List: - r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, - NameValueStr: "message"), - Gated(Stability::Unstable, - sym::on_unimplemented, - "the `#[rustc_on_unimplemented]` attribute \ - is an experimental feature", - cfg_fn!(on_unimplemented))), - (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), - Gated(Stability::Unstable, - sym::rustc_const_unstable, - "the `#[rustc_const_unstable]` attribute \ - is an internal feature", - cfg_fn!(rustc_const_unstable))), - (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[default_lib_allocator]` \ - attribute is an experimental feature", - cfg_fn!(allocator_internals))), - (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[needs_allocator]` \ - attribute is an experimental \ - feature", - cfg_fn!(allocator_internals))), - (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::panic_runtime, - "the `#[panic_runtime]` attribute is \ - an experimental feature", - cfg_fn!(panic_runtime))), - (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::needs_panic_runtime, - "the `#[needs_panic_runtime]` \ - attribute is an experimental \ - feature", - cfg_fn!(needs_panic_runtime))), - (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_outlives]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_variance]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_start]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_end]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_regions]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_error]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dirty]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_clean]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_partition_reused, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs) - ) - ), - ( - sym::rustc_partition_codegened, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", - kind = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_mir]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_inherit_overflow_checks, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_inherit_overflow_checks]` \ - attribute is just used to control \ - overflow checking behavior of several \ - libcore functions that are inlined \ - across crates and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - - (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_env_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_object_lifetime_default]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_test_marker]` attribute \ - is used internally to track tests", - cfg_fn!(rustc_attrs))), - (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr: - "transparent|semitransparent|opaque"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally for testing macro hygiene", - cfg_fn!(rustc_attrs))), - (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::compiler_builtins, - "the `#[compiler_builtins]` attribute is used to \ - identify the `compiler_builtins` crate which \ - contains compiler-rt intrinsics and will never be \ - stable", - cfg_fn!(compiler_builtins))), - (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::sanitizer_runtime, - "the `#[sanitizer_runtime]` attribute is used to \ - identify crates that contain the runtime of a \ - sanitizer and will never be stable", - cfg_fn!(sanitizer_runtime))), - (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::profiler_runtime, - "the `#[profiler_runtime]` attribute is used to \ - identify the `profiler_builtins` crate which \ - contains the profiler runtime and will never be \ - stable", - cfg_fn!(profiler_runtime))), - - (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), - Gated(Stability::Unstable, - sym::allow_internal_unstable, - EXPLAIN_ALLOW_INTERNAL_UNSTABLE, - cfg_fn!(allow_internal_unstable))), - - (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_internal_unsafe, - EXPLAIN_ALLOW_INTERNAL_UNSAFE, - cfg_fn!(allow_internal_unsafe))), - - (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::fundamental, - "the `#[fundamental]` attribute \ - is an experimental feature", - cfg_fn!(fundamental))), - - (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ - /*opt*/ attributes(name1, name2, ...)"), - Ungated), - - (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable, - sym::rustc_attrs, - "used by the test suite", - cfg_fn!(rustc_attrs))), - - // FIXME: #14408 whitelist docs since rustdoc looks at them - ( - sym::doc, - Whitelisted, - template!(List: "hidden|inline|...", NameValueStr: "string"), - Ungated - ), - - // FIXME: #14406 these are processed in codegen, which happens after the - // lint pass - (sym::cold, Whitelisted, template!(Word), Ungated), - (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::naked_functions, - "the `#[naked]` attribute \ - is an experimental feature", - cfg_fn!(naked_functions))), - (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::ffi_returns_twice, - "the `#[ffi_returns_twice]` attribute \ - is an experimental feature", - cfg_fn!(ffi_returns_twice))), - (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), - (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), - (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...""#), Ungated), - (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::no_builtins, Whitelisted, template!(Word), Ungated), - (sym::no_debug, Whitelisted, template!(Word), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - sym::no_debug, - "the `#[no_debug]` attribute was an experimental feature that has been \ - deprecated due to lack of demand", - cfg_fn!(no_debug))), - ( - sym::omit_gdb_pretty_printer_section, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::omit_gdb_pretty_printer_section, - "the `#[omit_gdb_pretty_printer_section]` \ - attribute is just used for the Rust test \ - suite", - cfg_fn!(omit_gdb_pretty_printer_section) - ) - ), - (sym::may_dangle, - Normal, - template!(Word), - Gated(Stability::Unstable, - sym::dropck_eyepatch, - "`may_dangle` has unstable semantics and may be removed in the future", - cfg_fn!(dropck_eyepatch))), - (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, - sym::unwind_attributes, - "`#[unwind]` is experimental", - cfg_fn!(unwind_attributes))), - (sym::used, Whitelisted, template!(Word), Ungated), - - // used in resolve - (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::prelude_import, - "`#[prelude_import]` is for use by rustc only", - cfg_fn!(prelude_import))), - - // FIXME: #14407 these are only looked at on-demand so we can't - // guarantee they'll have already been checked - ( - sym::rustc_deprecated, - Whitelisted, - template!(List: r#"since = "version", reason = "...""#), - Ungated - ), - (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), - ( - sym::stable, - Whitelisted, - template!(List: r#"feature = "name", since = "version""#), - Ungated - ), - ( - sym::unstable, - Whitelisted, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), - Ungated - ), - (sym::deprecated, - Normal, - template!( - Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, - NameValueStr: "reason" - ), - Ungated - ), - - (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, - sym::unboxed_closures, - "unboxed_closures are still evolving", - cfg_fn!(unboxed_closures))), - - (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), - - (sym::proc_macro_attribute, Normal, template!(Word), Ungated), - (sym::proc_macro, Normal, template!(Word), Ungated), - - (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally by rustc", - cfg_fn!(rustc_attrs))), - - (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_fail, - "allow_fail attribute is currently unstable", - cfg_fn!(allow_fail))), - - (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - // whitelists "identity-like" conversion methods to suggest on type mismatch - (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - ( - sym::rustc_args_required_const, - Whitelisted, - template!(List: "N"), - Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", - cfg_fn!(rustc_attrs)) - ), - // RFC 2070 - (sym::panic_handler, Normal, template!(Word), Ungated), - - (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, - sym::alloc_error_handler, - "`#[alloc_error_handler]` is an unstable feature", - cfg_fn!(alloc_error_handler))), - - // RFC 2412 - (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, - sym::optimize_attribute, - "`#[optimize]` attribute is an unstable feature", - cfg_fn!(optimize_attribute))), - - // Crate level attributes - (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), - (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), - (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), - (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), - (sym::no_start, CrateLevel, template!(Word), Ungated), - (sym::no_main, CrateLevel, template!(Word), Ungated), - (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, - sym::custom_test_frameworks, - "custom test frameworks are an unstable feature", - cfg_fn!(custom_test_frameworks))), -]; - -pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); - -lazy_static! { - pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap = { - let mut map = FxHashMap::default(); - for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.0, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.0); - } - } - map - }; -} - -// cfg(...)'s that are feature gated -const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ - // (name in cfg, feature, function to check if the feature is enabled) - (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), - (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), - (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), - (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), -]; - -#[derive(Debug)] -pub struct GatedCfg { - span: Span, - index: usize, -} - -impl GatedCfg { - pub fn gate(cfg: &ast::MetaItem) -> Option { - GATED_CFGS.iter() - .position(|info| cfg.check_name(info.0)) - .map(|idx| { - GatedCfg { - span: cfg.span, - index: idx - } - }) - } - - pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { - let (cfg, feature, has_feature) = GATED_CFGS[self.index]; - if !has_feature(features) && !self.span.allows_unstable(feature) { - let explain = format!("`cfg({})` is experimental and subject to change", cfg); - emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); - } - } -} - -struct Context<'a> { - features: &'a Features, - parse_sess: &'a ParseSess, - plugin_attributes: &'a [(Symbol, AttributeType)], -} - -macro_rules! gate_feature_fn { - ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ - let (cx, has_feature, span, - name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); - let has_feature: bool = has_feature(&$cx.features); - debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); - if !has_feature && !span.allows_unstable($name) { - leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) - .emit(); - } - }} -} - -macro_rules! gate_feature { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, GateStrength::Hard) - }; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, $level) - }; -} - -impl<'a> Context<'a> { - fn check_attribute( - &self, - attr: &ast::Attribute, - attr_info: Option<&BuiltinAttribute>, - is_macro: bool - ) { - debug!("check_attribute(attr = {:?})", attr); - if let Some(&(name, ty, _template, ref gateage)) = attr_info { - if let Gated(_, name, desc, ref has_feature) = *gateage { - if !attr.span.allows_unstable(name) { - gate_feature_fn!( - self, has_feature, attr.span, name, desc, GateStrength::Hard - ); - } - } else if name == sym::doc { - if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name(sym::include)) { - gate_feature!(self, external_doc, attr.span, - "`#[doc(include = \"...\")]` is experimental" - ); - } - } - } - debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); - return; - } else { - for segment in &attr.path.segments { - if segment.ident.as_str().starts_with("rustc") { - let msg = "attributes starting with `rustc` are \ - reserved for use by the `rustc` compiler"; - gate_feature!(self, rustc_attrs, segment.ident.span, msg); - } - } - } - for &(n, ty) in self.plugin_attributes { - if attr.path == n { - // Plugins can't gate attributes, so we don't check for it - // unlike the code above; we only use this loop to - // short-circuit to avoid the checks below. - debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); - return; - } - } - if !is_macro && !attr::is_known(attr) { - // Only run the custom attribute lint during regular feature gate - // checking. Macro gating runs before the plugin attributes are - // registered, so we skip this in that case. - let msg = format!("the attribute `{}` is currently unknown to the compiler and \ - may have meaning added to it in the future", attr.path); - gate_feature!(self, custom_attribute, attr.span, &msg); - } - } -} - -pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { - let cx = Context { features, parse_sess, plugin_attributes: &[] }; - cx.check_attribute( - attr, - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)), - true - ); -} - -fn find_lang_feature_issue(feature: Symbol) -> Option { - if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { - let issue = info.2; - // FIXME (#28244): enforce that active features have issue numbers - // assert!(issue.is_some()) - issue - } else { - // search in Accepted, Removed, or Stable Removed features - let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) - .find(|t| t.0 == feature); - match found { - Some(&(_, _, issue, _)) => issue, - None => panic!("Feature `{}` is not declared anywhere", feature), - } - } -} - -pub enum GateIssue { - Language, - Library(Option) -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum GateStrength { - /// A hard error. (Most feature gates should use this.) - Hard, - /// Only a warning. (Use this only as backwards-compatibility demands.) - Soft, -} - -pub fn emit_feature_err( - sess: &ParseSess, - feature: Symbol, - span: Span, - issue: GateIssue, - explain: &str, -) { - feature_err(sess, feature, span, issue, explain).emit(); -} - -pub fn feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, -) -> DiagnosticBuilder<'a> { - leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) -} - -fn leveled_feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, - level: GateStrength, -) -> DiagnosticBuilder<'a> { - let diag = &sess.span_diagnostic; - - let issue = match issue { - GateIssue::Language => find_lang_feature_issue(feature), - GateIssue::Library(lib) => lib, - }; - - let mut err = match level { - GateStrength::Hard => { - diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658)) - } - GateStrength::Soft => diag.struct_span_warn(span, explain), - }; - - match issue { - None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility - Some(n) => { - err.note(&format!( - "for more information, see https://github.com/rust-lang/rust/issues/{}", - n, - )); - } - } - - // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { - err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); - } - - // If we're on stable and only emitting a "soft" warning, add a note to - // clarify that the feature isn't "on" (rather than being on but - // warning-worthy). - if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { - err.help("a nightly build of the compiler is required to enable this feature"); - } - - err - -} - -const EXPLAIN_BOX_SYNTAX: &str = - "box expression syntax is experimental; you can call `Box::new` instead"; - -pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = - "attributes on expressions are experimental"; - -pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = - "allow_internal_unstable side-steps feature gating and stability checks"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = - "allow_internal_unsafe side-steps the unsafe_code lint"; - -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = - "unsized tuple coercion is not stable enough for use and is subject to change"; - -struct PostExpansionVisitor<'a> { - context: &'a Context<'a>, - builtin_attributes: &'static FxHashMap, -} - -macro_rules! gate_feature_post { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain) - } - }}; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain, $level) - } - }} -} - -impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: Abi, span: Span) { - match abi { - Abi::RustIntrinsic => { - gate_feature_post!(&self, intrinsics, span, - "intrinsics are subject to change"); - }, - Abi::PlatformIntrinsic => { - gate_feature_post!(&self, platform_intrinsics, span, - "platform intrinsics are experimental and possibly buggy"); - }, - Abi::Vectorcall => { - gate_feature_post!(&self, abi_vectorcall, span, - "vectorcall is experimental and subject to change"); - }, - Abi::Thiscall => { - gate_feature_post!(&self, abi_thiscall, span, - "thiscall is experimental and subject to change"); - }, - Abi::RustCall => { - gate_feature_post!(&self, unboxed_closures, span, - "rust-call ABI is subject to change"); - }, - Abi::PtxKernel => { - gate_feature_post!(&self, abi_ptx, span, - "PTX ABIs are experimental and subject to change"); - }, - Abi::Unadjusted => { - gate_feature_post!(&self, abi_unadjusted, span, - "unadjusted ABI is an implementation detail and perma-unstable"); - }, - Abi::Msp430Interrupt => { - gate_feature_post!(&self, abi_msp430_interrupt, span, - "msp430-interrupt ABI is experimental and subject to change"); - }, - Abi::X86Interrupt => { - gate_feature_post!(&self, abi_x86_interrupt, span, - "x86-interrupt ABI is experimental and subject to change"); - }, - Abi::AmdGpuKernel => { - gate_feature_post!(&self, abi_amdgpu_kernel, span, - "amdgpu-kernel ABI is experimental and subject to change"); - }, - // Stable - Abi::Cdecl | - Abi::Stdcall | - Abi::Fastcall | - Abi::Aapcs | - Abi::Win64 | - Abi::SysV64 | - Abi::Rust | - Abi::C | - Abi::System => {} - } - } -} - -impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { - fn visit_attribute(&mut self, attr: &ast::Attribute) { - let attr_info = attr.ident().and_then(|ident| { - self.builtin_attributes.get(&ident.name).map(|a| *a) - }); - - // Check for gated attributes. - self.context.check_attribute(attr, attr_info, false); - - if attr.check_name(sym::doc) { - if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name(sym::cfg) { - gate_feature_post!(&self, doc_cfg, attr.span, - "`#[doc(cfg(...))]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::masked)) { - gate_feature_post!(&self, doc_masked, attr.span, - "`#[doc(masked)]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::spotlight)) { - gate_feature_post!(&self, doc_spotlight, attr.span, - "`#[doc(spotlight)]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::alias)) { - gate_feature_post!(&self, doc_alias, attr.span, - "`#[doc(alias = \"...\")]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::keyword)) { - gate_feature_post!(&self, doc_keyword, attr.span, - "`#[doc(keyword = \"...\")]` is experimental" - ); - } - } - } - - match attr_info { - // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(&(name, _, template, _)) if name != sym::rustc_dummy => - check_builtin_attribute(self.context.parse_sess, attr, name, template), - _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() { - if token == token::Eq { - // All key-value attributes are restricted to meta-item syntax. - attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok(); - } - } - } - } - - fn visit_name(&mut self, sp: Span, name: ast::Name) { - if !name.as_str().is_ascii() { - gate_feature_post!( - &self, - non_ascii_idents, - self.context.parse_sess.source_map().def_span(sp), - "non-ascii idents are not fully supported" - ); - } - } - - fn visit_item(&mut self, i: &'a ast::Item) { - match i.node { - ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi, i.span); - } - - ast::ItemKind::Fn(..) => { - if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { - gate_feature_post!(&self, plugin_registrar, i.span, - "compiler plugins are experimental and possibly buggy"); - } - if attr::contains_name(&i.attrs[..], sym::start) { - gate_feature_post!(&self, start, i.span, - "a `#[start]` function is an experimental \ - feature whose signature may change \ - over time"); - } - if attr::contains_name(&i.attrs[..], sym::main) { - gate_feature_post!(&self, main, i.span, - "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required"); - } - } - - ast::ItemKind::Struct(..) => { - for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { - for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name(sym::simd) { - gate_feature_post!(&self, repr_simd, attr.span, - "SIMD types are experimental and possibly buggy"); - } - } - } - } - - ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { - for variant in variants { - match (&variant.node.data, &variant.node.disr_expr) { - (ast::VariantData::Unit(..), _) => {}, - (_, Some(disr_expr)) => - gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental"), - _ => {}, - } - } - - let has_feature = self.context.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - Parser::maybe_report_invalid_custom_discriminants( - self.context.parse_sess, - &variants, - ); - } - } - - ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => { - if polarity == ast::ImplPolarity::Negative { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "negative trait bounds are not yet fully implemented; \ - use marker types for now"); - } - - if let ast::Defaultness::Default = defaultness { - gate_feature_post!(&self, specialization, - i.span, - "specialization is unstable"); - } - } - - ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "auto traits are experimental and possibly buggy"); - } - - ast::ItemKind::TraitAlias(..) => { - gate_feature_post!( - &self, - trait_alias, - i.span, - "trait aliases are experimental" - ); - } - - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { - let msg = "`macro` is experimental"; - gate_feature_post!(&self, decl_macro, i.span, msg); - } - - ast::ItemKind::OpaqueTy(..) => { - gate_feature_post!( - &self, - type_alias_impl_trait, - i.span, - "`impl Trait` in type aliases is unstable" - ); - } - - _ => {} - } - - visit::walk_item(self, i); - } - - fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) { - match i.node { - ast::ForeignItemKind::Fn(..) | - ast::ForeignItemKind::Static(..) => { - let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); - let links_to_llvm = match link_name { - Some(val) => val.as_str().starts_with("llvm."), - _ => false - }; - if links_to_llvm { - gate_feature_post!(&self, link_llvm_intrinsics, i.span, - "linking to LLVM intrinsics is experimental"); - } - } - ast::ForeignItemKind::Ty => { - gate_feature_post!(&self, extern_types, i.span, - "extern types are experimental"); - } - ast::ForeignItemKind::Macro(..) => {} - } - - visit::walk_foreign_item(self, i) - } - - fn visit_ty(&mut self, ty: &'a ast::Ty) { - match ty.node { - ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi, ty.span); - } - ast::TyKind::Never => { - gate_feature_post!(&self, never_type, ty.span, - "The `!` type is experimental"); - } - _ => {} - } - visit::walk_ty(self, ty) - } - - fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { - if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { - if let ast::TyKind::Never = output_ty.node { - // Do nothing. - } else { - self.visit_ty(output_ty) - } - } - } - - fn visit_expr(&mut self, e: &'a ast::Expr) { - match e.node { - ast::ExprKind::Box(_) => { - gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); - } - ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. - if self.context.parse_sess.span_diagnostic.err_count() == 0 { - gate_feature_post!(&self, type_ascription, e.span, - "type ascription is experimental"); - } - } - ast::ExprKind::Yield(..) => { - gate_feature_post!(&self, generators, - e.span, - "yield syntax is experimental"); - } - ast::ExprKind::TryBlock(_) => { - gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); - } - ast::ExprKind::Block(_, opt_label) => { - if let Some(label) = opt_label { - gate_feature_post!(&self, label_break_value, label.ident.span, - "labels on blocks are unstable"); - } - } - ast::ExprKind::Async(..) => { - gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); - } - ast::ExprKind::Await(_) => { - gate_feature_post!(&self, async_await, e.span, "async/await is unstable"); - } - _ => {} - } - visit::walk_expr(self, e) - } - - fn visit_arm(&mut self, arm: &'a ast::Arm) { - visit::walk_arm(self, arm) - } - - fn visit_pat(&mut self, pattern: &'a ast::Pat) { - match &pattern.node { - PatKind::Slice(pats) => { - for pat in &*pats { - let span = pat.span; - let inner_pat = match &pat.node { - PatKind::Ident(.., Some(pat)) => pat, - _ => pat, - }; - if inner_pat.is_rest() { - gate_feature_post!( - &self, - slice_patterns, - span, - "subslice patterns are unstable" - ); - } - } - } - PatKind::Box(..) => { - gate_feature_post!(&self, box_patterns, - pattern.span, - "box pattern syntax is experimental"); - } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { - gate_feature_post!(&self, exclusive_range_pattern, pattern.span, - "exclusive range pattern syntax is experimental"); - } - _ => {} - } - visit::walk_pat(self, pattern) - } - - fn visit_fn(&mut self, - fn_kind: FnKind<'a>, - fn_decl: &'a ast::FnDecl, - span: Span, - _node_id: NodeId) { - if let Some(header) = fn_kind.header() { - // Check for const fn and async fn declarations. - if header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, span, "async fn is unstable"); - } - - // Stability of const fn methods are covered in - // `visit_trait_item` and `visit_impl_item` below; this is - // because default methods don't pass through this point. - self.check_abi(header.abi, span); - } - - if fn_decl.c_variadic { - gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); - } - - visit::walk_fn(self, fn_kind, fn_decl, span) - } - - fn visit_generic_param(&mut self, param: &'a GenericParam) { - match param.kind { - GenericParamKind::Const { .. } => - gate_feature_post!(&self, const_generics, param.ident.span, - "const generics are unstable"), - _ => {} - } - visit::walk_generic_param(self, param) - } - - fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { - match constraint.kind { - AssocTyConstraintKind::Bound { .. } => - gate_feature_post!(&self, associated_type_bounds, constraint.span, - "associated type bounds are unstable"), - _ => {} - } - visit::walk_assoc_ty_constraint(self, constraint) - } - - fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { - match ti.node { - ast::TraitItemKind::Method(ref sig, ref block) => { - if block.is_none() { - self.check_abi(sig.header.abi, ti.span); - } - if sig.header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, ti.span, "async fn is unstable"); - } - if sig.decl.c_variadic { - gate_feature_post!(&self, c_variadic, ti.span, - "C-variadic functions are unstable"); - } - if sig.header.constness.node == ast::Constness::Const { - gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); - } - } - ast::TraitItemKind::Type(_, ref default) => { - // We use three if statements instead of something like match guards so that all - // of these errors can be emitted if all cases apply. - if default.is_some() { - gate_feature_post!(&self, associated_type_defaults, ti.span, - "associated type defaults are unstable"); - } - if !ti.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "generic associated types are unstable"); - } - if !ti.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_trait_item(self, ti) - } - - fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { - if ii.defaultness == ast::Defaultness::Default { - gate_feature_post!(&self, specialization, - ii.span, - "specialization is unstable"); - } - - match ii.node { - ast::ImplItemKind::Method(..) => {} - ast::ImplItemKind::OpaqueTy(..) => { - gate_feature_post!( - &self, - type_alias_impl_trait, - ii.span, - "`impl Trait` in type aliases is unstable" - ); - } - ast::ImplItemKind::TyAlias(_) => { - if !ii.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "generic associated types are unstable"); - } - if !ii.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_impl_item(self, ii) - } - - fn visit_vis(&mut self, vis: &'a ast::Visibility) { - if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { - gate_feature_post!(&self, crate_visibility_modifier, vis.span, - "`crate` visibility modifier is experimental"); - } - visit::walk_vis(self, vis) - } -} - -pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], - crate_edition: Edition, allow_features: &Option>) -> Features { - fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { - let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); - if let Some(reason) = reason { - err.span_note(span, reason); - } else { - err.span_label(span, "feature has been removed"); - } - err.emit(); - } - - let mut features = Features::new(); - let mut edition_enabled_features = FxHashMap::default(); - - for &edition in ALL_EDITIONS { - if edition <= crate_edition { - // The `crate_edition` implies its respective umbrella feature-gate - // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). - edition_enabled_features.insert(edition.feature_name(), edition); - } - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= crate_edition { - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, crate_edition); - } - } - } - - // Process the edition umbrella feature-gates first, to ensure - // `edition_enabled_features` is completed before it's queried. - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - for mi in list { - if !mi.is_word() { - continue; - } - - let name = mi.name_or_empty(); - - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { - if *edition <= crate_edition { - continue; - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= *edition { - // FIXME(Manishearth) there is currently no way to set - // lib features by edition - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, *edition); - } - } - } - } - } - } - - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - let bad_input = |span| { - struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") - }; - - for mi in list { - let name = match mi.ident() { - Some(ident) if mi.is_word() => ident.name, - Some(ident) => { - bad_input(mi.span()).span_suggestion( - mi.span(), - "expected just one word", - format!("{}", ident.name), - Applicability::MaybeIncorrect, - ).emit(); - continue - } - None => { - bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); - continue - } - }; - - if let Some(edition) = edition_enabled_features.get(&name) { - struct_span_warn!( - span_handler, - mi.span(), - E0705, - "the feature `{}` is included in the Rust {} edition", - name, - edition, - ).emit(); - continue; - } - - if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { - // Handled in the separate loop above. - continue; - } - - let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); - let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); - if let Some((.., reason)) = removed.or(stable_removed) { - feature_removed(span_handler, mi.span(), *reason); - continue; - } - - if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { - let since = Some(Symbol::intern(since)); - features.declared_lang_features.push((name, mi.span(), since)); - continue; - } - - if let Some(allowed) = allow_features.as_ref() { - if allowed.iter().find(|f| *f == name.as_str()).is_none() { - span_err!(span_handler, mi.span(), E0725, - "the feature `{}` is not in the list of allowed features", - name); - continue; - } - } - - if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - set(&mut features, mi.span()); - features.declared_lang_features.push((name, mi.span(), None)); - continue; - } - - features.declared_lib_features.push((name, mi.span())); - } - } - - features -} - -fn for_each_in_lock(vec: &Lock>, f: impl Fn(&T)) { - vec.borrow().iter().for_each(f); -} - -pub fn check_crate(krate: &ast::Crate, - sess: &ParseSess, - features: &Features, - plugin_attributes: &[(Symbol, AttributeType)], - unstable: UnstableFeatures) { - maybe_stage_features(&sess.span_diagnostic, krate, unstable); - let ctx = Context { - features, - parse_sess: sess, - plugin_attributes, - }; - - for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( - &ctx, - let_chains, - *span, - "`let` expressions in this position are experimental" - )); - - for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!( - &ctx, - async_closure, - *span, - "async closures are unstable" - )); - - let visitor = &mut PostExpansionVisitor { - context: &ctx, - builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, - }; - visit::walk_crate(visitor, krate); -} - -#[derive(Clone, Copy, Hash)] -pub enum UnstableFeatures { - /// Hard errors for unstable features are active, as on beta/stable channels. - Disallow, - /// Allow features to be activated, as on nightly. - Allow, - /// Errors are bypassed for bootstrapping. This is required any time - /// during the build that feature-related lints are set to warn or above - /// because the build turns on warnings-as-errors and uses lots of unstable - /// features. As a result, this is always required for building Rust itself. - Cheat -} - -impl UnstableFeatures { - pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e., on the beta or stable channel - let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // Whether we should enable unstable features for bootstrapping - let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); - match (disable_unstable_features, bootstrap) { - (_, true) => UnstableFeatures::Cheat, - (true, _) => UnstableFeatures::Disallow, - (false, _) => UnstableFeatures::Allow - } - } - - pub fn is_nightly_build(&self) -> bool { - match *self { - UnstableFeatures::Allow | UnstableFeatures::Cheat => true, - _ => false, - } - } -} - -fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, - unstable: UnstableFeatures) { - let allow_features = match unstable { - UnstableFeatures::Allow => true, - UnstableFeatures::Disallow => false, - UnstableFeatures::Cheat => true - }; - if !allow_features { - for attr in &krate.attrs { - if attr.check_name(sym::feature) { - let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); - span_err!(span_handler, attr.span, E0554, - "`#![feature]` may not be used on the {} release channel", - release_channel); - } - } - } -} diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs new file mode 100644 index 0000000000..5538daf388 --- /dev/null +++ b/src/libsyntax/feature_gate/accepted.rs @@ -0,0 +1,252 @@ +//! List of the accepted feature gates. + +use crate::symbol::sym; +use super::{State, Feature}; + +macro_rules! declare_features { + ($( + $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None), + )+) => { + /// Those language feature has since been Accepted (it was once Active) + pub const ACCEPTED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Accepted, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ + ]; + } +} + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: for testing purposes + // ------------------------------------------------------------------------- + + /// A temporary feature gate used to enable parser extensions needed + /// to bootstrap fix for #5723. + (accepted, issue_5723_bootstrap, "1.0.0", None, None), + /// These are used to test this portion of the compiler, + /// they don't actually mean anything. + (accepted, test_accepted_feature, "1.0.0", None, None), + + // ------------------------------------------------------------------------- + // feature-group-end: for testing purposes + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: accepted features + // ------------------------------------------------------------------------- + + /// Allows using associated `type`s in `trait`s. + (accepted, associated_types, "1.0.0", None, None), + /// Allows using assigning a default type to type parameters in algebraic data type definitions. + (accepted, default_type_params, "1.0.0", None, None), + // FIXME: explain `globs`. + (accepted, globs, "1.0.0", None, None), + /// Allows `macro_rules!` items. + (accepted, macro_rules, "1.0.0", None, None), + /// Allows use of `&foo[a..b]` as a slicing syntax. + (accepted, slicing_syntax, "1.0.0", None, None), + /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). + (accepted, struct_variant, "1.0.0", None, None), + /// Allows indexing tuples. + (accepted, tuple_indexing, "1.0.0", None, None), + /// Allows the use of `if let` expressions. + (accepted, if_let, "1.0.0", None, None), + /// Allows the use of `while let` expressions. + (accepted, while_let, "1.0.0", None, None), + /// Allows using `#![no_std]`. + (accepted, no_std, "1.6.0", None, None), + /// Allows overloading augmented assignment operations like `a += b`. + (accepted, augmented_assignments, "1.8.0", Some(28235), None), + /// Allows empty structs and enum variants with braces. + (accepted, braced_empty_structs, "1.8.0", Some(29720), None), + /// Allows `#[deprecated]` attribute. + (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows macros to appear in the type position. + (accepted, type_macros, "1.13.0", Some(27245), None), + /// Allows use of the postfix `?` operator in expressions. + (accepted, question_mark, "1.13.0", Some(31436), None), + /// Allows `..` in tuple (struct) patterns. + (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), + /// Allows some increased flexibility in the name resolution rules, + /// especially around globs and shadowing (RFC 1560). + (accepted, item_like_imports, "1.15.0", Some(35120), None), + /// Allows using `Self` and associated types in struct expressions and patterns. + (accepted, more_struct_aliases, "1.16.0", Some(37544), None), + /// Allows elision of `'static` lifetimes in `static`s and `const`s. + (accepted, static_in_const, "1.17.0", Some(35897), None), + /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. + (accepted, field_init_shorthand, "1.17.0", Some(37340), None), + /// Allows the definition recursive static items. + (accepted, static_recursion, "1.17.0", Some(29719), None), + /// Allows `pub(restricted)` visibilities (RFC 1422). + (accepted, pub_restricted, "1.18.0", Some(32409), None), + /// Allows `#![windows_subsystem]`. + (accepted, windows_subsystem, "1.18.0", Some(37499), None), + /// Allows `break {expr}` with a value inside `loop`s. + (accepted, loop_break_value, "1.19.0", Some(37339), None), + /// Allows numeric fields in struct expressions and patterns. + (accepted, relaxed_adts, "1.19.0", Some(35626), None), + /// Allows coercing non capturing closures to function pointers. + (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), + /// Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814), None), + /// Allows the definition of associated constants in `trait` or `impl` blocks. + (accepted, associated_consts, "1.20.0", Some(29646), None), + /// Allows usage of the `compile_error!` macro. + (accepted, compile_error, "1.20.0", Some(40872), None), + /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). + (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), + /// Allows `Drop` types in constants (RFC 1440). + (accepted, drop_types_in_const, "1.22.0", Some(33156), None), + /// Allows the sysV64 ABI to be specified on all platforms + /// instead of just the platforms on which it is the C ABI. + (accepted, abi_sysv64, "1.24.0", Some(36167), None), + /// Allows `repr(align(16))` struct attribute (RFC 1358). + (accepted, repr_align, "1.25.0", Some(33626), None), + /// Allows '|' at beginning of match arms (RFC 1925). + (accepted, match_beginning_vert, "1.25.0", Some(44101), None), + /// Allows nested groups in `use` items (RFC 2128). + (accepted, use_nested_groups, "1.25.0", Some(44494), None), + /// Allows indexing into constant arrays. + (accepted, const_indexing, "1.26.0", Some(29947), None), + /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. + (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), + /// Allows `..=` in patterns (RFC 1192). + (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). + (accepted, termination_trait, "1.26.0", Some(43301), None), + /// Allows implementing `Clone` for closures where possible (RFC 2132). + (accepted, clone_closures, "1.26.0", Some(44490), None), + /// Allows implementing `Copy` for closures where possible (RFC 2132). + (accepted, copy_closures, "1.26.0", Some(44490), None), + /// Allows `impl Trait` in function arguments. + (accepted, universal_impl_trait, "1.26.0", Some(34511), None), + /// Allows `impl Trait` in function return types. + (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), + /// Allows using the `u128` and `i128` types. + (accepted, i128_type, "1.26.0", Some(35118), None), + /// Allows default match binding modes (RFC 2005). + (accepted, match_default_bindings, "1.26.0", Some(42640), None), + /// Allows `'_` placeholder lifetimes. + (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), + /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). + (accepted, generic_param_attrs, "1.27.0", Some(48848), None), + /// Allows `cfg(target_feature = "...")`. + (accepted, cfg_target_feature, "1.27.0", Some(29717), None), + /// Allows `#[target_feature(...)]`. + (accepted, target_feature, "1.27.0", None, None), + /// Allows using `dyn Trait` as a syntax for trait objects. + (accepted, dyn_trait, "1.27.0", Some(44662), None), + /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). + (accepted, fn_must_use, "1.27.0", Some(43302), None), + /// Allows use of the `:lifetime` macro fragment specifier. + (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), + /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). + (accepted, termination_trait_test, "1.27.0", Some(48854), None), + /// Allows the `#[global_allocator]` attribute. + (accepted, global_allocator, "1.28.0", Some(27389), None), + /// Allows `#[repr(transparent)]` attribute on newtype structs. + (accepted, repr_transparent, "1.28.0", Some(43036), None), + /// Allows procedural macros in `proc-macro` crates. + (accepted, proc_macro, "1.29.0", Some(38356), None), + /// Allows `foo.rs` as an alternative to `foo/mod.rs`. + (accepted, non_modrs_mods, "1.30.0", Some(44660), None), + /// Allows use of the `:vis` macro fragment specifier + (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), + /// Allows importing and reexporting macros with `use`, + /// enables macro modularization in general. + (accepted, use_extern_macros, "1.30.0", Some(35896), None), + /// Allows keywords to be escaped for use as identifiers. + (accepted, raw_identifiers, "1.30.0", Some(48589), None), + /// Allows attributes scoped to tools. + (accepted, tool_attributes, "1.30.0", Some(44690), None), + /// Allows multi-segment paths in attributes and derives. + (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), + /// Allows all literals in attribute lists and values of key-value pairs. + (accepted, attr_literals, "1.30.0", Some(34981), None), + /// Allows inferring outlives requirements (RFC 2093). + (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), + /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. + /// This defines the behavior of panics. + (accepted, panic_handler, "1.30.0", Some(44489), None), + /// Allows `#[used]` to preserve symbols (see llvm.used). + (accepted, used, "1.30.0", Some(40289), None), + /// Allows `crate` in paths. + (accepted, crate_in_paths, "1.30.0", Some(45477), None), + /// Allows resolving absolute paths as paths from other crates. + (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), + /// Allows access to crate names passed via `--extern` through prelude. + (accepted, extern_prelude, "1.30.0", Some(44660), None), + /// Allows parentheses in patterns. + (accepted, pattern_parentheses, "1.31.0", Some(51087), None), + /// Allows the definition of `const fn` functions. + (accepted, min_const_fn, "1.31.0", Some(53555), None), + /// Allows scoped lints. + (accepted, tool_lints, "1.31.0", Some(44690), None), + /// Allows lifetime elision in `impl` headers. For example: + /// + `impl Iterator for &mut Iterator` + /// + `impl Debug for Foo<'_>` + (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), + /// Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + /// Allows use of `?` as the Kleene "at most one" operator in macros. + (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), + /// Allows `Self` struct constructor (RFC 2302). + (accepted, self_struct_ctor, "1.32.0", Some(51994), None), + /// Allows `Self` in type definitions (RFC 2300). + (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + /// Allows `use x::y;` to search `x` in the current scope. + (accepted, uniform_paths, "1.32.0", Some(53130), None), + /// Allows integer match exhaustiveness checking (RFC 2591). + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + /// Allows `use path as _;` and `extern crate c as _;`. + (accepted, underscore_imports, "1.33.0", Some(48216), None), + /// Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), + /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). + (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), + /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), + /// Allows let bindings, assignments and destructuring in `const` functions and constants. + /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used + /// at the same time as let bindings. + (accepted, const_let, "1.33.0", Some(48821), None), + /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. + (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), + /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. + (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), + /// Allows `cfg(target_vendor = "...")`. + (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), + /// Allows `extern crate self as foo;`. + /// This puts local crate root into extern prelude under name `foo`. + (accepted, extern_crate_self, "1.34.0", Some(56409), None), + /// Allows arbitrary delimited token streams in non-macro attributes. + (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), + /// Allows paths to enum variants on type aliases including `Self`. + (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), + /// Allows using `#[repr(align(X))]` on enums with equivalent semantics + /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. + (accepted, repr_align_enum, "1.37.0", Some(57996), None), + /// Allows `const _: TYPE = VALUE`. + (accepted, underscore_const_names, "1.37.0", Some(54912), None), + /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. + (accepted, async_await, "1.39.0", Some(50547), None), + /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. + (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), + /// Allows attributes in formal function parameters. + (accepted, param_attrs, "1.39.0", Some(60406), None), + + // ------------------------------------------------------------------------- + // feature-group-end: accepted features + // ------------------------------------------------------------------------- +); diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs new file mode 100644 index 0000000000..38c16dbac6 --- /dev/null +++ b/src/libsyntax/feature_gate/active.rs @@ -0,0 +1,539 @@ +//! List of the active feature gates. + +use super::{State, Feature}; + +use crate::edition::Edition; +use crate::symbol::{Symbol, sym}; + +use syntax_pos::Span; + +macro_rules! set { + ($field: ident) => {{ + fn f(features: &mut Features, _: Span) { + features.$field = true; + } + f as fn(&mut Features, Span) + }} +} + +macro_rules! declare_features { + ($( + $(#[doc = $doc:tt])* (active, $feature:ident, $ver:expr, $issue:expr, $edition:expr), + )+) => { + /// Represents active features that are currently being implemented or + /// currently being considered for addition/removal. + pub const ACTIVE_FEATURES: + &[Feature] = + &[$( + // (sym::$feature, $ver, $issue, $edition, set!($feature)) + Feature { + state: State::Active { set: set!($feature) }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: $edition, + description: concat!($($doc,)*), + } + ),+]; + + /// A set of features to be used by later passes. + #[derive(Clone)] + pub struct Features { + /// `#![feature]` attrs for language features, for error reporting. + pub declared_lang_features: Vec<(Symbol, Span, Option)>, + /// `#![feature]` attrs for non-language (library) features. + pub declared_lib_features: Vec<(Symbol, Span)>, + $( + $(#[doc = $doc])* + pub $feature: bool + ),+ + } + + impl Features { + pub fn new() -> Features { + Features { + declared_lang_features: Vec::new(), + declared_lib_features: Vec::new(), + $($feature: false),+ + } + } + + pub fn walk_feature_fields(&self, mut f: F) + where F: FnMut(&str, bool) + { + $(f(stringify!($feature), self.$feature);)+ + } + } + }; +} + +impl Feature { + /// Sets this feature in `Features`. Panics if called on a non-active feature. + pub fn set(&self, features: &mut Features, span: Span) { + match self.state { + State::Active { set } => set(features, span), + _ => panic!("called `set` on feature `{}` which is not `active`", self.name) + } + } +} + +// If you change this, please modify `src/doc/unstable-book` as well. +// +// Don't ever remove anything from this list; move them to `removed.rs`. +// +// The version numbers here correspond to the version in which the current status +// was set. This is most important for knowing when a particular feature became +// stable (active). +// +// Note that the features are grouped into internal/user-facing and then +// sorted by version inside those groups. This is enforced with tidy. +// +// N.B., `tools/tidy/src/features.rs` parses this information directly out of the +// source, so take care when modifying it. + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: internal feature gates + // ------------------------------------------------------------------------- + + // no-tracking-issue-start + + /// Allows using compiler's own crates. + (active, rustc_private, "1.0.0", Some(27812), None), + + /// Allows using the `rust-intrinsic`'s "ABI". + (active, intrinsics, "1.0.0", None, None), + + /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. + (active, lang_items, "1.0.0", None, None), + + /// Allows using the `#[stable]` and `#[unstable]` attributes. + (active, staged_api, "1.0.0", None, None), + + /// Allows using `#[allow_internal_unstable]`. This is an + /// attribute on `macro_rules!` and can't use the attribute handling + /// below (it has to be checked before expansion possibly makes + /// macros disappear). + (active, allow_internal_unstable, "1.0.0", None, None), + + /// Allows using `#[allow_internal_unsafe]`. This is an + /// attribute on `macro_rules!` and can't use the attribute handling + /// below (it has to be checked before expansion possibly makes + /// macros disappear). + (active, allow_internal_unsafe, "1.0.0", None, None), + + /// Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which + /// lets a function to be `const` when opted into with `#![feature(foo)]`. + (active, rustc_const_unstable, "1.0.0", None, None), + + /// no-tracking-issue-end + + /// Allows using `#[link_name="llvm.*"]`. + (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + + /// Allows using `rustc_*` attributes (RFC 572). + (active, rustc_attrs, "1.0.0", Some(29642), None), + + /// Allows using `#[on_unimplemented(..)]` on traits. + (active, on_unimplemented, "1.0.0", Some(29628), None), + + /// Allows using the `box $expr` syntax. + (active, box_syntax, "1.0.0", Some(49733), None), + + /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. + (active, main, "1.0.0", Some(29634), None), + + /// Allows using `#[start]` on a function indicating that it is the program entrypoint. + (active, start, "1.0.0", Some(29633), None), + + /// Allows using the `#[fundamental]` attribute. + (active, fundamental, "1.0.0", Some(29635), None), + + /// Allows using the `rust-call` ABI. + (active, unboxed_closures, "1.0.0", Some(29625), None), + + /// Allows using the `#[linkage = ".."]` attribute. + (active, linkage, "1.0.0", Some(29603), None), + + /// Allows features specific to OIBIT (auto traits). + (active, optin_builtin_traits, "1.0.0", Some(13231), None), + + /// Allows using `box` in patterns (RFC 469). + (active, box_patterns, "1.0.0", Some(29641), None), + + // no-tracking-issue-start + + /// Allows using `#[prelude_import]` on glob `use` items. + (active, prelude_import, "1.2.0", None, None), + + // no-tracking-issue-end + + // no-tracking-issue-start + + /// Allows using `#[omit_gdb_pretty_printer_section]`. + (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), + + /// Allows using the `vectorcall` ABI. + (active, abi_vectorcall, "1.7.0", None, None), + + // no-tracking-issue-end + + /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. + (active, structural_match, "1.8.0", Some(31434), None), + + /// Allows using the `may_dangle` attribute (RFC 1327). + (active, dropck_eyepatch, "1.10.0", Some(34761), None), + + /// Allows using the `#![panic_runtime]` attribute. + (active, panic_runtime, "1.10.0", Some(32837), None), + + /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + (active, needs_panic_runtime, "1.10.0", Some(32837), None), + + // no-tracking-issue-start + + /// Allows identifying the `compiler_builtins` crate. + (active, compiler_builtins, "1.13.0", None, None), + + /// Allows using the `unadjusted` ABI; perma-unstable. + (active, abi_unadjusted, "1.16.0", None, None), + + /// Allows identifying crates that contain sanitizer runtimes. + (active, sanitizer_runtime, "1.17.0", None, None), + + /// Used to identify crates that contain the profiler runtime. + (active, profiler_runtime, "1.18.0", None, None), + + /// Allows using the `thiscall` ABI. + (active, abi_thiscall, "1.19.0", None, None), + + /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. + (active, allocator_internals, "1.20.0", None, None), + + // no-tracking-issue-end + + /// Added for testing E0705; perma-unstable. + (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), + + // ------------------------------------------------------------------------- + // feature-group-end: internal feature gates + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: actual feature gates (target features) + // ------------------------------------------------------------------------- + + // FIXME: Document these and merge with the list below. + + // Unstable `#[target_feature]` directives. + (active, arm_target_feature, "1.27.0", Some(44839), None), + (active, aarch64_target_feature, "1.27.0", Some(44839), None), + (active, hexagon_target_feature, "1.27.0", Some(44839), None), + (active, powerpc_target_feature, "1.27.0", Some(44839), None), + (active, mips_target_feature, "1.27.0", Some(44839), None), + (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, mmx_target_feature, "1.27.0", Some(44839), None), + (active, sse4a_target_feature, "1.27.0", Some(44839), None), + (active, tbm_target_feature, "1.27.0", Some(44839), None), + (active, wasm_target_feature, "1.30.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), + (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, rtm_target_feature, "1.35.0", Some(44839), None), + (active, f16c_target_feature, "1.36.0", Some(44839), None), + + // ------------------------------------------------------------------------- + // feature-group-end: actual feature gates (target features) + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: actual feature gates + // ------------------------------------------------------------------------- + + /// Allows using the `#[link_args]` attribute. + (active, link_args, "1.0.0", Some(29596), None), + + /// Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "1.0.0", Some(55467), None), + + /// Allows using `#[plugin_registrar]` on functions. + (active, plugin_registrar, "1.0.0", Some(29597), None), + + /// Allows using `#![plugin(myplugin)]`. + (active, plugin, "1.0.0", Some(29597), None), + + /// Allows using `#[thread_local]` on `static` items. + (active, thread_local, "1.0.0", Some(29594), None), + + /// Allows the use of SIMD types in functions declared in `extern` blocks. + (active, simd_ffi, "1.0.0", Some(27731), None), + + /// Allows using custom attributes (RFC 572). + (active, custom_attribute, "1.0.0", Some(29642), None), + + /// Allows using non lexical lifetimes (RFC 2094). + (active, nll, "1.0.0", Some(43234), None), + + /// Allows using slice patterns. + (active, slice_patterns, "1.0.0", Some(62254), None), + + /// Allows the definition of `const` functions with some advanced features. + (active, const_fn, "1.2.0", Some(57563), None), + + /// Allows associated type defaults. + (active, associated_type_defaults, "1.2.0", Some(29661), None), + + /// Allows `#![no_core]`. + (active, no_core, "1.3.0", Some(29639), None), + + /// Allows default type parameters to influence type inference. + (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), + + /// Allows `repr(simd)` and importing the various simd intrinsics. + (active, repr_simd, "1.4.0", Some(27731), None), + + /// Allows `extern "platform-intrinsic" { ... }`. + (active, platform_intrinsics, "1.4.0", Some(27731), None), + + /// Allows `#[unwind(..)]`. + /// + /// Permits specifying whether a function should permit unwinding or abort on unwind. + (active, unwind_attributes, "1.4.0", Some(58760), None), + + /// Allows `#[no_debug]`. + (active, no_debug, "1.5.0", Some(29721), None), + + /// Allows attributes on expressions and non-item statements. + (active, stmt_expr_attributes, "1.6.0", Some(15701), None), + + /// Allows the use of type ascription in expressions. + (active, type_ascription, "1.6.0", Some(23416), None), + + /// Allows `cfg(target_thread_local)`. + (active, cfg_target_thread_local, "1.7.0", Some(29594), None), + + /// Allows specialization of implementations (RFC 1210). + (active, specialization, "1.7.0", Some(31844), None), + + /// Allows using `#[naked]` on functions. + (active, naked_functions, "1.9.0", Some(32408), None), + + /// Allows `cfg(target_has_atomic = "...")`. + (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), + + /// Allows `X..Y` patterns. + (active, exclusive_range_pattern, "1.11.0", Some(37854), None), + + /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + (active, never_type, "1.13.0", Some(35121), None), + + /// Allows exhaustive pattern matching on types that contain uninhabited types. + (active, exhaustive_patterns, "1.13.0", Some(51085), None), + + /// Allows untagged unions `union U { ... }`. + (active, untagged_unions, "1.13.0", Some(32836), None), + + /// Allows `#[link(..., cfg(..))]`. + (active, link_cfg, "1.14.0", Some(37406), None), + + /// Allows `extern "ptx-*" fn()`. + (active, abi_ptx, "1.15.0", Some(38788), None), + + /// Allows the `#[repr(i128)]` attribute for enums. + (active, repr128, "1.16.0", Some(35118), None), + + /// Allows `#[link(kind="static-nobundle"...)]`. + (active, static_nobundle, "1.16.0", Some(37403), None), + + /// Allows `extern "msp430-interrupt" fn()`. + (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), + + /// Allows declarative macros 2.0 (`macro`). + (active, decl_macro, "1.17.0", Some(39412), None), + + /// Allows `extern "x86-interrupt" fn()`. + (active, abi_x86_interrupt, "1.17.0", Some(40180), None), + + /// Allows overlapping impls of marker traits. + (active, overlapping_marker_traits, "1.18.0", Some(29864), None), + + /// Allows a test to fail without failing the whole suite. + (active, allow_fail, "1.19.0", Some(46488), None), + + /// Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), + + /// Allows defining generators. + (active, generators, "1.21.0", Some(43122), None), + + /// Allows `#[doc(cfg(...))]`. + (active, doc_cfg, "1.21.0", Some(43781), None), + + /// Allows `#[doc(masked)]`. + (active, doc_masked, "1.21.0", Some(44027), None), + + /// Allows `#[doc(spotlight)]`. + (active, doc_spotlight, "1.22.0", Some(45040), None), + + /// Allows `#[doc(include = "some-file")]`. + (active, external_doc, "1.22.0", Some(44732), None), + + /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). + (active, non_exhaustive, "1.22.0", Some(44109), None), + + /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. + (active, crate_visibility_modifier, "1.23.0", Some(53120), None), + + /// Allows defining `extern type`s. + (active, extern_types, "1.23.0", Some(43467), None), + + /// Allows trait methods with arbitrary self types. + (active, arbitrary_self_types, "1.23.0", Some(44874), None), + + /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). + (active, in_band_lifetimes, "1.23.0", Some(44524), None), + + /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). + (active, generic_associated_types, "1.23.0", Some(44265), None), + + /// Allows defining `trait X = A + B;` alias items. + (active, trait_alias, "1.24.0", Some(41517), None), + + /// Allows infering `'static` outlives requirements (RFC 2093). + (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), + + /// Allows macro invocations in `extern {}` blocks. + (active, macros_in_extern, "1.27.0", Some(49476), None), + + /// Allows accessing fields of unions inside `const` functions. + (active, const_fn_union, "1.27.0", Some(51909), None), + + /// Allows casting raw pointers to `usize` during const eval. + (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), + + /// Allows dereferencing raw pointers during const eval. + (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), + + /// Allows comparing raw pointers during const eval. + (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), + + /// Allows `#[doc(alias = "...")]`. + (active, doc_alias, "1.27.0", Some(50146), None), + + /// Allows inconsistent bounds in where clauses. + (active, trivial_bounds, "1.28.0", Some(48214), None), + + /// Allows `'a: { break 'a; }`. + (active, label_break_value, "1.28.0", Some(48594), None), + + /// Allows using `#[doc(keyword = "...")]`. + (active, doc_keyword, "1.28.0", Some(51315), None), + + /// Allows reinterpretation of the bits of a value of one type as another + /// type during const eval. + (active, const_transmute, "1.29.0", Some(53605), None), + + /// Allows using `try {...}` expressions. + (active, try_blocks, "1.29.0", Some(31436), None), + + /// Allows defining an `#[alloc_error_handler]`. + (active, alloc_error_handler, "1.29.0", Some(51540), None), + + /// Allows using the `amdgpu-kernel` ABI. + (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), + + /// Allows panicking during const eval (producing compile-time errors). + (active, const_panic, "1.30.0", Some(51999), None), + + /// Allows `#[marker]` on certain traits allowing overlapping implementations. + (active, marker_trait_attr, "1.30.0", Some(29864), None), + + /// Allows macro invocations on modules expressions and statements and + /// procedural macros to expand to non-items. + (active, proc_macro_hygiene, "1.30.0", Some(54727), None), + + /// Allows unsized rvalues at arguments and parameters. + (active, unsized_locals, "1.30.0", Some(48055), None), + + /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. + (active, custom_test_frameworks, "1.30.0", Some(50297), None), + + /// Allows non-builtin attributes in inner attribute position. + (active, custom_inner_attributes, "1.30.0", Some(54726), None), + + /// Allows `impl Trait` in bindings (`let`, `const`, `static`). + (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), + + /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. + (active, lint_reasons, "1.31.0", Some(54503), None), + + /// Allows exhaustive integer pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), + + /// Allows relaxing the coherence rules such that + /// `impl ForeignTrait for ForeignType` is permitted. + (active, re_rebalance_coherence, "1.32.0", Some(55437), None), + + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (active, ffi_returns_twice, "1.34.0", Some(58314), None), + + /// Allows const generic types (e.g. `struct Foo(...);`). + (active, const_generics, "1.34.0", Some(44580), None), + + /// Allows using `#[optimize(X)]`. + (active, optimize_attribute, "1.34.0", Some(54882), None), + + /// Allows using C-variadics. + (active, c_variadic, "1.34.0", Some(44930), None), + + /// Allows the user of associated type bounds. + (active, associated_type_bounds, "1.34.0", Some(52662), None), + + /// Allows calling constructor functions in `const fn`. + (active, const_constructor, "1.37.0", Some(61456), None), + + /// Allows `if/while p && let q = r && ...` chains. + (active, let_chains, "1.37.0", Some(53667), None), + + /// Allows #[repr(transparent)] on enums (RFC 2645). + (active, transparent_enums, "1.37.0", Some(60405), None), + + /// Allows #[repr(transparent)] on unions (RFC 2645). + (active, transparent_unions, "1.37.0", Some(60405), None), + + /// Allows explicit discriminants on non-unit enum variants. + (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), + + /// Allows `impl Trait` with multiple unrelated lifetimes. + (active, member_constraints, "1.37.0", Some(61977), None), + + /// Allows `async || body` closures. + (active, async_closure, "1.37.0", Some(62290), None), + + /// Allows the use of `#[cfg(doctest)]`; set when rustdoc is collecting doctests. + (active, cfg_doctest, "1.37.0", Some(62210), None), + + /// Allows `[x; N]` where `x` is a constant (RFC 2203). + (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), + + /// Allows `impl Trait` to be used inside type aliases (RFC 2515). + (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + + /// Allows the use of or-patterns (e.g., `0 | 1`). + (active, or_patterns, "1.38.0", Some(54883), None), + + // ------------------------------------------------------------------------- + // feature-group-end: actual feature gates + // ------------------------------------------------------------------------- +); + +/// Some features are known to be incomplete and using them is likely to have +/// unanticipated results, such as compiler crashes. We warn the user about these +/// to alert them. +pub const INCOMPLETE_FEATURES: &[Symbol] = &[ + sym::impl_trait_in_bindings, + sym::generic_associated_types, + sym::const_generics, + sym::or_patterns, + sym::let_chains, +]; diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs new file mode 100644 index 0000000000..b6e13200f3 --- /dev/null +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -0,0 +1,574 @@ +//! Built-in attributes and `cfg` flag gating. + +use AttributeType::*; +use AttributeGate::*; + +use super::check::{emit_feature_err, GateIssue}; +use super::check::{Stability, EXPLAIN_ALLOW_INTERNAL_UNSAFE, EXPLAIN_ALLOW_INTERNAL_UNSTABLE}; +use super::active::Features; + +use crate::ast; +use crate::attr::AttributeTemplate; +use crate::symbol::{Symbol, sym}; +use crate::parse::ParseSess; + +use syntax_pos::Span; +use rustc_data_structures::fx::FxHashMap; +use lazy_static::lazy_static; + +type GateFn = fn(&Features) -> bool; + +macro_rules! cfg_fn { + ($field: ident) => { + (|features| { features.$field }) as GateFn + } +} + +/// `cfg(...)`'s that are feature gated. +const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[ + // (name in cfg, feature, function to check if the feature is enabled) + (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), + (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), + (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), + (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), +]; + +#[derive(Debug)] +pub struct GatedCfg { + span: Span, + index: usize, +} + +impl GatedCfg { + pub fn gate(cfg: &ast::MetaItem) -> Option { + GATED_CFGS.iter() + .position(|info| cfg.check_name(info.0)) + .map(|idx| { + GatedCfg { + span: cfg.span, + index: idx + } + }) + } + + pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { + let (cfg, feature, has_feature) = GATED_CFGS[self.index]; + if !has_feature(features) && !self.span.allows_unstable(feature) { + let explain = format!("`cfg({})` is experimental and subject to change", cfg); + emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); + } + } +} + +// If you change this, please modify `src/doc/unstable-book` as well. You must +// move that documentation into the relevant place in the other docs, and +// remove the chapter on the flag. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum AttributeType { + /// Normal, builtin attribute that is consumed + /// by the compiler before the unused_attribute check + Normal, + + /// Builtin attribute that may not be consumed by the compiler + /// before the unused_attribute check. These attributes + /// will be ignored by the unused_attribute lint + Whitelisted, + + /// Builtin attribute that is only allowed at the crate level + CrateLevel, +} + +#[derive(Clone, Copy)] +pub enum AttributeGate { + /// Is gated by a given feature gate, reason + /// and function to check if enabled + Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), + + /// Ungated attribute, can be used on all release channels + Ungated, +} + +// fn() is not Debug +impl std::fmt::Debug for AttributeGate { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + Self::Gated(ref stab, name, expl, _) => + write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), + Self::Ungated => write!(fmt, "Ungated") + } + } +} + +impl AttributeGate { + fn is_deprecated(&self) -> bool { + match *self { + Self::Gated(Stability::Deprecated(_, _), ..) => true, + _ => false, + } + } +} + +/// A convenience macro for constructing attribute templates. +/// E.g., `template!(Word, List: "description")` means that the attribute +/// supports forms `#[attr]` and `#[attr(description)]`. +macro_rules! template { + (Word) => { template!(@ true, None, None) }; + (List: $descr: expr) => { template!(@ false, Some($descr), None) }; + (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; + (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; + (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; + (List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ false, Some($descr1), Some($descr2)) + }; + (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ true, Some($descr1), Some($descr2)) + }; + (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { + word: $word, list: $list, name_value_str: $name_value_str + } }; +} + +macro_rules! ungated { + ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Ungated) + }; +} + +macro_rules! gated { + ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate))) + }; + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr))) + }; +} + +macro_rules! rustc_attr { + (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { + rustc_attr!( + $attr, $typ, $tpl, + concat!("the `#[", stringify!($attr), "]` attribute is just used for rustc unit tests \ + and will never be stable", + ), + ) + }; + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, + Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs))) + }; +} + +macro_rules! experimental { + ($attr:ident) => { + concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") + } +} + +const IMPL_DETAIL: &str = "internal implementation detail"; +const INTERAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; + +pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); + +/// Attributes that have a special meaning to rustc or rustdoc. +pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ + // ========================================================================== + // Stable attributes: + // ========================================================================== + + // Condtional compilation: + ungated!(cfg, Normal, template!(List: "predicate")), + ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + + // Testing: + ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!( + should_panic, Normal, + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), + ), + // FIXME(Centril): This can be used on stable but shouldn't. + ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), + + // Macros: + ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), + ungated!(automatically_derived, Normal, template!(Word)), + // FIXME(#14407) + ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), + ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. + ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), + ungated!(proc_macro, Normal, template!(Word)), + ungated!( + proc_macro_derive, Normal, + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + ), + ungated!(proc_macro_attribute, Normal, template!(Word)), + + // Lints: + ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(must_use, Whitelisted, template!(Word, NameValueStr: "reason")), + // FIXME(#14407) + ungated!( + deprecated, Normal, + template!( + Word, + List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, + NameValueStr: "reason" + ), + ), + + // Crate properties: + ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), + ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), + ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), + + // ABI, linking, symbols, and FFI + ungated!( + link, Whitelisted, + template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...""#), + ), + ungated!(link_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(no_link, Normal, template!(Word)), + ungated!(repr, Normal, template!(List: "C, packed, ...")), + ungated!(export_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(link_section, Whitelisted, template!(NameValueStr: "name")), + ungated!(no_mangle, Whitelisted, template!(Word)), + ungated!(used, Whitelisted, template!(Word)), + + // Limits: + ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), + ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + + // Entry point: + ungated!(main, Normal, template!(Word)), + ungated!(start, Normal, template!(Word)), + ungated!(no_start, CrateLevel, template!(Word)), + ungated!(no_main, CrateLevel, template!(Word)), + + // Modules, prelude, and resolution: + ungated!(path, Normal, template!(NameValueStr: "file")), + ungated!(no_std, CrateLevel, template!(Word)), + ungated!(no_implicit_prelude, Normal, template!(Word)), + + // Runtime + ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), + ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 + + // Code generation: + ungated!(inline, Whitelisted, template!(Word, List: "always|never")), + ungated!(cold, Whitelisted, template!(Word)), + ungated!(no_builtins, Whitelisted, template!(Word)), + ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + + // FIXME: #14408 whitelist docs since rustdoc looks at them + ungated!(doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string")), + + // ========================================================================== + // Unstable attributes: + // ========================================================================== + + // Linking: + gated!(naked, Whitelisted, template!(Word), naked_functions, experimental!(naked)), + gated!( + link_args, Normal, template!(NameValueStr: "args"), + "the `link_args` attribute is experimental and not portable across platforms, \ + it is recommended to use `#[link(name = \"foo\")] instead", + ), + + // Plugins: + ungated!(plugin_registrar, Normal, template!(Word)), + gated!( + plugin, CrateLevel, template!(List: "name|name(args)"), + "compiler plugins are experimental and possibly buggy", + ), + + // Testing: + gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), + gated!( + test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, + "custom test frameworks are an unstable feature", + ), + + // RFC #2008 + gated!(non_exhaustive, Whitelisted, template!(Word), experimental!(non_exhaustive)), + // RFC #1268 + gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), + gated!( + thread_local, Whitelisted, template!(Word), + "`#[thread_local]` is an experimental feature, and does not currently handle destructors", + ), + gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), + // RFC 2412 + gated!( + optimize, Whitelisted, template!(List: "size|speed"), optimize_attribute, + experimental!(optimize), + ), + + gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), + + // ========================================================================== + // Internal attributes: Stability, deprecation, and unsafe: + // ========================================================================== + + ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), + // FIXME(#14407) -- only looked at on-demand so we can't + // guarantee they'll have already been checked. + ungated!( + rustc_deprecated, Whitelisted, + template!(List: r#"since = "version", reason = "...""#) + ), + // FIXME(#14407) + ungated!(stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#)), + // FIXME(#14407) + ungated!( + unstable, Whitelisted, + template!(List: r#"feature = "name", reason = "...", issue = "N""#), + ), + gated!( + rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + "the `#[rustc_const_unstable]` attribute is an internal feature", + ), + gated!( + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + EXPLAIN_ALLOW_INTERNAL_UNSTABLE, + ), + gated!(allow_internal_unsafe, Normal, template!(Word), EXPLAIN_ALLOW_INTERNAL_UNSAFE), + + // ========================================================================== + // Internal attributes: Type system related: + // ========================================================================== + + gated!(fundamental, Whitelisted, template!(Word), experimental!(fundamental)), + gated!( + // RFC #1445. + structural_match, Whitelisted, template!(Word), + "the semantics of constant patterns is not yet settled", + ), + gated!( + may_dangle, Normal, template!(Word), dropck_eyepatch, + "`may_dangle` has unstable semantics and may be removed in the future", + ), + + // ========================================================================== + // Internal attributes: Runtime related: + // ========================================================================== + + rustc_attr!(rustc_allocator, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allocator_nounwind, Whitelisted, template!(Word), IMPL_DETAIL), + gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), + gated!( + default_lib_allocator, Whitelisted, template!(Word), allocator_internals, + experimental!(default_lib_allocator), + ), + gated!( + needs_allocator, Normal, template!(Word), allocator_internals, + experimental!(needs_allocator), + ), + gated!(panic_runtime, Whitelisted, template!(Word), experimental!(panic_runtime)), + gated!(needs_panic_runtime, Whitelisted, template!(Word), experimental!(needs_panic_runtime)), + gated!( + unwind, Whitelisted, template!(List: "allowed|aborts"), unwind_attributes, + experimental!(unwind), + ), + gated!( + compiler_builtins, Whitelisted, template!(Word), + "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ + which contains compiler-rt intrinsics and will never be stable", + ), + gated!( + sanitizer_runtime, Whitelisted, template!(Word), + "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \ + of a sanitizer and will never be stable", + ), + gated!( + profiler_runtime, Whitelisted, template!(Word), + "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ + which contains the profiler runtime and will never be stable", + ), + + // ========================================================================== + // Internal attributes, Linkage: + // ========================================================================== + + gated!( + linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), + "the `linkage` attribute is experimental and not portable across platforms", + ), + rustc_attr!(rustc_std_internal_symbol, Whitelisted, template!(Word), INTERAL_UNSTABLE), + + // ========================================================================== + // Internal attributes, Macro related: + // ========================================================================== + + rustc_attr!(rustc_builtin_macro, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERAL_UNSTABLE), + rustc_attr!( + rustc_macro_transparency, Whitelisted, + template!(NameValueStr: "transparent|semitransparent|opaque"), + "used internally for testing macro hygiene", + ), + + // ========================================================================== + // Internal attributes, Diagnostics related: + // ========================================================================== + + gated!( + rustc_on_unimplemented, Whitelisted, + template!( + List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, + NameValueStr: "message" + ), + on_unimplemented, + experimental!(rustc_on_unimplemented), + ), + // Whitelists "identity-like" conversion methods to suggest on type mismatch. + rustc_attr!(rustc_conversion_suggestion, Whitelisted, template!(Word), INTERAL_UNSTABLE), + + // ========================================================================== + // Internal attributes, Const related: + // ========================================================================== + + rustc_attr!(rustc_promotable, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allow_const_fn_ptr, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_args_required_const, Whitelisted, template!(List: "N"), INTERAL_UNSTABLE), + + // ========================================================================== + // Internal attributes, Layout related: + // ========================================================================== + + rustc_attr!( + rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + rustc_attr!( + rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + rustc_attr!( + rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), + "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + + // ========================================================================== + // Internal attributes, Misc: + // ========================================================================== + + gated!( + lang, Normal, template!(NameValueStr: "name"), lang_items, + "language items are subject to change", + ), + ( + sym::rustc_diagnostic_item, + Normal, + template!(NameValueStr: "name"), + Gated( + Stability::Unstable, + sym::rustc_attrs, + "diagnostic items compiler internal support for linting", + cfg_fn!(rustc_attrs), + ), + ), + ( + sym::no_debug, Whitelisted, template!(Word), + Gated( + Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), + sym::no_debug, + "the `#[no_debug]` attribute was an experimental feature that has been \ + deprecated due to lack of demand", + cfg_fn!(no_debug) + ) + ), + gated!( + // Used in resolve: + prelude_import, Whitelisted, template!(Word), + "`#[prelude_import]` is for use by rustc only", + ), + gated!( + rustc_paren_sugar, Normal, template!(Word), unboxed_closures, + "unboxed_closures are still evolving", + ), + rustc_attr!( + rustc_inherit_overflow_checks, Whitelisted, template!(Word), + "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ + overflow checking behavior of several libcore functions that are inlined \ + across crates and will never be stable", + ), + rustc_attr!( + rustc_test_marker, Normal, template!(Word), + "the `#[rustc_test_marker]` attribute is used internally to track tests", + ), + + // ========================================================================== + // Internal attributes, Testing: + // ========================================================================== + + rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), + rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), + rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), + rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), + rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")), + rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")), + rustc_attr!( + TEST, rustc_dirty, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + ), + rustc_attr!( + TEST, rustc_clean, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + ), + rustc_attr!( + TEST, rustc_partition_reused, Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), + ), + rustc_attr!( + TEST, rustc_partition_codegened, Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), + ), + rustc_attr!( + TEST, rustc_expected_cgu_reuse, Whitelisted, + template!(List: r#"cfg = "...", module = "...", kind = "...""#), + ), + rustc_attr!(TEST, rustc_synthetic, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_symbol_name, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_def_path, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_mir, Whitelisted, template!(List: "arg1, arg2, ...")), + rustc_attr!(TEST, rustc_dump_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_object_lifetime_default, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), + gated!( + omit_gdb_pretty_printer_section, Whitelisted, template!(Word), + "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", + ), +]; + +pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { + BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() +} + +pub fn is_builtin_attr_name(name: ast::Name) -> bool { + BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() +} + +pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some() +} + +lazy_static! { + pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap = { + let mut map = FxHashMap::default(); + for attr in BUILTIN_ATTRIBUTES.iter() { + if map.insert(attr.0, attr).is_some() { + panic!("duplicate builtin attribute `{}`", attr.0); + } + } + map + }; +} diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs new file mode 100644 index 0000000000..b50ca1ad1c --- /dev/null +++ b/src/libsyntax/feature_gate/check.rs @@ -0,0 +1,873 @@ +use super::{active::{ACTIVE_FEATURES, Features}, Feature, State as FeatureState}; +use super::accepted::ACCEPTED_FEATURES; +use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; +use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; + +use crate::ast::{ + self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, + PatKind, RangeEnd, +}; +use crate::attr::{self, check_builtin_attribute}; +use crate::source_map::Spanned; +use crate::edition::{ALL_EDITIONS, Edition}; +use crate::visit::{self, FnKind, Visitor}; +use crate::parse::{token, ParseSess}; +use crate::parse::parser::Parser; +use crate::symbol::{Symbol, sym}; +use crate::tokenstream::TokenTree; + +use errors::{Applicability, DiagnosticBuilder, Handler}; +use rustc_data_structures::fx::FxHashMap; +use rustc_target::spec::abi::Abi; +use syntax_pos::{Span, DUMMY_SP, MultiSpan}; +use log::debug; + +use std::env; + +#[derive(Copy, Clone, Debug)] +pub enum Stability { + Unstable, + // First argument is tracking issue link; second argument is an optional + // help message, which defaults to "remove this attribute" + Deprecated(&'static str, Option<&'static str>), +} + +macro_rules! gate_feature_fn { + ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ + let (cx, has_feature, span, + name, explain, level) = (&*$cx, $has_feature, $span, $name, $explain, $level); + let has_feature: bool = has_feature(&$cx.features); + debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); + if !has_feature && !span.allows_unstable($name) { + leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) + .emit(); + } + }} +} + +macro_rules! gate_feature { + ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + sym::$feature, $explain, GateStrength::Hard) + }; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + sym::$feature, $explain, $level) + }; +} + +crate fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { + PostExpansionVisitor { parse_sess, features }.visit_attribute(attr) +} + +fn find_lang_feature_issue(feature: Symbol) -> Option { + if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) { + // FIXME (#28244): enforce that active features have issue numbers + // assert!(info.issue.is_some()) + info.issue + } else { + // search in Accepted, Removed, or Stable Removed features + let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) + .find(|t| t.name == feature); + match found { + Some(&Feature { issue, .. }) => issue, + None => panic!("Feature `{}` is not declared anywhere", feature), + } + } +} + +pub enum GateIssue { + Language, + Library(Option) +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum GateStrength { + /// A hard error. (Most feature gates should use this.) + Hard, + /// Only a warning. (Use this only as backwards-compatibility demands.) + Soft, +} + +pub fn emit_feature_err( + sess: &ParseSess, + feature: Symbol, + span: Span, + issue: GateIssue, + explain: &str, +) { + feature_err(sess, feature, span, issue, explain).emit(); +} + +pub fn feature_err<'a, S: Into>( + sess: &'a ParseSess, + feature: Symbol, + span: S, + issue: GateIssue, + explain: &str, +) -> DiagnosticBuilder<'a> { + leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) +} + +fn leveled_feature_err<'a, S: Into>( + sess: &'a ParseSess, + feature: Symbol, + span: S, + issue: GateIssue, + explain: &str, + level: GateStrength, +) -> DiagnosticBuilder<'a> { + let diag = &sess.span_diagnostic; + + let issue = match issue { + GateIssue::Language => find_lang_feature_issue(feature), + GateIssue::Library(lib) => lib, + }; + + let mut err = match level { + GateStrength::Hard => { + diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658)) + } + GateStrength::Soft => diag.struct_span_warn(span, explain), + }; + + match issue { + None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility + Some(n) => { + err.note(&format!( + "for more information, see https://github.com/rust-lang/rust/issues/{}", + n, + )); + } + } + + // #23973: do not suggest `#![feature(...)]` if we are in beta/stable + if sess.unstable_features.is_nightly_build() { + err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); + } + + // If we're on stable and only emitting a "soft" warning, add a note to + // clarify that the feature isn't "on" (rather than being on but + // warning-worthy). + if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { + err.help("a nightly build of the compiler is required to enable this feature"); + } + + err + +} + +const EXPLAIN_BOX_SYNTAX: &str = + "box expression syntax is experimental; you can call `Box::new` instead"; + +pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = + "attributes on expressions are experimental"; + +pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = + "allow_internal_unstable side-steps feature gating and stability checks"; +pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = + "allow_internal_unsafe side-steps the unsafe_code lint"; + +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = + "unsized tuple coercion is not stable enough for use and is subject to change"; + +struct PostExpansionVisitor<'a> { + parse_sess: &'a ParseSess, + features: &'a Features, +} + +macro_rules! gate_feature_post { + ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ + let (cx, span) = ($cx, $span); + if !span.allows_unstable(sym::$feature) { + gate_feature!(cx, $feature, span, $explain) + } + }}; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ + let (cx, span) = ($cx, $span); + if !span.allows_unstable(sym::$feature) { + gate_feature!(cx, $feature, span, $explain, $level) + } + }} +} + +impl<'a> PostExpansionVisitor<'a> { + fn check_abi(&self, abi: Abi, span: Span) { + match abi { + Abi::RustIntrinsic => { + gate_feature_post!(&self, intrinsics, span, + "intrinsics are subject to change"); + }, + Abi::PlatformIntrinsic => { + gate_feature_post!(&self, platform_intrinsics, span, + "platform intrinsics are experimental and possibly buggy"); + }, + Abi::Vectorcall => { + gate_feature_post!(&self, abi_vectorcall, span, + "vectorcall is experimental and subject to change"); + }, + Abi::Thiscall => { + gate_feature_post!(&self, abi_thiscall, span, + "thiscall is experimental and subject to change"); + }, + Abi::RustCall => { + gate_feature_post!(&self, unboxed_closures, span, + "rust-call ABI is subject to change"); + }, + Abi::PtxKernel => { + gate_feature_post!(&self, abi_ptx, span, + "PTX ABIs are experimental and subject to change"); + }, + Abi::Unadjusted => { + gate_feature_post!(&self, abi_unadjusted, span, + "unadjusted ABI is an implementation detail and perma-unstable"); + }, + Abi::Msp430Interrupt => { + gate_feature_post!(&self, abi_msp430_interrupt, span, + "msp430-interrupt ABI is experimental and subject to change"); + }, + Abi::X86Interrupt => { + gate_feature_post!(&self, abi_x86_interrupt, span, + "x86-interrupt ABI is experimental and subject to change"); + }, + Abi::AmdGpuKernel => { + gate_feature_post!(&self, abi_amdgpu_kernel, span, + "amdgpu-kernel ABI is experimental and subject to change"); + }, + // Stable + Abi::Cdecl | + Abi::Stdcall | + Abi::Fastcall | + Abi::Aapcs | + Abi::Win64 | + Abi::SysV64 | + Abi::Rust | + Abi::C | + Abi::System => {} + } + } +} + +impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { + fn visit_attribute(&mut self, attr: &ast::Attribute) { + let attr_info = + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a); + // Check feature gates for built-in attributes. + if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info { + gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard); + } + // Check input tokens for built-in and key-value attributes. + match attr_info { + // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. + Some((name, _, template, _)) if name != sym::rustc_dummy => + check_builtin_attribute(self.parse_sess, attr, name, template), + _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() { + if token == token::Eq { + // All key-value attributes are restricted to meta-item syntax. + attr.parse_meta(self.parse_sess).map_err(|mut err| err.emit()).ok(); + } + } + } + // Check unstable flavors of the `#[doc]` attribute. + if attr.check_name(sym::doc) { + for nested_meta in attr.meta_item_list().unwrap_or_default() { + macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => { + $(if nested_meta.check_name(sym::$name) { + let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental"); + gate_feature!(self, $feature, attr.span, msg); + })* + }} + + gate_doc!( + include => external_doc + cfg => doc_cfg + masked => doc_masked + spotlight => doc_spotlight + alias => doc_alias + keyword => doc_keyword + ); + } + } + } + + fn visit_name(&mut self, sp: Span, name: ast::Name) { + if !name.as_str().is_ascii() { + gate_feature_post!( + &self, + non_ascii_idents, + self.parse_sess.source_map().def_span(sp), + "non-ascii idents are not fully supported" + ); + } + } + + fn visit_item(&mut self, i: &'a ast::Item) { + match i.node { + ast::ItemKind::ForeignMod(ref foreign_module) => { + self.check_abi(foreign_module.abi, i.span); + } + + ast::ItemKind::Fn(..) => { + if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { + gate_feature_post!(&self, plugin_registrar, i.span, + "compiler plugins are experimental and possibly buggy"); + } + if attr::contains_name(&i.attrs[..], sym::start) { + gate_feature_post!(&self, start, i.span, + "a `#[start]` function is an experimental \ + feature whose signature may change \ + over time"); + } + if attr::contains_name(&i.attrs[..], sym::main) { + gate_feature_post!(&self, main, i.span, + "declaration of a non-standard `#[main]` \ + function may change over time, for now \ + a top-level `fn main()` is required"); + } + } + + ast::ItemKind::Struct(..) => { + for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.check_name(sym::simd) { + gate_feature_post!(&self, repr_simd, attr.span, + "SIMD types are experimental and possibly buggy"); + } + } + } + } + + ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { + for variant in variants { + match (&variant.data, &variant.disr_expr) { + (ast::VariantData::Unit(..), _) => {}, + (_, Some(disr_expr)) => + gate_feature_post!( + &self, + arbitrary_enum_discriminant, + disr_expr.value.span, + "discriminants on non-unit variants are experimental"), + _ => {}, + } + } + + let has_feature = self.features.arbitrary_enum_discriminant; + if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { + Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants); + } + } + + ast::ItemKind::Impl(_, polarity, defaultness, ..) => { + if polarity == ast::ImplPolarity::Negative { + gate_feature_post!(&self, optin_builtin_traits, + i.span, + "negative trait bounds are not yet fully implemented; \ + use marker types for now"); + } + + if let ast::Defaultness::Default = defaultness { + gate_feature_post!(&self, specialization, + i.span, + "specialization is unstable"); + } + } + + ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { + gate_feature_post!(&self, optin_builtin_traits, + i.span, + "auto traits are experimental and possibly buggy"); + } + + ast::ItemKind::TraitAlias(..) => { + gate_feature_post!( + &self, + trait_alias, + i.span, + "trait aliases are experimental" + ); + } + + ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { + let msg = "`macro` is experimental"; + gate_feature_post!(&self, decl_macro, i.span, msg); + } + + ast::ItemKind::OpaqueTy(..) => { + gate_feature_post!( + &self, + type_alias_impl_trait, + i.span, + "`impl Trait` in type aliases is unstable" + ); + } + + _ => {} + } + + visit::walk_item(self, i); + } + + fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) { + match i.node { + ast::ForeignItemKind::Fn(..) | + ast::ForeignItemKind::Static(..) => { + let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); + let links_to_llvm = match link_name { + Some(val) => val.as_str().starts_with("llvm."), + _ => false + }; + if links_to_llvm { + gate_feature_post!(&self, link_llvm_intrinsics, i.span, + "linking to LLVM intrinsics is experimental"); + } + } + ast::ForeignItemKind::Ty => { + gate_feature_post!(&self, extern_types, i.span, + "extern types are experimental"); + } + ast::ForeignItemKind::Macro(..) => {} + } + + visit::walk_foreign_item(self, i) + } + + fn visit_ty(&mut self, ty: &'a ast::Ty) { + match ty.node { + ast::TyKind::BareFn(ref bare_fn_ty) => { + self.check_abi(bare_fn_ty.abi, ty.span); + } + ast::TyKind::Never => { + gate_feature_post!(&self, never_type, ty.span, + "The `!` type is experimental"); + } + _ => {} + } + visit::walk_ty(self, ty) + } + + fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { + if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { + if let ast::TyKind::Never = output_ty.node { + // Do nothing. + } else { + self.visit_ty(output_ty) + } + } + } + + fn visit_expr(&mut self, e: &'a ast::Expr) { + match e.node { + ast::ExprKind::Box(_) => { + gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); + } + ast::ExprKind::Type(..) => { + // To avoid noise about type ascription in common syntax errors, only emit if it + // is the *only* error. + if self.parse_sess.span_diagnostic.err_count() == 0 { + gate_feature_post!(&self, type_ascription, e.span, + "type ascription is experimental"); + } + } + ast::ExprKind::TryBlock(_) => { + gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); + } + ast::ExprKind::Block(_, opt_label) => { + if let Some(label) = opt_label { + gate_feature_post!(&self, label_break_value, label.ident.span, + "labels on blocks are unstable"); + } + } + _ => {} + } + visit::walk_expr(self, e) + } + + fn visit_arm(&mut self, arm: &'a ast::Arm) { + visit::walk_arm(self, arm) + } + + fn visit_pat(&mut self, pattern: &'a ast::Pat) { + match &pattern.node { + PatKind::Slice(pats) => { + for pat in &*pats { + let span = pat.span; + let inner_pat = match &pat.node { + PatKind::Ident(.., Some(pat)) => pat, + _ => pat, + }; + if inner_pat.is_rest() { + gate_feature_post!( + &self, + slice_patterns, + span, + "subslice patterns are unstable" + ); + } + } + } + PatKind::Box(..) => { + gate_feature_post!(&self, box_patterns, + pattern.span, + "box pattern syntax is experimental"); + } + PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { + gate_feature_post!(&self, exclusive_range_pattern, pattern.span, + "exclusive range pattern syntax is experimental"); + } + _ => {} + } + visit::walk_pat(self, pattern) + } + + fn visit_fn(&mut self, + fn_kind: FnKind<'a>, + fn_decl: &'a ast::FnDecl, + span: Span, + _node_id: NodeId) { + if let Some(header) = fn_kind.header() { + // Stability of const fn methods are covered in + // `visit_trait_item` and `visit_impl_item` below; this is + // because default methods don't pass through this point. + self.check_abi(header.abi, span); + } + + if fn_decl.c_variadic { + gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); + } + + visit::walk_fn(self, fn_kind, fn_decl, span) + } + + fn visit_generic_param(&mut self, param: &'a GenericParam) { + match param.kind { + GenericParamKind::Const { .. } => + gate_feature_post!(&self, const_generics, param.ident.span, + "const generics are unstable"), + _ => {} + } + visit::walk_generic_param(self, param) + } + + fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { + match constraint.kind { + AssocTyConstraintKind::Bound { .. } => + gate_feature_post!(&self, associated_type_bounds, constraint.span, + "associated type bounds are unstable"), + _ => {} + } + visit::walk_assoc_ty_constraint(self, constraint) + } + + fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { + match ti.node { + ast::TraitItemKind::Method(ref sig, ref block) => { + if block.is_none() { + self.check_abi(sig.header.abi, ti.span); + } + if sig.decl.c_variadic { + gate_feature_post!(&self, c_variadic, ti.span, + "C-variadic functions are unstable"); + } + if sig.header.constness.node == ast::Constness::Const { + gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); + } + } + ast::TraitItemKind::Type(_, ref default) => { + // We use three if statements instead of something like match guards so that all + // of these errors can be emitted if all cases apply. + if default.is_some() { + gate_feature_post!(&self, associated_type_defaults, ti.span, + "associated type defaults are unstable"); + } + if !ti.generics.params.is_empty() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "generic associated types are unstable"); + } + if !ti.generics.where_clause.predicates.is_empty() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "where clauses on associated types are unstable"); + } + } + _ => {} + } + visit::walk_trait_item(self, ti) + } + + fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { + if ii.defaultness == ast::Defaultness::Default { + gate_feature_post!(&self, specialization, + ii.span, + "specialization is unstable"); + } + + match ii.node { + ast::ImplItemKind::Method(..) => {} + ast::ImplItemKind::OpaqueTy(..) => { + gate_feature_post!( + &self, + type_alias_impl_trait, + ii.span, + "`impl Trait` in type aliases is unstable" + ); + } + ast::ImplItemKind::TyAlias(_) => { + if !ii.generics.params.is_empty() { + gate_feature_post!(&self, generic_associated_types, ii.span, + "generic associated types are unstable"); + } + if !ii.generics.where_clause.predicates.is_empty() { + gate_feature_post!(&self, generic_associated_types, ii.span, + "where clauses on associated types are unstable"); + } + } + _ => {} + } + visit::walk_impl_item(self, ii) + } + + fn visit_vis(&mut self, vis: &'a ast::Visibility) { + if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { + gate_feature_post!(&self, crate_visibility_modifier, vis.span, + "`crate` visibility modifier is experimental"); + } + visit::walk_vis(self, vis) + } +} + +pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], + crate_edition: Edition, allow_features: &Option>) -> Features { + fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { + let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); + if let Some(reason) = reason { + err.span_note(span, reason); + } else { + err.span_label(span, "feature has been removed"); + } + err.emit(); + } + + let mut features = Features::new(); + let mut edition_enabled_features = FxHashMap::default(); + + for &edition in ALL_EDITIONS { + if edition <= crate_edition { + // The `crate_edition` implies its respective umbrella feature-gate + // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). + edition_enabled_features.insert(edition.feature_name(), edition); + } + } + + for feature in active_features_up_to(crate_edition) { + feature.set(&mut features, DUMMY_SP); + edition_enabled_features.insert(feature.name, crate_edition); + } + + // Process the edition umbrella feature-gates first, to ensure + // `edition_enabled_features` is completed before it's queried. + for attr in krate_attrs { + if !attr.check_name(sym::feature) { + continue + } + + let list = match attr.meta_item_list() { + Some(list) => list, + None => continue, + }; + + for mi in list { + if !mi.is_word() { + continue; + } + + let name = mi.name_or_empty(); + + let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied(); + if let Some(edition) = edition { + if edition <= crate_edition { + continue; + } + + for feature in active_features_up_to(edition) { + // FIXME(Manishearth) there is currently no way to set + // lib features by edition + feature.set(&mut features, DUMMY_SP); + edition_enabled_features.insert(feature.name, edition); + } + } + } + } + + for attr in krate_attrs { + if !attr.check_name(sym::feature) { + continue + } + + let list = match attr.meta_item_list() { + Some(list) => list, + None => continue, + }; + + let bad_input = |span| { + struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") + }; + + for mi in list { + let name = match mi.ident() { + Some(ident) if mi.is_word() => ident.name, + Some(ident) => { + bad_input(mi.span()).span_suggestion( + mi.span(), + "expected just one word", + format!("{}", ident.name), + Applicability::MaybeIncorrect, + ).emit(); + continue + } + None => { + bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); + continue + } + }; + + if let Some(edition) = edition_enabled_features.get(&name) { + struct_span_warn!( + span_handler, + mi.span(), + E0705, + "the feature `{}` is included in the Rust {} edition", + name, + edition, + ).emit(); + continue; + } + + if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { + // Handled in the separate loop above. + continue; + } + + let removed = REMOVED_FEATURES.iter().find(|f| name == f.name); + let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name); + if let Some(Feature { state, .. }) = removed.or(stable_removed) { + if let FeatureState::Removed { reason } + | FeatureState::Stabilized { reason } = state + { + feature_removed(span_handler, mi.span(), *reason); + continue; + } + } + + if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) { + let since = Some(Symbol::intern(since)); + features.declared_lang_features.push((name, mi.span(), since)); + continue; + } + + if let Some(allowed) = allow_features.as_ref() { + if allowed.iter().find(|f| *f == name.as_str()).is_none() { + span_err!(span_handler, mi.span(), E0725, + "the feature `{}` is not in the list of allowed features", + name); + continue; + } + } + + if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) { + f.set(&mut features, mi.span()); + features.declared_lang_features.push((name, mi.span(), None)); + continue; + } + + features.declared_lib_features.push((name, mi.span())); + } + } + + features +} + +fn active_features_up_to(edition: Edition) -> impl Iterator { + ACTIVE_FEATURES.iter() + .filter(move |feature| { + if let Some(feature_edition) = feature.edition { + feature_edition <= edition + } else { + false + } + }) +} + +pub fn check_crate(krate: &ast::Crate, + parse_sess: &ParseSess, + features: &Features, + unstable: UnstableFeatures) { + maybe_stage_features(&parse_sess.span_diagnostic, krate, unstable); + let mut visitor = PostExpansionVisitor { parse_sess, features }; + + macro_rules! gate_all { + ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); }; + ($spans:ident, $gate:ident, $msg:literal) => { + for span in &*parse_sess.gated_spans.$spans.borrow() { + gate_feature!(&visitor, $gate, *span, $msg); + } + } + } + + gate_all!(let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure, "async closures are unstable"); + gate_all!(yields, generators, "yield syntax is experimental"); + gate_all!(or_patterns, "or-patterns syntax is experimental"); + + visit::walk_crate(&mut visitor, krate); +} + +#[derive(Clone, Copy, Hash)] +pub enum UnstableFeatures { + /// Hard errors for unstable features are active, as on beta/stable channels. + Disallow, + /// Allow features to be activated, as on nightly. + Allow, + /// Errors are bypassed for bootstrapping. This is required any time + /// during the build that feature-related lints are set to warn or above + /// because the build turns on warnings-as-errors and uses lots of unstable + /// features. As a result, this is always required for building Rust itself. + Cheat +} + +impl UnstableFeatures { + pub fn from_environment() -> UnstableFeatures { + // `true` if this is a feature-staged build, i.e., on the beta or stable channel. + let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); + // `true` if we should enable unstable features for bootstrapping. + let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); + match (disable_unstable_features, bootstrap) { + (_, true) => UnstableFeatures::Cheat, + (true, _) => UnstableFeatures::Disallow, + (false, _) => UnstableFeatures::Allow + } + } + + pub fn is_nightly_build(&self) -> bool { + match *self { + UnstableFeatures::Allow | UnstableFeatures::Cheat => true, + _ => false, + } + } +} + +fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) { + let allow_features = match unstable { + UnstableFeatures::Allow => true, + UnstableFeatures::Disallow => false, + UnstableFeatures::Cheat => true + }; + if !allow_features { + for attr in &krate.attrs { + if attr.check_name(sym::feature) { + let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); + span_err!(span_handler, attr.span, E0554, + "`#![feature]` may not be used on the {} release channel", + release_channel); + } + } + } +} diff --git a/src/libsyntax/feature_gate/mod.rs b/src/libsyntax/feature_gate/mod.rs new file mode 100644 index 0000000000..ca13ab3620 --- /dev/null +++ b/src/libsyntax/feature_gate/mod.rs @@ -0,0 +1,65 @@ +//! # Feature gating +//! +//! This module implements the gating necessary for preventing certain compiler +//! features from being used by default. This module will crawl a pre-expanded +//! AST to ensure that there are no features which are used that are not +//! enabled. +//! +//! Features are enabled in programs via the crate-level attributes of +//! `#![feature(...)]` with a comma-separated list of features. +//! +//! For the purpose of future feature-tracking, once code for detection of feature +//! gate usage is added, *do not remove it again* even once the feature +//! becomes stable. + +mod accepted; +mod removed; +mod active; +mod builtin_attrs; +mod check; + +use std::fmt; +use crate::{edition::Edition, symbol::Symbol}; +use syntax_pos::Span; + +#[derive(Clone, Copy)] +pub enum State { + Accepted, + Active { set: fn(&mut Features, Span) }, + Removed { reason: Option<&'static str> }, + Stabilized { reason: Option<&'static str> }, +} + +impl fmt::Debug for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + State::Accepted { .. } => write!(f, "accepted"), + State::Active { .. } => write!(f, "active"), + State::Removed { .. } => write!(f, "removed"), + State::Stabilized { .. } => write!(f, "stabilized"), + } + } +} + +#[derive(Debug, Clone)] +pub struct Feature { + state: State, + name: Symbol, + since: &'static str, + issue: Option, + edition: Option, + description: &'static str, +} + +pub use active::{Features, INCOMPLETE_FEATURES}; +pub use builtin_attrs::{ + AttributeGate, AttributeType, GatedCfg, + BuiltinAttribute, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, + deprecated_attributes, is_builtin_attr, is_builtin_attr_name, +}; +pub use check::{ + check_crate, get_features, feature_err, emit_feature_err, + Stability, GateIssue, UnstableFeatures, + EXPLAIN_STMT_ATTR_SYNTAX, EXPLAIN_UNSIZED_TUPLE_COERCION, +}; +crate use check::check_attribute; diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs new file mode 100644 index 0000000000..2c29e1ebf1 --- /dev/null +++ b/src/libsyntax/feature_gate/removed.rs @@ -0,0 +1,110 @@ +//! List of the removed feature gates. + +use crate::symbol::sym; +use super::{State, Feature}; + +macro_rules! declare_features { + ($( + $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr), + )+) => { + /// Represents unstable features which have since been removed (it was once Active) + pub const REMOVED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Removed { reason: $reason }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ + ]; + }; + + ($( + $(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None), + )+) => { + /// Represents stable features which have since been removed (it was once Accepted) + pub const STABLE_REMOVED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Stabilized { reason: None }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ + ]; + }; +} + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: removed features + // ------------------------------------------------------------------------- + + (removed, import_shadowing, "1.0.0", None, None, None), + (removed, managed_boxes, "1.0.0", None, None, None), + /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 + (removed, negate_unsigned, "1.0.0", Some(29645), None, None), + (removed, reflect, "1.0.0", Some(27749), None, None), + /// A way to temporarily opt out of opt in copy. This will *never* be accepted. + (removed, opt_out_copy, "1.0.0", None, None, None), + (removed, quad_precision_float, "1.0.0", None, None, None), + (removed, struct_inherit, "1.0.0", None, None, None), + (removed, test_removed_feature, "1.0.0", None, None, None), + (removed, visible_private_types, "1.0.0", None, None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), + /// Allows using items which are missing stability attributes + (removed, unmarked_api, "1.0.0", None, None, None), + (removed, allocator, "1.0.0", None, None, None), + (removed, simd, "1.0.0", Some(27731), None, + Some("removed in favor of `#[repr(simd)]`")), + (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, + Some("merged into `#![feature(slice_patterns)]`")), + (removed, macro_reexport, "1.0.0", Some(29638), None, + Some("subsumed by `pub use`")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), + (removed, proc_macro_mod, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_expr, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_non_items, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_gen, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, panic_implementation, "1.28.0", Some(44489), None, + Some("subsumed by `#[panic_handler]`")), + /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.32.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), + /// Paths of the form: `extern::foo::bar` + (removed, extern_in_paths, "1.33.0", Some(55600), None, + Some("subsumed by `::foo::bar` paths")), + (removed, quote, "1.33.0", Some(29601), None, None), + /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). + (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), + (removed, await_macro, "1.38.0", Some(50547), None, + Some("subsumed by `.await` syntax")), + /// Allows defining `existential type`s. + (removed, existential_type, "1.38.0", Some(63063), None, + Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), + /// Allows using the macros: + /// + `__diagnostic_used` + /// + `__register_diagnostic` + /// +`__build_diagnostic_array` + (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), + + // ------------------------------------------------------------------------- + // feature-group-end: removed features + // ------------------------------------------------------------------------- +); + +declare_features! ( + (stable_removed, no_stack_check, "1.0.0", None, None), +); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 83c9c692bd..5cdea3aabb 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -12,7 +12,7 @@ use crate::source_map::{SourceMap, FilePathMapping}; use errors::registry::Registry; -use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, SourceMapper}; +use errors::{SubDiagnostic, CodeSuggestion, SourceMapper}; use errors::{DiagnosticId, Applicability}; use errors::emitter::{Emitter, HumanReadableErrorType}; @@ -32,6 +32,7 @@ pub struct JsonEmitter { pretty: bool, ui_testing: bool, json_rendered: HumanReadableErrorType, + external_macro_backtrace: bool, } impl JsonEmitter { @@ -40,6 +41,7 @@ impl JsonEmitter { source_map: Lrc, pretty: bool, json_rendered: HumanReadableErrorType, + external_macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), @@ -48,13 +50,18 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, + external_macro_backtrace, } } - pub fn basic(pretty: bool, json_rendered: HumanReadableErrorType) -> JsonEmitter { + pub fn basic( + pretty: bool, + json_rendered: HumanReadableErrorType, + external_macro_backtrace: bool, + ) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)), - pretty, json_rendered) + pretty, json_rendered, external_macro_backtrace) } pub fn new( @@ -63,6 +70,7 @@ impl JsonEmitter { source_map: Lrc, pretty: bool, json_rendered: HumanReadableErrorType, + external_macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { dst, @@ -71,6 +79,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, + external_macro_backtrace, } } @@ -80,8 +89,8 @@ impl JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let data = Diagnostic::from_diagnostic_builder(db, self); + fn emit_diagnostic(&mut self, db: &errors::Diagnostic) { + let data = Diagnostic::from_errors_diagnostic(db, self); let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { @@ -189,7 +198,7 @@ struct ArtifactNotification<'a> { } impl Diagnostic { - fn from_diagnostic_builder(db: &DiagnosticBuilder<'_>, + fn from_errors_diagnostic(db: &errors::Diagnostic, je: &JsonEmitter) -> Diagnostic { let sugg = db.suggestions.iter().map(|sugg| { @@ -219,8 +228,9 @@ impl Diagnostic { } let buf = BufWriter::default(); let output = buf.clone(); - je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false) - .ui_testing(je.ui_testing).emit_diagnostic(db); + je.json_rendered.new_emitter( + Box::new(buf), Some(je.sm.clone()), false, None, je.external_macro_backtrace + ).ui_testing(je.ui_testing).emit_diagnostic(db); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 8ac48d8d74..b4ae1e87bc 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -7,7 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(const_fn)] #![feature(const_transmute)] @@ -18,7 +18,6 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] -#![feature(rustc_diagnostic_macros)] #![feature(try_trait)] #![feature(unicode_internals)] @@ -61,12 +60,12 @@ macro_rules! panictry { macro_rules! panictry_buffer { ($handler:expr, $e:expr) => ({ use std::result::Result::{Ok, Err}; - use errors::{FatalError, DiagnosticBuilder}; + use errors::FatalError; match $e { Ok(e) => e, Err(errs) => { for e in errs { - DiagnosticBuilder::new_diagnostic($handler, e).emit(); + $handler.emit_diagnostic(&e); } FatalError.raise() } @@ -123,12 +122,8 @@ scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); pub mod diagnostics { #[macro_use] pub mod macros; - pub mod plugin; - pub mod metadata; } -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. pub mod error_codes; pub mod util { @@ -183,5 +178,3 @@ pub mod ext { } pub mod early_buffered_lints; - -__build_diagnostic_array! { libsyntax, DIAGNOSTICS } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index be04c6a76b..5a37222ee5 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1,10 +1,10 @@ -//! A MutVisitor represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a MutVisitor +//! A `MutVisitor` represents an AST modification; it accepts an AST piece and +//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor` //! that walks over an AST and modifies it. //! -//! Note: using a MutVisitor (other than the MacroExpander MutVisitor) on +//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on //! an AST before macro expansion is probably a bad idea. For instance, -//! a MutVisitor renaming item names in a module will miss all of those +//! a `MutVisitor` renaming item names in a module will miss all of those //! that are created by the expansion of a macro. use crate::ast::*; @@ -98,8 +98,8 @@ pub trait MutVisitor: Sized { noop_visit_fn_header(header, self); } - fn visit_struct_field(&mut self, sf: &mut StructField) { - noop_visit_struct_field(sf, self); + fn flat_map_struct_field(&mut self, sf: StructField) -> SmallVec<[StructField; 1]> { + noop_flat_map_struct_field(sf, self) } fn visit_item_kind(&mut self, i: &mut ItemKind) { @@ -130,8 +130,8 @@ pub trait MutVisitor: Sized { noop_flat_map_stmt(s, self) } - fn visit_arm(&mut self, a: &mut Arm) { - noop_visit_arm(a, self); + fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { + noop_flat_map_arm(arm, self) } fn visit_pat(&mut self, p: &mut P) { @@ -174,8 +174,8 @@ pub trait MutVisitor: Sized { noop_visit_foreign_mod(nm, self); } - fn visit_variant(&mut self, v: &mut Variant) { - noop_visit_variant(v, self); + fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { + noop_flat_map_variant(v, self) } fn visit_ident(&mut self, i: &mut Ident) { @@ -225,8 +225,8 @@ pub trait MutVisitor: Sized { noop_visit_attribute(at, self); } - fn visit_arg(&mut self, a: &mut Arg) { - noop_visit_arg(a, self); + fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { + noop_flat_map_param(param, self) } fn visit_generics(&mut self, generics: &mut Generics) { @@ -245,12 +245,8 @@ pub trait MutVisitor: Sized { noop_visit_variant_data(vdata, self); } - fn visit_generic_param(&mut self, param: &mut GenericParam) { - noop_visit_generic_param(param, self); - } - - fn visit_generic_params(&mut self, params: &mut Vec) { - noop_visit_generic_params(params, self); + fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { + noop_flat_map_generic_param(param, self) } fn visit_tt(&mut self, tt: &mut TokenTree) { @@ -277,8 +273,8 @@ pub trait MutVisitor: Sized { noop_visit_mt(mt, self); } - fn visit_field(&mut self, field: &mut Field) { - noop_visit_field(field, self); + fn flat_map_field(&mut self, f: Field) -> SmallVec<[Field; 1]> { + noop_flat_map_field(f, self) } fn visit_where_clause(&mut self, where_clause: &mut WhereClause) { @@ -300,6 +296,10 @@ pub trait MutVisitor: Sized { fn visit_span(&mut self, _sp: &mut Span) { // Do nothing. } + + fn flat_map_field_pattern(&mut self, fp: FieldPat) -> SmallVec<[FieldPat; 1]> { + noop_flat_map_field_pattern(fp, self) + } } /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful @@ -362,6 +362,27 @@ pub fn visit_method_sig(MethodSig { header, decl }: &mut MethodSi vis.visit_fn_decl(decl); } +pub fn noop_flat_map_field_pattern( + mut fp: FieldPat, + vis: &mut T, +) -> SmallVec<[FieldPat; 1]> { + let FieldPat { + attrs, + id, + ident, + is_placeholder: _, + is_shorthand: _, + pat, + span, + } = &mut fp; + vis.visit_id(id); + vis.visit_ident(ident); + vis.visit_pat(pat); + vis.visit_span(span); + visit_thin_attrs(attrs, vis); + smallvec![fp] +} + pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { let UseTree { prefix, kind, span } = use_tree; vis.visit_path(prefix); @@ -382,15 +403,15 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arm( - Arm { attrs, pats, guard, body, span }: &mut Arm, - vis: &mut T, -) { +pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { + let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; visit_attrs(attrs, vis); - visit_vec(pats, |pat| vis.visit_pat(pat)); + vis.visit_id(id); + vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); vis.visit_expr(body); vis.visit_span(span); + smallvec![arm] } pub fn noop_visit_ty_constraint( @@ -424,7 +445,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { } TyKind::BareFn(bft) => { let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut(); - vis.visit_generic_params(generic_params); + generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); } TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), @@ -454,14 +475,17 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } -pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; +pub fn noop_flat_map_variant(mut variant: Variant, vis: &mut T) + -> SmallVec<[Variant; 1]> +{ + let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; vis.visit_ident(ident); visit_attrs(attrs, vis); vis.visit_id(id); vis.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); vis.visit_span(span); + smallvec![variant] } pub fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mut T) { @@ -532,8 +556,8 @@ pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_mac(Spanned { node, span }: &mut Mac, vis: &mut T) { - let Mac_ { path, delim: _, tts, .. } = node; +pub fn noop_visit_mac(mac: &mut Mac, vis: &mut T) { + let Mac { path, delim: _, tts, span, prior_type_ascription: _ } = mac; vis.visit_path(path); vis.visit_tts(tts); vis.visit_span(span); @@ -561,12 +585,14 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) { +pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> { + let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param; vis.visit_id(id); visit_thin_attrs(attrs, vis); vis.visit_pat(pat); vis.visit_span(span); vis.visit_ty(ty); + smallvec![param] } pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { @@ -589,7 +615,7 @@ pub fn noop_visit_tts(TokenStream(tts): &mut TokenStream, vis: &m }) } -// Apply ident visitor if it's an ident, apply other visits to interpolated nodes. +// Applies ident visitor if it's an ident; applies other visits to interpolated nodes. // In practice the ident part is not actually used by specific visitors right now, // but there's a test below checking that it works. pub fn noop_visit_token(t: &mut Token, vis: &mut T) { @@ -600,7 +626,7 @@ pub fn noop_visit_token(t: &mut Token, vis: &mut T) { vis.visit_ident(&mut ident); *name = ident.name; *span = ident.span; - return; // avoid visiting the span for the second time + return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { let mut nt = Lrc::make_mut(nt); @@ -611,28 +637,28 @@ pub fn noop_visit_token(t: &mut Token, vis: &mut T) { vis.visit_span(span); } -/// Apply visitor to elements of interpolated nodes. +/// Applies the visitor to elements of interpolated nodes. // // N.B., this can occur only when applying a visitor to partially expanded // code, where parsed pieces have gotten implanted ito *other* macro // invocations. This is relevant for macro hygiene, but possibly not elsewhere. // // One problem here occurs because the types for flat_map_item, flat_map_stmt, -// etc. allow the visitor to return *multiple* items; this is a problem for the +// etc., allow the visitor to return *multiple* items; this is a problem for the // nodes here, because they insist on having exactly one piece. One solution // would be to mangle the MutVisitor trait to include one-to-many and // one-to-one versions of these entry points, but that would probably confuse a // lot of people and help very few. Instead, I'm just going to put in dynamic // checks. I think the performance impact of this will be pretty much -// nonexistent. The danger is that someone will apply a MutVisitor to a +// nonexistent. The danger is that someone will apply a `MutVisitor` to a // partially expanded node, and will be confused by the fact that their -// "flat_map_item" or "flat_map_stmt" isn't getting called on NtItem or NtStmt +// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt` // nodes. Hopefully they'll wind up reading this comment, and doing something // appropriate. // -// BTW, design choice: I considered just changing the type of, e.g., NtItem to +// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to // contain multiple items, but decided against it when I looked at -// parse_item_or_view_item and tried to figure out what I would do with +// `parse_item_or_view_item` and tried to figure out what I would do with // multiple items there.... pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: &mut T) { match nt { @@ -692,7 +718,7 @@ pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut(); - visit_vec(inputs, |input| vis.visit_arg(input)); + inputs.flat_map_in_place(|param| vis.flat_map_param(param)); match output { FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Ty(ty) => vis.visit_ty(ty), @@ -706,8 +732,12 @@ pub fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) } } -pub fn noop_visit_generic_param(param: &mut GenericParam, vis: &mut T) { - let GenericParam { id, ident, attrs, bounds, kind } = param; +pub fn noop_flat_map_generic_param( + mut param: GenericParam, + vis: &mut T +) -> SmallVec<[GenericParam; 1]> +{ + let GenericParam { id, ident, attrs, bounds, kind, is_placeholder: _ } = &mut param; vis.visit_id(id); vis.visit_ident(ident); visit_thin_attrs(attrs, vis); @@ -721,10 +751,7 @@ pub fn noop_visit_generic_param(param: &mut GenericParam, vis: &m vis.visit_ty(ty); } } -} - -pub fn noop_visit_generic_params(params: &mut Vec, vis: &mut T){ - visit_vec(params, |param| vis.visit_generic_param(param)); + smallvec![param] } pub fn noop_visit_label(Label { ident }: &mut Label, vis: &mut T) { @@ -738,7 +765,7 @@ fn noop_visit_lifetime(Lifetime { id, ident }: &mut Lifetime, vis pub fn noop_visit_generics(generics: &mut Generics, vis: &mut T) { let Generics { params, where_clause, span } = generics; - vis.visit_generic_params(params); + params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_where_clause(where_clause); vis.visit_span(span); } @@ -754,7 +781,7 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: WherePredicate::BoundPredicate(bp) => { let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp; vis.visit_span(span); - vis.visit_generic_params(bound_generic_params); + bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_ty(bounded_ty); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } @@ -776,9 +803,11 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), + VariantData::Struct(fields, ..) => { + fields.flat_map_in_place(|field| vis.flat_map_struct_field(field)); + }, VariantData::Tuple(fields, id) => { - visit_vec(fields, |field| vis.visit_struct_field(field)); + fields.flat_map_in_place(|field| vis.flat_map_struct_field(field)); vis.visit_id(id); }, VariantData::Unit(id) => vis.visit_id(id), @@ -792,27 +821,32 @@ pub fn noop_visit_trait_ref(TraitRef { path, ref_id }: &mut Trait pub fn noop_visit_poly_trait_ref(p: &mut PolyTraitRef, vis: &mut T) { let PolyTraitRef { bound_generic_params, trait_ref, span } = p; - vis.visit_generic_params(bound_generic_params); + bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_trait_ref(trait_ref); vis.visit_span(span); } -pub fn noop_visit_struct_field(f: &mut StructField, visitor: &mut T) { - let StructField { span, ident, vis, id, ty, attrs } = f; +pub fn noop_flat_map_struct_field(mut sf: StructField, visitor: &mut T) + -> SmallVec<[StructField; 1]> +{ + let StructField { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut sf; visitor.visit_span(span); visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_vis(vis); visitor.visit_id(id); visitor.visit_ty(ty); visit_attrs(attrs, visitor); + smallvec![sf] } -pub fn noop_visit_field(f: &mut Field, vis: &mut T) { - let Field { ident, expr, span, is_shorthand: _, attrs } = f; +pub fn noop_flat_map_field(mut f: Field, vis: &mut T) -> SmallVec<[Field; 1]> { + let Field { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f; vis.visit_ident(ident); vis.visit_expr(expr); + vis.visit_id(id); vis.visit_span(span); visit_thin_attrs(attrs, vis); + smallvec![f] } pub fn noop_visit_mt(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) { @@ -856,7 +890,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); } ItemKind::Enum(EnumDef { variants }, generics) => { - visit_vec(variants, |variant| vis.visit_variant(variant)); + variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); vis.visit_generics(generics); } ItemKind::Struct(variant_data, generics) | @@ -981,7 +1015,7 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { }); } -// Mutate one item into possibly many items. +// Mutates one item into possibly many items. pub fn noop_flat_map_item(mut item: P, visitor: &mut T) -> SmallVec<[P; 1]> { let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut(); @@ -1040,14 +1074,8 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { } PatKind::Struct(path, fields, _etc) => { vis.visit_path(path); - for Spanned { node: FieldPat { ident, pat, is_shorthand: _, attrs }, span } in fields { - vis.visit_ident(ident); - vis.visit_pat(pat); - visit_thin_attrs(attrs, vis); - vis.visit_span(span); - }; - } - PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), + fields.flat_map_in_place(|field| vis.flat_map_field_pattern(field)); + } PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { @@ -1055,7 +1083,9 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { vis.visit_expr(e2); vis.visit_span(span); } - PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), + PatKind::Tuple(elems) + | PatKind::Slice(elems) + | PatKind::Or(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Paren(inner) => vis.visit_pat(inner), PatKind::Mac(mac) => vis.visit_mac(mac), } @@ -1100,8 +1130,8 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, vis.visit_ty(ty); } ExprKind::AddrOf(_m, ohs) => vis.visit_expr(ohs), - ExprKind::Let(pats, scrutinee) => { - visit_vec(pats, |pat| vis.visit_pat(pat)); + ExprKind::Let(pat, scrutinee) => { + vis.visit_pat(pat); vis.visit_expr(scrutinee); } ExprKind::If(cond, tr, fl) => { @@ -1126,7 +1156,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, } ExprKind::Match(expr, arms) => { vis.visit_expr(expr); - visit_vec(arms, |arm| vis.visit_arm(arm)); + arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); } ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => { vis.visit_asyncness(asyncness); @@ -1179,7 +1209,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, } ExprKind::InlineAsm(asm) => { let InlineAsm { asm: _, asm_str_style: _, outputs, inputs, clobbers: _, volatile: _, - alignstack: _, dialect: _, ctxt: _ } = asm.deref_mut(); + alignstack: _, dialect: _ } = asm.deref_mut(); for out in outputs { let InlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out; vis.visit_expr(expr); @@ -1189,13 +1219,13 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, ExprKind::Mac(mac) => vis.visit_mac(mac), ExprKind::Struct(path, fields, expr) => { vis.visit_path(path); - visit_vec(fields, |field| vis.visit_field(field)); + fields.flat_map_in_place(|field| vis.flat_map_field(field)); visit_opt(expr, |expr| vis.visit_expr(expr)); }, ExprKind::Paren(expr) => { vis.visit_expr(expr); - // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids. + // Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs. *id = expr.id; vis.visit_span(span); visit_thin_attrs(attrs, vis); diff --git a/src/libsyntax/mut_visit/tests.rs b/src/libsyntax/mut_visit/tests.rs index 6868736976..f779e0d0a6 100644 --- a/src/libsyntax/mut_visit/tests.rs +++ b/src/libsyntax/mut_visit/tests.rs @@ -6,13 +6,13 @@ use crate::print::pprust; use crate::mut_visit; use crate::with_default_globals; -// this version doesn't care about getting comments or docstrings in. +// This version doesn't care about getting comments or doc-strings in. fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) { s.print_mod(&krate.module, &krate.attrs) } -// change every identifier to "zz" +// Change every identifier to "zz". struct ToZzIdentMutVisitor; impl MutVisitor for ToZzIdentMutVisitor { @@ -24,7 +24,7 @@ impl MutVisitor for ToZzIdentMutVisitor { } } -// maybe add to expand.rs... +// Maybe add to `expand.rs`. macro_rules! assert_pred { ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( { @@ -39,7 +39,7 @@ macro_rules! assert_pred { ) } -// make sure idents get transformed everywhere +// Make sure idents get transformed everywhere. #[test] fn ident_transformation () { with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; @@ -54,7 +54,7 @@ macro_rules! assert_pred { }) } -// even inside macro defs.... +// Make sure idents get transformed even inside macro defs. #[test] fn ident_transformation_in_defs () { with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a42da11236..cf6151d17b 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -19,15 +19,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ permitted in this context"; impl<'a> Parser<'a> { - crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec> { - let attrs = self.parse_outer_attributes()?; - attrs.iter().for_each(|a| - self.sess.param_attr_spans.borrow_mut().push(a.span) - ); - Ok(attrs) - } - - /// Parse attributes that appear before an item + /// Parses attributes that appear before an item. crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; @@ -70,10 +62,10 @@ impl<'a> Parser<'a> { Ok(attrs) } - /// Matches `attribute = # ! [ meta_item ]` + /// Matches `attribute = # ! [ meta_item ]`. /// - /// If permit_inner is true, then a leading `!` indicates an inner - /// attribute + /// If `permit_inner` is `true`, then a leading `!` indicates an inner + /// attribute. pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, @@ -168,16 +160,16 @@ impl<'a> Parser<'a> { }) } - /// Parse an inner part of attribute - path and following tokens. + /// Parses an inner part of an attribute (the path and following tokens). /// The tokens must be either a delimited token stream, or empty token stream, /// or the "legacy" key-value form. - /// PATH `(` TOKEN_STREAM `)` - /// PATH `[` TOKEN_STREAM `]` - /// PATH `{` TOKEN_STREAM `}` - /// PATH - /// PATH `=` TOKEN_TREE + /// PATH `(` TOKEN_STREAM `)` + /// PATH `[` TOKEN_STREAM `]` + /// PATH `{` TOKEN_STREAM `}` + /// PATH + /// PATH `=` TOKEN_TREE /// The delimiters or `=` are still put into the resulting token stream. - crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { + pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { let meta = match self.token.kind { token::Interpolated(ref nt) => match **nt { Nonterminal::NtMeta(ref meta) => Some(meta.clone()), @@ -218,11 +210,11 @@ impl<'a> Parser<'a> { }) } - /// Parse attributes that appear after the opening of an item. These should + /// Parses attributes that appear after the opening of an item. These should /// be preceded by an exclamation mark, but we accept and warn about one /// terminated by a semicolon. - - /// matches inner_attrs* + /// + /// Matches `inner_attrs*`. crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { @@ -238,7 +230,7 @@ impl<'a> Parser<'a> { attrs.push(attr); } token::DocComment(s) => { - // we need to get the position of this token before we bump. + // We need to get the position of this token before we bump. let attr = attr::mk_sugared_doc_attr(s, self.token.span); if attr.style == ast::AttrStyle::Inner { attrs.push(attr); @@ -269,10 +261,10 @@ impl<'a> Parser<'a> { Ok(lit) } - /// Per RFC#1559, matches the following grammar: + /// Matches the following grammar (per RFC 1559). /// - /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; - /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; + /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; + /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token.kind { token::Interpolated(ref nt) => match **nt { @@ -304,20 +296,20 @@ impl<'a> Parser<'a> { }) } - /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ; + /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`. fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { match self.parse_unsuffixed_lit() { Ok(lit) => { return Ok(ast::NestedMetaItem::Literal(lit)) } - Err(ref mut err) => self.diagnostic().cancel(err) + Err(ref mut err) => err.cancel(), } match self.parse_meta_item() { Ok(mi) => { return Ok(ast::NestedMetaItem::MetaItem(mi)) } - Err(ref mut err) => self.diagnostic().cancel(err) + Err(ref mut err) => err.cancel(), } let found = self.this_token_to_string(); @@ -325,7 +317,7 @@ impl<'a> Parser<'a> { Err(self.diagnostic().struct_span_err(self.token.span, &msg)) } - /// matches meta_seq = ( COMMASEP(meta_item_inner) ) + /// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`. fn parse_meta_seq(&mut self) -> PResult<'a, Vec> { self.parse_seq_to_end(&token::CloseDelim(token::Paren), SeqSep::trailing_allowed(token::Comma), diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 730efb5ef0..59de5f1412 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1,5 +1,5 @@ use crate::ast::{ - self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, + self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, }; use crate::feature_gate::{feature_err, UnstableFeatures}; @@ -8,18 +8,17 @@ use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, Token use crate::parse::token::{self, TokenKind}; use crate::print::pprust; use crate::ptr::P; -use crate::source_map::Spanned; use crate::symbol::{kw, sym}; use crate::ThinVec; use crate::util::parser::AssocOp; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, pluralise}; use rustc_data_structures::fx::FxHashSet; use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; /// Creates a placeholder argument. -crate fn dummy_arg(ident: Ident) -> Arg { +crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), @@ -30,7 +29,14 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, id: ast::DUMMY_NODE_ID }; - Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) } + Param { + attrs: ThinVec::default(), + id: ast::DUMMY_NODE_ID, + pat, + span: ident.span, + ty: P(ty), + is_placeholder: false, + } } pub enum Error { @@ -191,10 +197,6 @@ impl<'a> Parser<'a> { self.sess.span_diagnostic.span_bug(sp, m) } - crate fn cancel(&self, err: &mut DiagnosticBuilder<'_>) { - self.sess.span_diagnostic.cancel(err) - } - crate fn diagnostic(&self) -> &'a errors::Handler { &self.sess.span_diagnostic } @@ -241,7 +243,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, bool /* recovered */> { fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); - // This might be a sign we need a connect method on Iterator. + // This might be a sign we need a connect method on `Iterator`. let b = i.next() .map_or(String::new(), |t| t.to_string()); i.enumerate().fold(b, |mut b, (i, a)| { @@ -302,7 +304,7 @@ impl<'a> Parser<'a> { ); } let sp = if self.token == token::Eof { - // This is EOF, don't want to point at the following char, but rather the last token + // This is EOF; don't want to point at the following char, but rather the last token. self.prev_span } else { label_sp @@ -318,9 +320,9 @@ impl<'a> Parser<'a> { } let is_semi_suggestable = expected.iter().any(|t| match t { - TokenType::Token(token::Semi) => true, // we expect a `;` here + TokenType::Token(token::Semi) => true, // We expect a `;` here. _ => false, - }) && ( // a `;` would be expected before the current keyword + }) && ( // A `;` would be expected before the current keyword. self.token.is_keyword(kw::Break) || self.token.is_keyword(kw::Continue) || self.token.is_keyword(kw::For) || @@ -420,15 +422,13 @@ impl<'a> Parser<'a> { /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { - let handler = self.diagnostic(); - if let Err(ref mut err) = self.parse_seq_to_before_tokens( kets, SeqSep::none(), TokenExpectType::Expect, |p| Ok(p.parse_token_tree()), ) { - handler.cancel(err); + err.cancel(); } } @@ -526,15 +526,15 @@ impl<'a> Parser<'a> { self.eat_to_tokens(&[&end]); let span = lo.until(self.token.span); - let plural = number_of_gt > 1 || number_of_shr >= 1; + let total_num_of_gt = number_of_gt + number_of_shr * 2; self.diagnostic() .struct_span_err( span, - &format!("unmatched angle bracket{}", if plural { "s" } else { "" }), + &format!("unmatched angle bracket{}", pluralise!(total_num_of_gt)), ) .span_suggestion( span, - &format!("remove extra angle bracket{}", if plural { "s" } else { "" }), + &format!("remove extra angle bracket{}", pluralise!(total_num_of_gt)), String::new(), Applicability::MachineApplicable, ) @@ -542,16 +542,16 @@ impl<'a> Parser<'a> { } } - /// Produce an error if comparison operators are chained (RFC #558). - /// We only need to check lhs, not rhs, because all comparison ops - /// have same precedence and are left-associative - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) { + /// Produces an error if comparison operators are chained (RFC #558). + /// We only need to check the LHS, not the RHS, because all comparison ops + /// have same precedence and are left-associative. + crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { debug_assert!(outer_op.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", outer_op); match lhs.node { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // respan to include both operators + // Respan to include both operators. let op_span = op.span.to(self.token.span); let mut err = self.struct_span_err( op_span, @@ -564,11 +564,14 @@ impl<'a> Parser<'a> { err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); err.help("or use `(...)` if you meant to specify fn arguments"); + // These cases cause too many knock-down errors, bail out (#61329). + return Err(err); } err.emit(); } _ => {} } + Ok(()) } crate fn maybe_report_ambiguous_plus( @@ -592,18 +595,18 @@ impl<'a> Parser<'a> { crate fn maybe_report_invalid_custom_discriminants( sess: &ParseSess, - variants: &[Spanned], + variants: &[ast::Variant], ) { - let has_fields = variants.iter().any(|variant| match variant.node.data { + let has_fields = variants.iter().any(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => true, VariantData::Unit(..) => false, }); - let discriminant_spans = variants.iter().filter(|variant| match variant.node.data { + let discriminant_spans = variants.iter().filter(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => false, VariantData::Unit(..) => true, }) - .filter_map(|variant| variant.node.disr_expr.as_ref().map(|c| c.value.span)) + .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) .collect::>(); if !discriminant_spans.is_empty() && has_fields { @@ -618,7 +621,7 @@ impl<'a> Parser<'a> { err.span_label(sp, "disallowed custom discriminant"); } for variant in variants.iter() { - match &variant.node.data { + match &variant.data { VariantData::Struct(..) => { err.span_label( variant.span, @@ -689,9 +692,9 @@ impl<'a> Parser<'a> { Ok(()) } - /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. - /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem` - /// tail, and combine them into a `::AssocItem` expression/pattern/type. + /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. + /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem` + /// tail, and combines them into a `::AssocItem` expression/pattern/type. crate fn maybe_recover_from_bad_qpath( &mut self, base: P, @@ -706,8 +709,8 @@ impl<'a> Parser<'a> { Ok(base) } - /// Given an already parsed `Ty` parse the `::AssocItem` tail and - /// combine them into a `::AssocItem` expression/pattern/type. + /// Given an already parsed `Ty`, parses the `::AssocItem` tail and + /// combines them into a `::AssocItem` expression/pattern/type. crate fn maybe_recover_from_bad_qpath_stage_2( &mut self, ty_span: Span, @@ -728,7 +731,7 @@ impl<'a> Parser<'a> { self.diagnostic() .struct_span_err(path.span, "missing angle brackets in associated item path") .span_suggestion( - // this is a best-effort recovery + // This is a best-effort recovery. path.span, "try", format!("<{}>::{}", ty_str, path), @@ -736,7 +739,7 @@ impl<'a> Parser<'a> { ) .emit(); - let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0 + let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. Ok(P(T::recovered( Some(QSelf { ty, @@ -759,8 +762,8 @@ impl<'a> Parser<'a> { if !items.is_empty() { let previous_item = &items[items.len() - 1]; let previous_item_kind_name = match previous_item.node { - // say "braced struct" because tuple-structs and - // braceless-empty-struct declarations do take a semicolon + // Say "braced struct" because tuple-structs and + // braceless-empty-struct declarations do take a semicolon. ItemKind::Struct(..) => Some("braced struct"), ItemKind::Enum(..) => Some("enum"), ItemKind::Trait(..) => Some("trait"), @@ -781,7 +784,7 @@ impl<'a> Parser<'a> { } } - /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a + /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a /// closing delimiter. pub fn unexpected_try_recover( &mut self, @@ -839,7 +842,7 @@ impl<'a> Parser<'a> { extern_sp: Span, ) -> PResult<'a, ()> { if self.token != token::Semi { - // this might be an incorrect fn definition (#62109) + // This might be an incorrect fn definition (#62109). let parser_snapshot = self.clone(); match self.parse_inner_attrs_and_block() { Ok((_, body)) => { @@ -869,7 +872,7 @@ impl<'a> Parser<'a> { Ok(()) } - /// Consume alternative await syntaxes like `await!()`, `await `, + /// Consumes alternative await syntaxes like `await!()`, `await `, /// `await? `, `await()`, and `await { }`. crate fn parse_incorrect_await_syntax( &mut self, @@ -922,7 +925,7 @@ impl<'a> Parser<'a> { sp } - /// If encountering `future.await()`, consume and emit error. + /// If encountering `future.await()`, consumes and emits an error. crate fn recover_from_await_method_call(&mut self) { if self.token == token::OpenDelim(token::Paren) && self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) @@ -942,7 +945,7 @@ impl<'a> Parser<'a> { } } - /// Recover a situation like `for ( $pat in $expr )` + /// Recovers a situation like `for ( $pat in $expr )` /// and suggest writing `for $pat in $expr` instead. /// /// This should be called before parsing the `$block`. @@ -1008,7 +1011,7 @@ impl<'a> Parser<'a> { Ok(x) => x, Err(mut err) => { err.emit(); - // recover from parse error + // Recover from parse error. self.consume_block(delim); self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) } @@ -1021,7 +1024,7 @@ impl<'a> Parser<'a> { mut err: DiagnosticBuilder<'a>, ) -> PResult<'a, bool> { let mut pos = None; - // we want to use the last closing delim that would apply + // We want to use the last closing delim that would apply. for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) && Some(self.token.span) > unmatched.unclosed_span @@ -1039,7 +1042,7 @@ impl<'a> Parser<'a> { let unmatched = self.unclosed_delims.remove(pos); let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); - // We want to suggest the inclusion of the closing delimiter where it makes + // We want to suggest the inclusion of the closing delimiter where it makes // the most sense, which is immediately after the last token: // // {foo(bar {}} @@ -1065,7 +1068,7 @@ impl<'a> Parser<'a> { } } - /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid. + /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. crate fn eat_bad_pub(&mut self) { if self.token.is_keyword(kw::Pub) { match self.parse_visibility(false) { @@ -1080,21 +1083,21 @@ impl<'a> Parser<'a> { } } - // Eat tokens until we can be relatively sure we reached the end of the - // statement. This is something of a best-effort heuristic. - // - // We terminate when we find an unmatched `}` (without consuming it). + /// Eats tokens until we can be relatively sure we reached the end of the + /// statement. This is something of a best-effort heuristic. + /// + /// We terminate when we find an unmatched `}` (without consuming it). crate fn recover_stmt(&mut self) { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) } - // If `break_on_semi` is `Break`, then we will stop consuming tokens after - // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is - // approximate - it can mean we break too early due to macros, but that - // should only lead to sub-optimal recovery, not inaccurate parsing). - // - // If `break_on_block` is `Break`, then we will stop consuming tokens - // after finding (and consuming) a brace-delimited block. + /// If `break_on_semi` is `Break`, then we will stop consuming tokens after + /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is + /// approximate -- it can mean we break too early due to macros, but that + /// should only lead to sub-optimal recovery, not inaccurate parsing). + /// + /// If `break_on_block` is `Break`, then we will stop consuming tokens + /// after finding (and consuming) a brace-delimited block. crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { let mut brace_depth = 0; let mut bracket_depth = 0; @@ -1184,7 +1187,7 @@ impl<'a> Parser<'a> { Err(err) } - crate fn eat_incorrect_doc_comment_for_arg_type(&mut self) { + crate fn eat_incorrect_doc_comment_for_param_type(&mut self) { if let token::DocComment(_) = self.token.kind { self.struct_span_err( self.token.span, @@ -1212,7 +1215,7 @@ impl<'a> Parser<'a> { } } - crate fn argument_without_type( + crate fn parameter_without_type( &mut self, err: &mut DiagnosticBuilder<'_>, pat: P, @@ -1287,13 +1290,13 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - crate fn recover_bad_self_arg( + crate fn recover_bad_self_param( &mut self, - mut arg: ast::Arg, + mut param: ast::Param, is_trait_item: bool, - ) -> PResult<'a, ast::Arg> { - let sp = arg.pat.span; - arg.ty.node = TyKind::Err; + ) -> PResult<'a, ast::Param> { + let sp = param.pat.span; + param.ty.node = TyKind::Err; let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); if is_trait_item { err.span_label(sp, "must be the first associated function parameter"); @@ -1302,7 +1305,7 @@ impl<'a> Parser<'a> { err.note("`self` is only valid as the first parameter of an associated function"); } err.emit(); - Ok(arg) + Ok(param) } crate fn consume_block(&mut self, delim: token::DelimToken) { @@ -1345,15 +1348,15 @@ impl<'a> Parser<'a> { err } - /// Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. + /// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors. /// /// This is necessary because at this point we don't know whether we parsed a function with - /// anonymous arguments or a function with names but no types. In order to minimize - /// unecessary errors, we assume the arguments are in the shape of `fn foo(a, b, c)` where - /// the arguments are *names* (so we don't emit errors about not being able to find `b` in + /// anonymous parameters or a function with names but no types. In order to minimize + /// unecessary errors, we assume the parameters are in the shape of `fn foo(a, b, c)` where + /// the parameters are *names* (so we don't emit errors about not being able to find `b` in /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`, - /// we deduplicate them to not complain about duplicated argument names. - crate fn deduplicate_recovered_arg_names(&self, fn_inputs: &mut Vec) { + /// we deduplicate them to not complain about duplicated parameter names. + crate fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec) { let mut seen_inputs = FxHashSet::default(); for input in fn_inputs.iter_mut() { let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = ( diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e86d4c7fde..d16889a91e 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -4,7 +4,7 @@ use crate::symbol::{sym, Symbol}; use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; use errors::{FatalError, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Pos, Span}; use rustc_lexer::Base; use rustc_lexer::unescape; @@ -84,7 +84,7 @@ impl<'a> StringReader<'a> { fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { - self.override_span.unwrap_or_else(|| Span::new(lo, hi, NO_EXPANSION)) + self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi)) } /// Returns the next token, including trivia like whitespace or comments. @@ -291,9 +291,6 @@ impl<'a> StringReader<'a> { } rustc_lexer::TokenKind::Semi => token::Semi, rustc_lexer::TokenKind::Comma => token::Comma, - rustc_lexer::TokenKind::DotDotDot => token::DotDotDot, - rustc_lexer::TokenKind::DotDotEq => token::DotDotEq, - rustc_lexer::TokenKind::DotDot => token::DotDot, rustc_lexer::TokenKind::Dot => token::Dot, rustc_lexer::TokenKind::OpenParen => token::OpenDelim(token::Paren), rustc_lexer::TokenKind::CloseParen => token::CloseDelim(token::Paren), @@ -305,42 +302,20 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Pound => token::Pound, rustc_lexer::TokenKind::Tilde => token::Tilde, rustc_lexer::TokenKind::Question => token::Question, - rustc_lexer::TokenKind::ColonColon => token::ModSep, rustc_lexer::TokenKind::Colon => token::Colon, rustc_lexer::TokenKind::Dollar => token::Dollar, - rustc_lexer::TokenKind::EqEq => token::EqEq, rustc_lexer::TokenKind::Eq => token::Eq, - rustc_lexer::TokenKind::FatArrow => token::FatArrow, - rustc_lexer::TokenKind::Ne => token::Ne, rustc_lexer::TokenKind::Not => token::Not, - rustc_lexer::TokenKind::Le => token::Le, - rustc_lexer::TokenKind::LArrow => token::LArrow, rustc_lexer::TokenKind::Lt => token::Lt, - rustc_lexer::TokenKind::ShlEq => token::BinOpEq(token::Shl), - rustc_lexer::TokenKind::Shl => token::BinOp(token::Shl), - rustc_lexer::TokenKind::Ge => token::Ge, rustc_lexer::TokenKind::Gt => token::Gt, - rustc_lexer::TokenKind::ShrEq => token::BinOpEq(token::Shr), - rustc_lexer::TokenKind::Shr => token::BinOp(token::Shr), - rustc_lexer::TokenKind::RArrow => token::RArrow, rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus), - rustc_lexer::TokenKind::MinusEq => token::BinOpEq(token::Minus), rustc_lexer::TokenKind::And => token::BinOp(token::And), - rustc_lexer::TokenKind::AndEq => token::BinOpEq(token::And), - rustc_lexer::TokenKind::AndAnd => token::AndAnd, rustc_lexer::TokenKind::Or => token::BinOp(token::Or), - rustc_lexer::TokenKind::OrEq => token::BinOpEq(token::Or), - rustc_lexer::TokenKind::OrOr => token::OrOr, rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus), - rustc_lexer::TokenKind::PlusEq => token::BinOpEq(token::Plus), rustc_lexer::TokenKind::Star => token::BinOp(token::Star), - rustc_lexer::TokenKind::StarEq => token::BinOpEq(token::Star), rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash), - rustc_lexer::TokenKind::SlashEq => token::BinOpEq(token::Slash), rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), - rustc_lexer::TokenKind::CaretEq => token::BinOpEq(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::PercentEq => token::BinOpEq(token::Percent), rustc_lexer::TokenKind::Unknown => { let c = self.str_from(start).chars().next().unwrap(); diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index fc47e4f0b1..de301b1fc4 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -1,44 +1,29 @@ use super::*; -use crate::ast::CrateConfig; use crate::symbol::Symbol; use crate::source_map::{SourceMap, FilePathMapping}; -use crate::feature_gate::UnstableFeatures; use crate::parse::token; -use crate::diagnostics::plugin::ErrorMap; use crate::with_default_globals; + +use errors::{Handler, emitter::EmitterWriter}; use std::io; use std::path::PathBuf; -use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition}; -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use rustc_data_structures::sync::{Lock, Once}; +use syntax_pos::{BytePos, Span}; fn mk_sess(sm: Lrc) -> ParseSess { - let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), - Some(sm.clone()), - false, - false, - false); - ParseSess { - span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)), - unstable_features: UnstableFeatures::from_environment(), - config: CrateConfig::default(), - included_mod_stack: Lock::new(Vec::new()), - source_map: sm, - missing_fragment_specifiers: Lock::new(FxHashSet::default()), - raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), - buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), - ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), - injected_crate_name: Once::new(), - } + let emitter = EmitterWriter::new( + Box::new(io::sink()), + Some(sm.clone()), + false, + false, + false, + None, + false, + ); + ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm) } -// open a string reader for the given string +// Creates a string reader for the given string. fn setup<'a>(sm: &SourceMap, sess: &'a ParseSess, teststr: String) @@ -52,26 +37,27 @@ fn t1() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - let mut string_reader = setup(&sm, - &sh, - "/* my source file */ fn main() { println!(\"zebra\"); }\n" - .to_string()); + let mut string_reader = setup( + &sm, + &sh, + "/* my source file */ fn main() { println!(\"zebra\"); }\n".to_string(), + ); assert_eq!(string_reader.next_token(), token::Comment); assert_eq!(string_reader.next_token(), token::Whitespace); let tok1 = string_reader.next_token(); let tok2 = Token::new( mk_ident("fn"), - Span::new(BytePos(21), BytePos(23), NO_EXPANSION), + Span::with_root_ctxt(BytePos(21), BytePos(23)), ); assert_eq!(tok1.kind, tok2.kind); assert_eq!(tok1.span, tok2.span); assert_eq!(string_reader.next_token(), token::Whitespace); - // read another token: + // Read another token. let tok3 = string_reader.next_token(); assert_eq!(string_reader.pos.clone(), BytePos(28)); let tok4 = Token::new( mk_ident("main"), - Span::new(BytePos(24), BytePos(28), NO_EXPANSION), + Span::with_root_ctxt(BytePos(24), BytePos(28)), ); assert_eq!(tok3.kind, tok4.kind); assert_eq!(tok3.span, tok4.span); @@ -81,15 +67,15 @@ fn t1() { }) } -// check that the given reader produces the desired stream -// of tokens (stop checking after exhausting the expected vec) +// Checks that the given reader produces the desired stream +// of tokens (stop checking after exhausting `expected`). fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec) { for expected_tok in &expected { assert_eq!(&string_reader.next_token(), expected_tok); } } -// make the identifier by looking up the string in the interner +// Makes the identifier by looking up the string in the interner. fn mk_ident(id: &str) -> TokenKind { token::Ident(Symbol::intern(id), false) } @@ -99,42 +85,50 @@ fn mk_lit(kind: token::LitKind, symbol: &str, suffix: Option<&str>) -> TokenKind } #[test] -fn doublecolonparsing() { +fn doublecolon_parsing() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a b".to_string()), - vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a b".to_string()), + vec![mk_ident("a"), token::Whitespace, mk_ident("b")], + ); }) } #[test] -fn dcparsing_2() { +fn doublecolon_parsing_2() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a::b".to_string()), - vec![mk_ident("a"), token::ModSep, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a::b".to_string()), + vec![mk_ident("a"), token::Colon, token::Colon, mk_ident("b")], + ); }) } #[test] -fn dcparsing_3() { +fn doublecolon_parsing_3() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a ::b".to_string()), - vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a ::b".to_string()), + vec![mk_ident("a"), token::Whitespace, token::Colon, token::Colon, mk_ident("b")], + ); }) } #[test] -fn dcparsing_4() { +fn doublecolon_parsing_4() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a:: b".to_string()), - vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a:: b".to_string()), + vec![mk_ident("a"), token::Colon, token::Colon, token::Whitespace, mk_ident("b")], + ); }) } @@ -143,8 +137,10 @@ fn character_a() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token(), - mk_lit(token::Char, "a", None)); + assert_eq!( + setup(&sm, &sh, "'a'".to_string()).next_token(), + mk_lit(token::Char, "a", None), + ); }) } @@ -153,8 +149,10 @@ fn character_space() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token(), - mk_lit(token::Char, " ", None)); + assert_eq!( + setup(&sm, &sh, "' '".to_string()).next_token(), + mk_lit(token::Char, " ", None), + ); }) } @@ -163,8 +161,10 @@ fn character_escaped() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token(), - mk_lit(token::Char, "\\n", None)); + assert_eq!( + setup(&sm, &sh, "'\\n'".to_string()).next_token(), + mk_lit(token::Char, "\\n", None), + ); }) } @@ -173,8 +173,10 @@ fn lifetime_name() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token(), - token::Lifetime(Symbol::intern("'abc"))); + assert_eq!( + setup(&sm, &sh, "'abc".to_string()).next_token(), + token::Lifetime(Symbol::intern("'abc")), + ); }) } @@ -183,8 +185,10 @@ fn raw_string() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(), - mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None)); + assert_eq!( + setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(), + mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None), + ); }) } @@ -195,11 +199,15 @@ fn literal_suffixes() { let sh = mk_sess(sm.clone()); macro_rules! test { ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ - assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, Some("suffix"))); - // with a whitespace separator: - assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, None)); + assert_eq!( + setup(&sm, &sh, format!("{}suffix", $input)).next_token(), + mk_lit(token::$tok_type, $tok_contents, Some("suffix")), + ); + // with a whitespace separator + assert_eq!( + setup(&sm, &sh, format!("{} suffix", $input)).next_token(), + mk_lit(token::$tok_type, $tok_contents, None), + ); }} } @@ -213,12 +221,18 @@ fn literal_suffixes() { test!("1.0", Float, "1.0"); test!("1.0e10", Float, "1.0e10"); - assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token(), - mk_lit(token::Integer, "2", Some("us"))); - assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::StrRaw(3), "raw", Some("suffix"))); - assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::ByteStrRaw(3), "raw", Some("suffix"))); + assert_eq!( + setup(&sm, &sh, "2us".to_string()).next_token(), + mk_lit(token::Integer, "2", Some("us")), + ); + assert_eq!( + setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(), + mk_lit(token::StrRaw(3), "raw", Some("suffix")), + ); + assert_eq!( + setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(), + mk_lit(token::ByteStrRaw(3), "raw", Some("suffix")), + ); }) } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 37e67a2729..e5ba7e4530 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -39,29 +39,29 @@ struct TokenTreesReader<'a> { impl<'a> TokenTreesReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { - let mut tts = Vec::new(); + let mut buf = TokenStreamBuilder::default(); self.real_token(); while self.token != token::Eof { - tts.push(self.parse_token_tree()?); + buf.push(self.parse_token_tree()?); } - Ok(TokenStream::new(tts)) + Ok(buf.into_token_stream()) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { - let mut tts = vec![]; + let mut buf = TokenStreamBuilder::default(); loop { if let token::CloseDelim(..) = self.token.kind { - return TokenStream::new(tts); + return buf.into_token_stream(); } match self.parse_token_tree() { - Ok(tree) => tts.push(tree), + Ok(tree) => buf.push(tree), Err(mut e) => { e.emit(); - return TokenStream::new(tts); + return buf.into_token_stream(); } } } @@ -223,8 +223,32 @@ impl<'a> TokenTreesReader<'a> { _ => { self.token = token; return; - }, + } + } + } + } +} + +#[derive(Default)] +struct TokenStreamBuilder { + buf: Vec, +} + +impl TokenStreamBuilder { + fn push(&mut self, (tree, joint): TreeAndJoint) { + if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() { + if let TokenTree::Token(token) = &tree { + if let Some(glued) = prev_token.glue(token) { + self.buf.pop(); + self.buf.push((TokenTree::Token(glued), joint)); + return; + } } } + self.buf.push((tree, joint)) + } + + fn into_token_stream(self) -> TokenStream { + TokenStream::new(self.buf) } } diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index eaa736c6a3..525b4215af 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -3,7 +3,7 @@ use super::StringReader; use errors::{Applicability, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION, symbol::kw}; +use syntax_pos::{BytePos, Pos, Span, symbol::kw}; use crate::parse::token; #[rustfmt::skip] // for line breaks @@ -343,7 +343,7 @@ crate fn check_for_substitution<'a>( None => return None, }; - let span = Span::new(pos, pos + Pos::from_usize(ch.len_utf8()), NO_EXPANSION); + let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8())); let (ascii_name, token) = match ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) { Some((_ascii_char, ascii_name, token)) => (ascii_name, token), @@ -362,10 +362,9 @@ crate fn check_for_substitution<'a>( ascii_char, ascii_name ); err.span_suggestion( - Span::new( + Span::with_root_ctxt( pos, pos + Pos::from_usize('“'.len_utf8() + s.len() + '”'.len_utf8()), - NO_EXPANSION, ), &msg, format!("\"{}\"", s), diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 6409acba57..36233de3cf 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -104,7 +104,7 @@ impl LitKind { Ok(match kind { token::Bool => { - assert!(symbol == kw::True || symbol == kw::False); + assert!(symbol.is_bool_lit()); LitKind::Bool(symbol == kw::True) } token::Byte => return unescape_byte(&symbol.as_str()) @@ -261,7 +261,7 @@ impl Lit { /// Converts arbitrary token into an AST literal. crate fn from_token(token: &Token) -> Result { let lit = match token.kind { - token::Ident(name, false) if name == kw::True || name == kw::False => + token::Ident(name, false) if name.is_bool_lit() => token::Lit::new(token::Bool, name, None), token::Literal(lit) => lit, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 80aa7a3526..fa4c104312 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -8,16 +8,18 @@ use crate::parse::parser::Parser; use crate::parse::parser::emit_unclosed_delims; use crate::parse::token::TokenKind; use crate::tokenstream::{TokenStream, TokenTree}; -use crate::diagnostics::plugin::ErrorMap; use crate::print::pprust; use crate::symbol::Symbol; use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +#[cfg(target_arch = "x86_64")] +use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::{Lrc, Lock, Once}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use syntax_pos::edition::Edition; +use syntax_pos::hygiene::ExpnId; -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; use std::path::{Path, PathBuf}; use std::str; @@ -38,6 +40,25 @@ crate mod unescape_error_reporting; pub type PResult<'a, T> = Result>; +// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. +// (See also the comment on `DiagnosticBuilderInner`.) +#[cfg(target_arch = "x86_64")] +static_assert_size!(PResult<'_, bool>, 16); + +/// Collected spans during parsing for places where a certain feature was +/// used and should be feature gated accordingly in `check_crate`. +#[derive(Default)] +pub struct GatedSpans { + /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`. + pub let_chains: Lock>, + /// Spans collected for gating `async_closure`, e.g. `async || ..`. + pub async_closure: Lock>, + /// Spans collected for gating `yield e?` expressions (`generators` gate). + pub yields: Lock>, + /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. + pub or_patterns: Lock>, +} + /// Info about a parsing session. pub struct ParseSess { pub span_diagnostic: Handler, @@ -47,8 +68,6 @@ pub struct ParseSess { pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock>, - /// The registered diagnostics codes. - crate registered_diagnostics: Lock, /// Used to determine and report recursive module inclusions. included_mod_stack: Lock>, source_map: Lrc, @@ -57,41 +76,36 @@ pub struct ParseSess { /// operation token that followed it, but that the parser cannot identify without further /// analysis. pub ambiguous_block_expr_parse: Lock>, - pub param_attr_spans: Lock>, - // Places where `let` exprs were used and should be feature gated according to `let_chains`. - pub let_chains_spans: Lock>, - // Places where `async || ..` exprs were used and should be feature gated. - pub async_closure_spans: Lock>, pub injected_crate_name: Once, + pub gated_spans: GatedSpans, } impl ParseSess { pub fn new(file_path_mapping: FilePathMapping) -> Self { let cm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, - true, - None, - Some(cm.clone())); + let handler = Handler::with_tty_emitter( + ColorConfig::Auto, + true, + None, + Some(cm.clone()), + ); ParseSess::with_span_handler(handler, cm) } - pub fn with_span_handler(handler: Handler, source_map: Lrc) -> ParseSess { - ParseSess { + pub fn with_span_handler(handler: Handler, source_map: Lrc) -> Self { + Self { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(), config: FxHashSet::default(), + edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Lock::new(FxHashSet::default()), raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), + gated_spans: GatedSpans::default(), } } @@ -144,17 +158,17 @@ pub struct Directory<'a> { #[derive(Copy, Clone)] pub enum DirectoryOwnership { Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs` + // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. relative: Option, }, UnownedViaBlock, UnownedViaMod(bool /* legacy warnings? */), } -// a bunch of utility functions of the form parse__from_ +// A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and -// source_str. +// `source_str`. pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> { let mut parser = new_parser_from_file(sess, input); @@ -208,14 +222,13 @@ pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source Ok(parser) } -/// Creates a new parser, handling errors as appropriate -/// if the file doesn't exist +/// Creates a new parser, handling errors as appropriate if the file doesn't exist. pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> { source_file_to_parser(sess, file_to_source_file(sess, path, None)) } -/// Creates a new parser, returning buffered diagnostics if the file doesn't -/// exist or from lexing the initial token stream. +/// Creates a new parser, returning buffered diagnostics if the file doesn't exist, +/// or from lexing the initial token stream. pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Result, Vec> { let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?; @@ -223,8 +236,8 @@ pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) } /// Given a session, a crate config, a path, and a span, add -/// the file at the given path to the source_map, and return a parser. -/// On an error, use the given span as the source of the problem. +/// the file at the given path to the `source_map`, and returns a parser. +/// On an error, uses the given span as the source of the problem. pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, directory_ownership: DirectoryOwnership, @@ -236,13 +249,13 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, p } -/// Given a source_file and config, return a parser +/// Given a `source_file` and config, returns a parser. fn source_file_to_parser(sess: &ParseSess, source_file: Lrc) -> Parser<'_> { panictry_buffer!(&sess.span_diagnostic, maybe_source_file_to_parser(sess, source_file)) } -/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the +/// Given a `source_file` and config, return a parser. Returns any buffered errors from lexing the /// initial token stream. fn maybe_source_file_to_parser( sess: &ParseSess, @@ -259,14 +272,14 @@ fn maybe_source_file_to_parser( Ok(parser) } -// must preserve old name for now, because quote! from the *existing* -// compiler expands into it +// Must preserve old name for now, because `quote!` from the *existing* +// compiler expands into it. pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec) -> Parser<'_> { stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS) } -// base abstractions +// Base abstractions /// Given a session and a path and an optional span (for error reporting), /// add the path to the session's source_map and return the new source_file or @@ -285,19 +298,19 @@ fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) } /// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's `source_map` and return the new `source_file`. +/// adds the path to the session's `source_map` and returns the new `source_file`. fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) -> Lrc { match try_file_to_source_file(sess, path, spanopt) { Ok(source_file) => source_file, Err(d) => { - DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit(); + sess.span_diagnostic.emit_diagnostic(&d); FatalError.raise(); } } } -/// Given a source_file, produces a sequence of token trees. +/// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( sess: &ParseSess, source_file: Lrc, @@ -341,7 +354,7 @@ pub fn maybe_file_to_stream( } } -/// Given stream and the `ParseSess`, produces a parser. +/// Given a stream and the `ParseSess`, produces a parser. pub fn stream_to_parser<'a>( sess: &'a ParseSess, stream: TokenStream, @@ -350,7 +363,7 @@ pub fn stream_to_parser<'a>( Parser::new(sess, stream, None, true, false, subparser_name) } -/// Given stream, the `ParseSess` and the base directory, produces a parser. +/// Given a stream, the `ParseSess` and the base directory, produces a parser. /// /// Use this function when you are creating a parser from the token stream /// and also care about the current working directory of the parser (e.g., diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1c1428c571..204f9c3409 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,23 +10,22 @@ pub use path::PathStyle; mod stmt; mod generics; -use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind}; -use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; -use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; -use crate::ext::hygiene::SyntaxContext; -use crate::source_map::{self, respan}; -use crate::parse::{SeqSep, literal, token}; +use crate::ast::{ + self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident, + IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility, + VisibilityKind, Unsafety, +}; +use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token}; +use crate::parse::diagnostics::{Error, dummy_arg}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::{Token, TokenKind, DelimToken}; -use crate::parse::{ParseSess, Directory, DirectoryOwnership}; use crate::print::pprust; use crate::ptr::P; -use crate::parse::PResult; -use crate::ThinVec; -use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; +use crate::source_map::{self, respan}; use crate::symbol::{kw, sym, Symbol}; -use crate::parse::diagnostics::{Error, dummy_arg}; +use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; +use crate::ThinVec; use errors::{Applicability, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; @@ -57,7 +56,7 @@ crate enum BlockMode { Ignore, } -/// As maybe_whole_expr, but for things other than expressions +/// Like `maybe_whole_expr`, but for things other than expressions. #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { @@ -117,11 +116,11 @@ pub struct Parser<'a> { /// with non-interpolated identifier and lifetime tokens they refer to. /// Perhaps the normalized / non-normalized setup can be simplified somehow. pub token: Token, - /// Span of the current non-normalized token. + /// The span of the current non-normalized token. meta_var_span: Option, - /// Span of the previous non-normalized token. + /// The span of the previous non-normalized token. pub prev_span: Span, - /// Kind of the previous normalized token (in simplified form). + /// The kind of the previous normalized token (in simplified form). prev_token_kind: PrevTokenKind, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. @@ -133,7 +132,7 @@ pub struct Parser<'a> { /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, crate expected_tokens: Vec, - crate token_cursor: TokenCursor, + token_cursor: TokenCursor, desugar_doc_comments: bool, /// `true` we should configure out of line modules as we parse. pub cfg_mods: bool, @@ -144,7 +143,7 @@ pub struct Parser<'a> { /// See the comments in the `parse_path_segment` function for more details. crate unmatched_angle_bracket_count: u32, crate max_angle_bracket_count: u32, - /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery + /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery /// it gets removed from here. Every entry left at the end gets emitted as an independent /// error. crate unclosed_delims: Vec, @@ -162,19 +161,19 @@ impl<'a> Drop for Parser<'a> { } #[derive(Clone)] -crate struct TokenCursor { - crate frame: TokenCursorFrame, - crate stack: Vec, +struct TokenCursor { + frame: TokenCursorFrame, + stack: Vec, } #[derive(Clone)] -crate struct TokenCursorFrame { - crate delim: token::DelimToken, - crate span: DelimSpan, - crate open_delim: bool, - crate tree_cursor: tokenstream::Cursor, - crate close_delim: bool, - crate last_token: LastToken, +struct TokenCursorFrame { + delim: token::DelimToken, + span: DelimSpan, + open_delim: bool, + tree_cursor: tokenstream::Cursor, + close_delim: bool, + last_token: LastToken, } /// This is used in `TokenCursorFrame` above to track tokens that are consumed @@ -376,10 +375,11 @@ impl<'a> Parser<'a> { if let Some(directory) = directory { parser.directory = directory; } else if !parser.token.span.is_dummy() { - if let FileName::Real(mut path) = - sess.source_map().span_to_unmapped_path(parser.token.span) { - path.pop(); - parser.directory.path = Cow::from(path); + if let Some(FileName::Real(path)) = + &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path { + if let Some(directory_path) = path.parent() { + parser.directory.path = Cow::from(directory_path.to_path_buf()); + } } } @@ -799,14 +799,14 @@ impl<'a> Parser<'a> { break; } Err(mut e) => { - // Attempt to keep parsing if it was a similar separator + // Attempt to keep parsing if it was a similar separator. if let Some(ref tokens) = t.similar_tokens() { if tokens.contains(&self.token.kind) { self.bump(); } } e.emit(); - // Attempt to keep parsing if it was an omitted separator + // Attempt to keep parsing if it was an omitted separator. match f(self) { Ok(t) => { v.push(t); @@ -871,7 +871,7 @@ impl<'a> Parser<'a> { self.parse_delim_comma_seq(token::Paren, f) } - /// Advance the parser by one token + /// Advance the parser by one token. pub fn bump(&mut self) { if self.prev_token_kind == PrevTokenKind::Eof { // Bumping after EOF is a bad sign, usually an infinite loop. @@ -894,17 +894,17 @@ impl<'a> Parser<'a> { self.token = self.next_tok(); self.expected_tokens.clear(); - // check after each token + // Check after each token. self.process_potential_macro_variable(); } - /// Advance the parser using provided token as a next one. Use this when + /// Advances the parser using provided token as a next one. Use this when /// consuming a part of a token. For example a single `<` from `<<`. fn bump_with(&mut self, next: TokenKind, span: Span) { self.prev_span = self.token.span.with_hi(span.lo()); // It would be incorrect to record the kind of the current token, but // fortunately for tokens currently using `bump_with`, the - // prev_token_kind will be of no use anyway. + // `prev_token_kind` will be of no use anyway. self.prev_token_kind = PrevTokenKind::Other; self.token = Token::new(next, span); self.expected_tokens.clear(); @@ -937,8 +937,8 @@ impl<'a> Parser<'a> { fn parse_asyncness(&mut self) -> IsAsync { if self.eat_keyword(kw::Async) { IsAsync::Async { - closure_id: ast::DUMMY_NODE_ID, - return_impl_trait_id: ast::DUMMY_NODE_ID, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, } } else { IsAsync::NotAsync @@ -971,30 +971,34 @@ impl<'a> Parser<'a> { /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. - /// This version of parse arg doesn't necessarily require identifier names. - fn parse_arg_general( + /// This version of parse param doesn't necessarily require identifier names. + fn parse_param_general( &mut self, + is_self_allowed: bool, is_trait_item: bool, allow_c_variadic: bool, - is_name_required: F, - ) -> PResult<'a, Arg> - where - F: Fn(&token::Token) -> bool - { + is_name_required: impl Fn(&token::Token) -> bool, + ) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_arg_attributes()?; - if let Some(mut arg) = self.parse_self_arg()? { - arg.attrs = attrs.into(); - return self.recover_bad_self_arg(arg, is_trait_item); + let attrs = self.parse_outer_attributes()?; + + // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. + if let Some(mut param) = self.parse_self_param()? { + param.attrs = attrs.into(); + return if is_self_allowed { + Ok(param) + } else { + self.recover_bad_self_param(param, is_trait_item) + }; } let is_name_required = is_name_required(&self.token); let (pat, ty) = if is_name_required || self.is_named_argument() { - debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required); + debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - let pat = self.parse_pat(Some("argument name"))?; + let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { - if let Some(ident) = self.argument_without_type( + if let Some(ident) = self.parameter_without_type( &mut err, pat, is_name_required, @@ -1007,12 +1011,12 @@ impl<'a> Parser<'a> { } } - self.eat_incorrect_doc_comment_for_arg_type(); + self.eat_incorrect_doc_comment_for_param_type(); (pat, self.parse_ty_common(true, true, allow_c_variadic)?) } else { - debug!("parse_arg_general ident_to_pat"); + debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_arg_type(); + self.eat_incorrect_doc_comment_for_param_type(); let mut ty = self.parse_ty_common(true, true, allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { @@ -1043,7 +1047,14 @@ impl<'a> Parser<'a> { let span = lo.to(self.token.span); - Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty }) + Ok(Param { + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + pat, + span, + ty, + }) } /// Parses mutability (`mut` or nothing). @@ -1101,7 +1112,7 @@ impl<'a> Parser<'a> { crate fn process_potential_macro_variable(&mut self) { self.token = match self.token.kind { - token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() && + token::Dollar if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => { self.bump(); let name = match self.token.kind { @@ -1189,26 +1200,27 @@ impl<'a> Parser<'a> { } - fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool) - -> PResult<'a, (Vec , bool)> { + fn parse_fn_params(&mut self, named_params: bool, allow_c_variadic: bool) + -> PResult<'a, (Vec , bool)> { let sp = self.token.span; let mut c_variadic = false; - let (args, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { + let (params, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { let do_not_enforce_named_arguments_for_c_variadic = |token: &token::Token| -> bool { if token == &token::DotDotDot { false } else { - named_args + named_params } }; - match p.parse_arg_general( + match p.parse_param_general( + false, false, allow_c_variadic, do_not_enforce_named_arguments_for_c_variadic ) { - Ok(arg) => { - if let TyKind::CVarArgs = arg.ty.node { + Ok(param) => { + if let TyKind::CVarArgs = param.ty.node { c_variadic = true; if p.token != token::CloseDelim(token::Paren) { let span = p.token.span; @@ -1216,10 +1228,10 @@ impl<'a> Parser<'a> { "`...` must be the last argument of a C-variadic function"); Ok(None) } else { - Ok(Some(arg)) + Ok(Some(param)) } } else { - Ok(Some(arg)) + Ok(Some(param)) } }, Err(mut e) => { @@ -1234,20 +1246,20 @@ impl<'a> Parser<'a> { } })?; - let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); + let params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); - if c_variadic && args.is_empty() { + if c_variadic && params.len() <= 1 { self.span_err(sp, "C-variadic function must be declared with at least one named argument"); } - Ok((args, c_variadic)) + Ok((params, c_variadic)) } - /// Returns the parsed optional self argument and whether a self shortcut was used. + /// Returns the parsed optional self parameter and whether a self shortcut was used. /// - /// See `parse_self_arg_with_attrs` to collect attributes. - fn parse_self_arg(&mut self) -> PResult<'a, Option> { + /// See `parse_self_param_with_attrs` to collect attributes. + fn parse_self_param(&mut self) -> PResult<'a, Option> { let expect_ident = |this: &mut Self| match this.token.kind { // Preserve hygienic context. token::Ident(name, _) => @@ -1352,61 +1364,28 @@ impl<'a> Parser<'a> { }; let eself = source_map::respan(eself_lo.to(eself_hi), eself); - Ok(Some(Arg::from_self(ThinVec::default(), eself, eself_ident))) - } - - /// Returns the parsed optional self argument with attributes and whether a self - /// shortcut was used. - fn parse_self_arg_with_attrs(&mut self) -> PResult<'a, Option> { - let attrs = self.parse_arg_attributes()?; - let arg_opt = self.parse_self_arg()?; - Ok(arg_opt.map(|mut arg| { - arg.attrs = attrs.into(); - arg - })) + Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) } /// Parses the parameter list and result type of a function that may have a `self` parameter. - fn parse_fn_decl_with_self(&mut self, parse_arg_fn: F) -> PResult<'a, P> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, - { - self.expect(&token::OpenDelim(token::Paren))?; - - // Parse optional self argument. - let self_arg = self.parse_self_arg_with_attrs()?; - - // Parse the rest of the function parameter list. - let sep = SeqSep::trailing_allowed(token::Comma); - let (mut fn_inputs, recovered) = if let Some(self_arg) = self_arg { - if self.check(&token::CloseDelim(token::Paren)) { - (vec![self_arg], false) - } else if self.eat(&token::Comma) { - let mut fn_inputs = vec![self_arg]; - let (mut input, _, recovered) = self.parse_seq_to_before_end( - &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; - fn_inputs.append(&mut input); - (fn_inputs, recovered) - } else { - match self.expect_one_of(&[], &[]) { - Err(err) => return Err(err), - Ok(recovered) => (vec![self_arg], recovered), - } - } - } else { - let (input, _, recovered) = - self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?; - (input, recovered) - }; + fn parse_fn_decl_with_self( + &mut self, + is_name_required: impl Copy + Fn(&token::Token) -> bool, + ) -> PResult<'a, P> { + // Parse the arguments, starting out with `self` being allowed... + let mut is_self_allowed = true; + let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| { + let res = p.parse_param_general(is_self_allowed, true, false, is_name_required); + // ...but now that we've parsed the first argument, `self` is no longer allowed. + is_self_allowed = false; + res + })?; - if !recovered { - // Parse closing paren and return type. - self.expect(&token::CloseDelim(token::Paren))?; - } - // Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. - self.deduplicate_recovered_arg_names(&mut fn_inputs); + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut inputs); Ok(P(FnDecl { - inputs: fn_inputs, + inputs, output: self.parse_ret_ty(true)?, c_variadic: false })) @@ -1498,7 +1477,7 @@ impl<'a> Parser<'a> { format!("in {}", path), Applicability::MachineApplicable, ) - .emit(); // emit diagnostic, but continue with public visibility + .emit(); // Emit diagnostic, but continue with public visibility. } } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 4432c1329c..d0c865a7b8 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,25 +1,26 @@ -use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle}; -use super::{BlockMode, SemiColonMode}; -use super::{SeqSep, TokenExpectType}; - +use super::{ + Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode, + SeqSep, TokenExpectType, +}; +use super::pat::{GateOr, PARAM_EXPECTED}; + +use crate::ast::{ + self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode, + Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind, + FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, +}; use crate::maybe_recover_from_interpolated_ty_qpath; -use crate::ptr::P; -use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode}; -use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm}; -use crate::ast::{Ty, TyKind, FunctionRetTy, Arg, FnDecl}; -use crate::ast::{BinOpKind, BinOp, UnOp}; -use crate::ast::{Mac_, AnonConst, Field}; - use crate::parse::classify; use crate::parse::token::{self, Token}; -use crate::parse::diagnostics::{Error}; +use crate::parse::diagnostics::Error; use crate::print::pprust; -use crate::source_map::{self, respan, Span}; +use crate::ptr::P; +use crate::source_map::{self, Span}; use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; -use std::mem; use errors::Applicability; +use std::mem; use rustc_data_structures::thin_vec::ThinVec; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression @@ -50,7 +51,7 @@ macro_rules! maybe_whole_expr { $p.token.span, ExprKind::Block(block, None), ThinVec::new() )); } - // N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`. + // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`. _ => {}, }; } @@ -65,6 +66,10 @@ pub(super) enum LhsExpr { } impl From>> for LhsExpr { + /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)` + /// and `None` into `LhsExpr::NotYetParsed`. + /// + /// This conversion does not allocate. fn from(o: Option>) -> Self { if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) @@ -75,6 +80,9 @@ impl From>> for LhsExpr { } impl From> for LhsExpr { + /// Converts the `expr: P` into `LhsExpr::AlreadyParsed(expr)`. + /// + /// This conversion does not allocate. fn from(expr: P) -> Self { LhsExpr::AlreadyParsed(expr) } @@ -224,9 +232,13 @@ impl<'a> Parser<'a> { self.err_dotdotdot_syntax(self.token.span); } + if self.token == token::LArrow { + self.err_larrow_operator(self.token.span); + } + self.bump(); if op.is_comparison() { - self.check_no_chained_comparison(&lhs, &op); + self.check_no_chained_comparison(&lhs, &op)?; } // Special cases: if op == AssocOp::As { @@ -335,7 +347,7 @@ impl<'a> Parser<'a> { fn is_at_start_of_range_notation_rhs(&self) -> bool { if self.token.can_begin_expr() { - // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. + // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. if self.token == token::OpenDelim(token::Brace) { return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); } @@ -345,12 +357,12 @@ impl<'a> Parser<'a> { } } - /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` + /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. fn parse_prefix_range_expr( &mut self, already_parsed_attrs: Option> ) -> PResult<'a, P> { - // Check for deprecated `...` syntax + // Check for deprecated `...` syntax. if self.token == token::DotDotDot { self.err_dotdotdot_syntax(self.token.span); } @@ -384,7 +396,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), r, attrs)) } - /// Parse a prefix-unary-operator expr + /// Parses a prefix-unary-operator expr. fn parse_prefix_expr( &mut self, already_parsed_attrs: Option> @@ -544,7 +556,7 @@ impl<'a> Parser<'a> { let expr = mk_expr(self, P(Ty { span: path.span, node: TyKind::Path(None, path), - id: ast::DUMMY_NODE_ID + id: DUMMY_NODE_ID, })); let expr_str = self.span_to_snippet(expr.span) @@ -560,7 +572,7 @@ impl<'a> Parser<'a> { expr.span, &format!("try {} the cast value", op_verb), format!("({})", expr_str), - Applicability::MachineApplicable + Applicability::MachineApplicable, ) .emit(); @@ -736,7 +748,6 @@ impl<'a> Parser<'a> { }) } - /// At the bottom (top?) of the precedence hierarchy, /// Parses things like parenthesized exprs, macros, `return`, etc. /// @@ -750,7 +761,7 @@ impl<'a> Parser<'a> { // added to the return value after the fact. // // Therefore, prevent sub-parser from parsing - // attributes by giving them a empty "already parsed" list. + // attributes by giving them a empty "already-parsed" list. let mut attrs = ThinVec::new(); let lo = self.token.span; @@ -766,14 +777,14 @@ impl<'a> Parser<'a> { ex = ExprKind::Lit(literal); } Err(mut err) => { - self.cancel(&mut err); + err.cancel(); return Err(self.expected_expression_found()); } } } } - // Note: when adding new syntax here, don't forget to adjust TokenKind::can_begin_expr(). + // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. match self.token.kind { // This match arm is a special-case of the `_` match arm below and // could be removed without changing functionality, but it's faster @@ -786,8 +797,8 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); - // (e) is parenthesized e - // (e,) is a tuple with only one field, e + // `(e)` is parenthesized `e`. + // `(e,)` is a tuple with only one field, `e`. let mut es = vec![]; let mut trailing_comma = false; let mut recovered = false; @@ -795,7 +806,7 @@ impl<'a> Parser<'a> { es.push(match self.parse_expr() { Ok(es) => es, Err(mut err) => { - // recover from parse error in tuple list + // Recover from parse error in tuple list. match self.token.kind { token::Ident(name, false) if name == kw::Underscore && self.look_ahead(1, |t| { @@ -839,7 +850,7 @@ impl<'a> Parser<'a> { return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs); } token::BinOp(token::Or) | token::OrOr => { - return self.parse_lambda_expr(attrs); + return self.parse_closure_expr(attrs); } token::OpenDelim(token::Bracket) => { self.bump(); @@ -847,21 +858,21 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); if self.eat(&token::CloseDelim(token::Bracket)) { - // Empty vector. + // Empty vector ex = ExprKind::Array(Vec::new()); } else { - // Nonempty vector. + // Non-empty vector let first_expr = self.parse_expr()?; if self.eat(&token::Semi) { - // Repeating array syntax: [ 0; 512 ] + // Repeating array syntax: `[ 0; 512 ]` let count = AnonConst { - id: ast::DUMMY_NODE_ID, + id: DUMMY_NODE_ID, value: self.parse_expr()?, }; self.expect(&token::CloseDelim(token::Bracket))?; ex = ExprKind::Repeat(first_expr, count); } else if self.eat(&token::Comma) { - // Vector with two or more elements. + // Vector with two or more elements let remaining_exprs = self.parse_seq_to_end( &token::CloseDelim(token::Bracket), SeqSep::trailing_allowed(token::Comma), @@ -871,7 +882,7 @@ impl<'a> Parser<'a> { exprs.extend(remaining_exprs); ex = ExprKind::Array(exprs); } else { - // Vector with one element. + // Vector with one element self.expect(&token::CloseDelim(token::Bracket))?; ex = ExprKind::Array(vec![first_expr]); } @@ -884,8 +895,38 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } + if self.token.is_path_start() { + let path = self.parse_path(PathStyle::Expr)?; + + // `!`, as an operator, is prefix, so we know this isn't that. + if self.eat(&token::Not) { + // MACRO INVOCATION expression + let (delim, tts) = self.expect_delimited_token_tree()?; + hi = self.prev_span; + ex = ExprKind::Mac(Mac { + path, + tts, + delim, + span: lo.to(hi), + prior_type_ascription: self.last_type_ascription, + }); + } else if self.check(&token::OpenDelim(token::Brace)) { + if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { + return expr; + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + + let expr = self.mk_expr(lo.to(hi), ex, attrs); + return self.maybe_recover_from_bad_qpath(expr, true); + } if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { - return self.parse_lambda_expr(attrs); + return self.parse_closure_expr(attrs); } if self.eat_keyword(kw::If) { return self.parse_if_expr(attrs); @@ -947,7 +988,7 @@ impl<'a> Parser<'a> { } if self.is_do_catch_block() { let mut db = self.fatal("found removed `do catch` syntax"); - db.help("Following RFC #2388, the new non-placeholder syntax is `try`"); + db.help("following RFC #2388, the new non-placeholder syntax is `try`"); return Err(db); } if self.is_try_block() { @@ -956,13 +997,13 @@ impl<'a> Parser<'a> { return self.parse_try_block(lo, attrs); } - // Span::rust_2018() is somewhat expensive; don't get it repeatedly. + // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. let is_span_rust_2018 = self.token.span.rust_2018(); if is_span_rust_2018 && self.check_keyword(kw::Async) { - return if self.is_async_block() { // check for `async {` and `async move {` + return if self.is_async_block() { // Check for `async {` and `async move {`. self.parse_async_block(attrs) } else { - self.parse_lambda_expr(attrs) + self.parse_closure_expr(attrs) }; } if self.eat_keyword(kw::Return) { @@ -993,50 +1034,27 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } + + let span = lo.to(hi); + self.sess.gated_spans.yields.borrow_mut().push(span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { let (await_hi, e_kind) = self.parse_incorrect_await_syntax(lo, self.prev_span)?; hi = await_hi; ex = e_kind; - } else if self.token.is_path_start() { - let path = self.parse_path(PathStyle::Expr)?; - - // `!`, as an operator, is prefix, so we know this isn't that - if self.eat(&token::Not) { - // MACRO INVOCATION expression - let (delim, tts) = self.expect_delimited_token_tree()?; - hi = self.prev_span; - ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { - path, - tts, - delim, - prior_type_ascription: self.last_type_ascription, - })); - } else if self.check(&token::OpenDelim(token::Brace)) { - if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { - return expr; - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } } else { if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces // recovery in order to keep the error count down. Fixing the // delimiters will possibly also fix the bare semicolon found in // expression context. For example, silence the following error: - // ``` - // error: expected expression, found `;` - // --> file.rs:2:13 - // | - // 2 | foo(bar(; - // | ^ expected expression - // ``` + // + // error: expected expression, found `;` + // --> file.rs:2:13 + // | + // 2 | foo(bar(; + // | ^ expected expression self.bump(); return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new())); } @@ -1083,11 +1101,11 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); let blk = self.parse_block_tail(lo, blk_mode)?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)); + Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)) } - /// Parses `move |args| expr`. - fn parse_lambda_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { + /// Parses a closure expression (e.g., `move |args| expr`). + fn parse_closure_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.token.span; let movability = if self.eat_keyword(kw::Static) { @@ -1102,8 +1120,8 @@ impl<'a> Parser<'a> { IsAsync::NotAsync }; if asyncness.is_async() { - // Feature gate `async ||` closures. - self.sess.async_closure_spans.borrow_mut().push(self.prev_span); + // Feature-gate `async ||` closures. + self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span); } let capture_clause = self.parse_capture_clause(); @@ -1115,8 +1133,7 @@ impl<'a> Parser<'a> { self.parse_expr_res(restrictions, None)? }, _ => { - // If an explicit return type is given, require a - // block to appear (RFC 968). + // If an explicit return type is given, require a block to appear (RFC 968). let body_lo = self.token.span; self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())? } @@ -1128,7 +1145,7 @@ impl<'a> Parser<'a> { attrs)) } - /// Parse an optional `move` prefix to a closure lke construct. + /// Parses an optional `move` prefix to a closure lke construct. fn parse_capture_clause(&mut self) -> CaptureBy { if self.eat_keyword(kw::Move) { CaptureBy::Value @@ -1148,7 +1165,7 @@ impl<'a> Parser<'a> { &[&token::BinOp(token::Or), &token::OrOr], SeqSep::trailing_allowed(token::Comma), TokenExpectType::NoExpect, - |p| p.parse_fn_block_arg() + |p| p.parse_fn_block_param() )?.0; self.expect_or()?; args @@ -1163,27 +1180,28 @@ impl<'a> Parser<'a> { })) } - /// Parses an argument in a lambda header (e.g., `|arg, arg|`). - fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { + /// Parses a parameter in a closure header (e.g., `|arg, arg|`). + fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_arg_attributes()?; - let pat = self.parse_pat(Some("argument name"))?; + let attrs = self.parse_outer_attributes()?; + let pat = self.parse_pat(PARAM_EXPECTED)?; let t = if self.eat(&token::Colon) { self.parse_ty()? } else { P(Ty { - id: ast::DUMMY_NODE_ID, + id: DUMMY_NODE_ID, node: TyKind::Infer, span: self.prev_span, }) }; let span = lo.to(self.token.span); - Ok(Arg { + Ok(Param { attrs: attrs.into(), ty: t, pat, span, - id: ast::DUMMY_NODE_ID + id: DUMMY_NODE_ID, + is_placeholder: false, }) } @@ -1199,7 +1217,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Else) || !cond.returns() { let sp = self.sess.source_map().next_point(lo); let mut err = self.diagnostic() - .struct_span_err(sp, "missing condition for `if` statemement"); + .struct_span_err(sp, "missing condition for `if` expression"); err.span_label(sp, "expected if condition here"); return Err(err) } @@ -1220,35 +1238,35 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) } - /// Parse the condition of a `if`- or `while`-expression + /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P> { let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; if let ExprKind::Let(..) = cond.node { // Remove the last feature gating of a `let` expression since it's stable. - let last = self.sess.let_chains_spans.borrow_mut().pop(); + let last = self.sess.gated_spans.let_chains.borrow_mut().pop(); debug_assert_eq!(cond.span, last.unwrap()); } Ok(cond) } - /// Parses a `let $pats = $expr` pseudo-expression. + /// Parses a `let $pat = $expr` pseudo-expression. /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - let pats = self.parse_pats()?; + let pat = self.parse_top_pat(GateOr::No)?; self.expect(&token::Eq)?; let expr = self.with_res( Restrictions::NO_STRUCT_LITERAL, |this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) )?; let span = lo.to(expr.span); - self.sess.let_chains_spans.borrow_mut().push(span); - Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs)) + self.sess.gated_spans.let_chains.borrow_mut().push(span); + Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs)) } - /// `else` token already eaten + /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P> { if self.eat_keyword(kw::If) { return self.parse_if_expr(ThinVec::new()); @@ -1258,7 +1276,7 @@ impl<'a> Parser<'a> { } } - /// Parse a 'for' .. 'in' expression ('for' token already eaten) + /// Parses a `for ... in` expression (`for` token already eaten). fn parse_for_expr( &mut self, opt_label: Option

(&self, sp: Span, predicate: P) -> Span where P: for <'r> FnMut(&'r char) -> bool { @@ -696,7 +719,7 @@ impl SourceMap { self.span_until_char(sp, '{') } - /// Returns a new span representing just the start-point of this span + /// Returns a new span representing just the start point of this span. pub fn start_point(&self, sp: Span) -> Span { let pos = sp.lo().0; let width = self.find_width_of_character_at_span(sp, false); @@ -705,7 +728,7 @@ impl SourceMap { sp.with_hi(end_point) } - /// Returns a new span representing just the end-point of this span + /// Returns a new span representing just the end point of this span. pub fn end_point(&self, sp: Span) -> Span { let pos = sp.hi().0; @@ -716,7 +739,7 @@ impl SourceMap { sp.with_lo(end_point) } - /// Returns a new span representing the next character after the end-point of this span + /// Returns a new span representing the next character after the end-point of this span. pub fn next_point(&self, sp: Span) -> Span { let start_of_next_point = sp.hi().0; @@ -819,7 +842,7 @@ impl SourceMap { None } - /// For a global BytePos compute the local offset within the containing SourceFile + /// For a global `BytePos`, computes the local offset within the containing `SourceFile`. pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos { let idx = self.lookup_source_file_idx(bpos); let sf = (*self.files.borrow().source_files)[idx].clone(); @@ -827,22 +850,22 @@ impl SourceMap { SourceFileAndBytePos {sf, pos: offset} } - /// Converts an absolute BytePos to a CharPos relative to the source_file. + /// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`. pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { let idx = self.lookup_source_file_idx(bpos); let map = &(*self.files.borrow().source_files)[idx]; - // The number of extra bytes due to multibyte chars in the SourceFile + // The number of extra bytes due to multibyte chars in the `SourceFile`. let mut total_extra_bytes = 0; for mbc in map.multibyte_chars.iter() { debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos); if mbc.pos < bpos { - // every character is at least one byte, so we only + // Every character is at least one byte, so we only // count the actual extra bytes. total_extra_bytes += mbc.bytes as u32 - 1; // We should never see a byte position in the middle of a - // character + // character. assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32); } else { break; @@ -853,13 +876,13 @@ impl SourceMap { CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize) } - // Return the index of the source_file (in self.files) which contains pos. + // Returns the index of the `SourceFile` (in `self.files`) that contains `pos`. pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { let files = self.files.borrow(); let files = &files.source_files; let count = files.len(); - // Binary search for the source_file. + // Binary search for the `SourceFile`. let mut a = 0; let mut b = count; while b - a > 1 { @@ -890,8 +913,8 @@ impl SourceMap { }).ok() } - /// Take the span of a type parameter in a function signature and try to generate a span for the - /// function name (with generics) and a new snippet for this span with the pointed type + /// Takes the span of a type parameter in a function signature and try to generate a span for + /// the function name (with generics) and a new snippet for this span with the pointed type /// parameter as a new local type parameter. /// /// For instance: @@ -907,18 +930,18 @@ impl SourceMap { /// /// Attention: The method used is very fragile since it essentially duplicates the work of the /// parser. If you need to use this function or something similar, please consider updating the - /// source_map functions and this function to something more robust. + /// `SourceMap` functions and this function to something more robust. pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> { // Try to extend the span to the previous "fn" keyword to retrieve the function - // signature + // signature. let sugg_span = self.span_extend_to_prev_str(span, "fn", false); if sugg_span != span { if let Ok(snippet) = self.span_to_snippet(sugg_span) { - // Consume the function name + // Consume the function name. let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_') .expect("no label after fn"); - // Consume the generics part of the function signature + // Consume the generics part of the function signature. let mut bracket_counter = 0; let mut last_char = None; for c in snippet[offset..].chars() { @@ -932,11 +955,11 @@ impl SourceMap { last_char = Some(c); } - // Adjust the suggestion span to encompass the function name with its generics + // Adjust the suggestion span to encompass the function name with its generics. let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32)); // Prepare the new suggested snippet to append the type parameter that triggered - // the error in the generics of the function signature + // the error in the generics of the function signature. let mut new_snippet = if last_char == Some('>') { format!("{}, ", &snippet[..(offset - '>'.len_utf8())]) } else { diff --git a/src/libsyntax/source_map/tests.rs b/src/libsyntax/source_map/tests.rs index 427e86b56e..15254336bb 100644 --- a/src/libsyntax/source_map/tests.rs +++ b/src/libsyntax/source_map/tests.rs @@ -4,18 +4,24 @@ use rustc_data_structures::sync::Lrc; fn init_source_map() -> SourceMap { let sm = SourceMap::new(FilePathMapping::empty()); - sm.new_source_file(PathBuf::from("blork.rs").into(), - "first line.\nsecond line".to_string()); - sm.new_source_file(PathBuf::from("empty.rs").into(), - String::new()); - sm.new_source_file(PathBuf::from("blork2.rs").into(), - "first line.\nsecond line".to_string()); + sm.new_source_file( + PathBuf::from("blork.rs").into(), + "first line.\nsecond line".to_string(), + ); + sm.new_source_file( + PathBuf::from("empty.rs").into(), + String::new(), + ); + sm.new_source_file( + PathBuf::from("blork2.rs").into(), + "first line.\nsecond line".to_string(), + ); sm } +/// Tests `lookup_byte_offset`. #[test] fn t3() { - // Test lookup_byte_offset let sm = init_source_map(); let srcfbp1 = sm.lookup_byte_offset(BytePos(23)); @@ -31,9 +37,9 @@ fn t3() { assert_eq!(srcfbp2.pos, BytePos(0)); } +/// Tests `bytepos_to_file_charpos`. #[test] fn t4() { - // Test bytepos_to_file_charpos let sm = init_source_map(); let cp1 = sm.bytepos_to_file_charpos(BytePos(22)); @@ -43,9 +49,9 @@ fn t4() { assert_eq!(cp2, CharPos(0)); } +/// Tests zero-length `SourceFile`s. #[test] fn t5() { - // Test zero-length source_files. let sm = init_source_map(); let loc1 = sm.lookup_char_pos(BytePos(22)); @@ -61,7 +67,7 @@ fn t5() { fn init_source_map_mbc() -> SourceMap { let sm = SourceMap::new(FilePathMapping::empty()); - // € is a three byte utf8 char. + // "€" is a three-byte UTF8 char. sm.new_source_file(PathBuf::from("blork.rs").into(), "fir€st €€€€ line.\nsecond line".to_string()); sm.new_source_file(PathBuf::from("blork2.rs").into(), @@ -69,9 +75,9 @@ fn init_source_map_mbc() -> SourceMap { sm } +/// Tests `bytepos_to_file_charpos` in the presence of multi-byte chars. #[test] fn t6() { - // Test bytepos_to_file_charpos in the presence of multi-byte chars let sm = init_source_map_mbc(); let cp1 = sm.bytepos_to_file_charpos(BytePos(3)); @@ -87,11 +93,11 @@ fn t6() { assert_eq!(cp4, CharPos(15)); } +/// Test `span_to_lines` for a span ending at the end of a `SourceFile`. #[test] fn t7() { - // Test span_to_lines for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let file_lines = sm.span_to_lines(span).unwrap(); assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into()); @@ -107,10 +113,10 @@ fn span_from_selection(input: &str, selection: &str) -> Span { assert_eq!(input.len(), selection.len()); let left_index = selection.find('~').unwrap() as u32; let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index); - Span::new(BytePos(left_index), BytePos(right_index + 1), NO_EXPANSION) + Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1)) } -/// Tests span_to_snippet and span_to_lines for a span converting 3 +/// Tests `span_to_snippet` and `span_to_lines` for a span converting 3 /// lines in the middle of a file. #[test] fn span_to_snippet_and_lines_spanning_multiple_lines() { @@ -120,10 +126,10 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() { sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string()); let span = span_from_selection(inputtext, selection); - // check that we are extracting the text we thought we were extracting + // Check that we are extracting the text we thought we were extracting. assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD"); - // check that span_to_lines gives us the complete result with the lines/cols we expected + // Check that span_to_lines gives us the complete result with the lines/cols we expected. let lines = sm.span_to_lines(span).unwrap(); let expected = vec![ LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) }, @@ -133,27 +139,27 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() { assert_eq!(lines.lines, expected); } +/// Test span_to_snippet for a span ending at the end of a `SourceFile`. #[test] fn t8() { - // Test span_to_snippet for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let snippet = sm.span_to_snippet(span); assert_eq!(snippet, Ok("second line".to_string())); } +/// Test `span_to_str` for a span ending at the end of a `SourceFile`. #[test] fn t9() { - // Test span_to_str for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let sstr = sm.span_to_string(span); assert_eq!(sstr, "blork.rs:2:1: 2:12"); } -/// Tests failing to merge two spans on different lines +/// Tests failing to merge two spans on different lines. #[test] fn span_merging_fail() { let sm = SourceMap::new(FilePathMapping::empty()); @@ -167,44 +173,46 @@ fn span_merging_fail() { assert!(sm.merge_spans(span1, span2).is_none()); } -/// Returns the span corresponding to the `n`th occurrence of -/// `substring` in `source_text`. +/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`. trait SourceMapExtension { - fn span_substr(&self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize) - -> Span; + fn span_substr( + &self, + file: &Lrc, + source_text: &str, + substring: &str, + n: usize, + ) -> Span; } impl SourceMapExtension for SourceMap { - fn span_substr(&self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize) - -> Span - { - println!("span_substr(file={:?}/{:?}, substring={:?}, n={})", - file.name, file.start_pos, substring, n); + fn span_substr( + &self, + file: &Lrc, + source_text: &str, + substring: &str, + n: usize, + ) -> Span { + println!( + "span_substr(file={:?}/{:?}, substring={:?}, n={})", + file.name, file.start_pos, substring, n + ); let mut i = 0; let mut hi = 0; loop { let offset = source_text[hi..].find(substring).unwrap_or_else(|| { - panic!("source_text `{}` does not have {} occurrences of `{}`, only {}", - source_text, n, substring, i); + panic!( + "source_text `{}` does not have {} occurrences of `{}`, only {}", + source_text, n, substring, i + ); }); let lo = hi + offset; hi = lo + substring.len(); if i == n { - let span = Span::new( + let span = Span::with_root_ctxt( BytePos(lo as u32 + file.start_pos.0), BytePos(hi as u32 + file.start_pos.0), - NO_EXPANSION, ); - assert_eq!(&self.span_to_snippet(span).unwrap()[..], - substring); + assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring); return span; } i += 1; diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index cff034fdeb..f510ac9273 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -9,7 +9,7 @@ use crate::with_default_globals; use errors::emitter::EmitterWriter; use errors::Handler; use rustc_data_structures::sync::Lrc; -use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan}; +use syntax_pos::{BytePos, Span, MultiSpan}; use std::io; use std::io::prelude::*; @@ -18,7 +18,7 @@ use std::path::{Path, PathBuf}; use std::str; use std::sync::{Arc, Mutex}; -/// Map string to parser (via tts) +/// Map string to parser (via tts). fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> { new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str) } @@ -32,7 +32,7 @@ crate fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) x } -/// Map a string to tts, using a made-up filename: +/// Maps a string to tts, using a made-up filename. crate fn string_to_stream(source_str: String) -> TokenStream { let ps = ParseSess::new(FilePathMapping::empty()); source_file_to_stream( @@ -42,7 +42,7 @@ crate fn string_to_stream(source_str: String) -> TokenStream { ), None).0 } -/// Parse a string, return a crate. +/// Parses a string, returns a crate. crate fn string_to_crate(source_str : String) -> ast::Crate { let ps = ParseSess::new(FilePathMapping::empty()); with_error_checking_parse(source_str, &ps, |p| { @@ -63,8 +63,8 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { (None, None) => return true, (None, _) => return false, (Some(&a), None) => { - if is_pattern_whitespace(a) { - break // trailing whitespace check is out of loop for borrowck + if rustc_lexer::is_whitespace(a) { + break // Trailing whitespace check is out of loop for borrowck. } else { return false } @@ -72,12 +72,12 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { (Some(&a), Some(&b)) => (a, b) }; - if is_pattern_whitespace(a) && is_pattern_whitespace(b) { - // skip whitespace for a and b + if rustc_lexer::is_whitespace(a) && rustc_lexer::is_whitespace(b) { + // Skip whitespace for `a` and `b`. scan_for_non_ws_or_end(&mut a_iter); scan_for_non_ws_or_end(&mut b_iter); - } else if is_pattern_whitespace(a) { - // skip whitespace for a + } else if rustc_lexer::is_whitespace(a) { + // Skip whitespace for `a`. scan_for_non_ws_or_end(&mut a_iter); } else if a == b { a_iter.next(); @@ -87,22 +87,18 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { } } - // check if a has *only* trailing whitespace - a_iter.all(is_pattern_whitespace) + // Check if a has *only* trailing whitespace. + a_iter.all(rustc_lexer::is_whitespace) } -/// Advances the given peekable `Iterator` until it reaches a non-whitespace character +/// Advances the given peekable `Iterator` until it reaches a non-whitespace character. fn scan_for_non_ws_or_end>(iter: &mut Peekable) { - while iter.peek().copied().map(|c| is_pattern_whitespace(c)) == Some(true) { + while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) { iter.next(); } } -fn is_pattern_whitespace(c: char) -> bool { - rustc_lexer::character_properties::is_whitespace(c) -} - -/// Identify a position in the text by the Nth occurrence of a string. +/// Identifies a position in the text by the n'th occurrence of a string. struct Position { string: &'static str, count: usize, @@ -144,11 +140,15 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & println!("text: {:?}", source_map.span_to_snippet(span)); } - let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), - Some(source_map.clone()), - false, - false, - false); + let emitter = EmitterWriter::new( + Box::new(Shared { data: output.clone() }), + Some(source_map.clone()), + false, + false, + false, + None, + false, + ); let handler = Handler::with_emitter(true, None, Box::new(emitter)); handler.span_err(msp, "foo"); @@ -169,7 +169,7 @@ fn make_span(file_text: &str, start: &Position, end: &Position) -> Span { let start = make_pos(file_text, start); let end = make_pos(file_text, end) + end.string.len(); // just after matching thing ends assert!(start <= end); - Span::new(BytePos(start as u32), BytePos(end as u32), NO_EXPANSION) + Span::with_root_ctxt(BytePos(start as u32), BytePos(end as u32)) } fn make_pos(file_text: &str, pos: &Position) -> usize { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 6ff8898fe2..d702038f54 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -6,7 +6,7 @@ //! //! ## Ownership //! -//! `TokenStreams` are persistent data structures constructed as ropes with reference +//! `TokenStream`s are persistent data structures constructed as ropes with reference //! counted-children. In general, this means that calling an operation on a `TokenStream` //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to //! the original. This essentially coerces `TokenStream`s into 'views' of their subparts, @@ -19,7 +19,7 @@ use crate::parse::Directory; use crate::parse::token::{self, DelimToken, Token, TokenKind}; use crate::print::pprust; -use syntax_pos::{BytePos, ExpnId, Span, DUMMY_SP}; +use syntax_pos::{BytePos, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; @@ -147,9 +147,8 @@ impl TokenTree { } } -/// # Token Streams -/// /// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s. +/// /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. @@ -304,7 +303,7 @@ impl TokenStream { Cursor::new(self) } - /// Compares two TokenStreams, checking equality without regarding span information. + /// Compares two `TokenStream`s, checking equality without regarding span information. pub fn eq_unspanned(&self, other: &TokenStream) -> bool { let mut t1 = self.trees(); let mut t2 = other.trees(); @@ -414,7 +413,7 @@ impl TokenStreamBuilder { let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); if let Some(TokenTree::Token(last_token)) = last_tree_if_joint { if let Some((TokenTree::Token(token), is_joint)) = stream.first_tree_and_joint() { - if let Some(glued_tok) = last_token.glue(token) { + if let Some(glued_tok) = last_token.glue(&token) { let last_stream = self.0.pop().unwrap(); self.push_all_but_last_tree(&last_stream); let glued_tt = TokenTree::Token(glued_tok); @@ -506,7 +505,7 @@ impl Cursor { impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&pprust::tokens_to_string(self.clone())) + f.write_str(&pprust::tts_to_string(self.clone())) } } @@ -547,11 +546,4 @@ impl DelimSpan { pub fn entire(self) -> Span { self.open.with_hi(self.close.hi()) } - - pub fn apply_mark(self, expn_id: ExpnId) -> Self { - DelimSpan { - open: self.open.apply_mark(expn_id), - close: self.close.apply_mark(expn_id), - } - } } diff --git a/src/libsyntax/tokenstream/tests.rs b/src/libsyntax/tokenstream/tests.rs index 72e22a4987..5017e5f542 100644 --- a/src/libsyntax/tokenstream/tests.rs +++ b/src/libsyntax/tokenstream/tests.rs @@ -3,14 +3,14 @@ use super::*; use crate::ast::Name; use crate::with_default_globals; use crate::tests::string_to_stream; -use syntax_pos::{Span, BytePos, NO_EXPANSION}; +use syntax_pos::{Span, BytePos}; fn string_to_ts(string: &str) -> TokenStream { string_to_stream(string.to_owned()) } fn sp(a: u32, b: u32) -> Span { - Span::new(BytePos(a), BytePos(b), NO_EXPANSION) + Span::with_root_ctxt(BytePos(a), BytePos(b)) } #[test] diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index f17eb3b394..a64fec7096 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -93,8 +93,7 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_poly_trait_ref(self, t, m) } - fn visit_variant_data(&mut self, s: &VariantData, _: Ident, - _: &Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &VariantData) { self.count += 1; walk_struct_def(self, s) } @@ -107,9 +106,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_enum_def(self, enum_definition, generics, item_id) } - fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) { + fn visit_variant(&mut self, v: &Variant) { self.count += 1; - walk_variant(self, v, g, item_id) + walk_variant(self, v) } fn visit_lifetime(&mut self, lifetime: &Lifetime) { self.count += 1; diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index d71358f45c..fceaed360c 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -69,7 +69,7 @@ pub enum Fixity { impl AssocOp { /// Creates a new AssocOP from a token - pub fn from_token(t: &Token) -> Option { + crate fn from_token(t: &Token) -> Option { use AssocOp::*; match t.kind { token::BinOpEq(k) => Some(AssignOp(k)), @@ -97,6 +97,8 @@ impl AssocOp { // DotDotDot is no longer supported, but we need some way to display the error token::DotDotDot => Some(DotDotEq), token::Colon => Some(Colon), + // `<-` should probably be `< -` + token::LArrow => Some(Less), _ if t.is_keyword(kw::As) => Some(As), _ => None } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 596c5b46b9..d7c537be89 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -21,13 +21,13 @@ use syntax_pos::Span; #[derive(Copy, Clone)] pub enum FnKind<'a> { - /// fn foo() or extern "Abi" fn foo() + /// E.g., `fn foo()` or `extern "Abi" fn foo()`. ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), - /// fn foo(&self) + /// E.g., `fn foo(&self)`. Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), - /// |x, y| body + /// E.g., `|x, y| body`. Closure(&'a Expr), } @@ -41,7 +41,7 @@ impl<'a> FnKind<'a> { } } -/// Each method of the Visitor trait is a hook to be potentially +/// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; /// e.g., the `visit_mod` method by default calls `visit::walk_mod`. @@ -66,7 +66,7 @@ pub trait Visitor<'ast>: Sized { fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) } fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) } fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) } - fn visit_arg(&mut self, arg: &'ast Arg) { walk_arg(self, arg) } + fn visit_param(&mut self, param: &'ast Param) { walk_param(self, param) } fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) } fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) } @@ -92,8 +92,7 @@ pub trait Visitor<'ast>: Sized { fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { walk_poly_trait_ref(self, t, m) } - fn visit_variant_data(&mut self, s: &'ast VariantData, _: Ident, - _: &'ast Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &'ast VariantData) { walk_struct_def(self, s) } fn visit_struct_field(&mut self, s: &'ast StructField) { walk_struct_field(self, s) } @@ -101,8 +100,8 @@ pub trait Visitor<'ast>: Sized { generics: &'ast Generics, item_id: NodeId, _: Span) { walk_enum_def(self, enum_definition, generics, item_id) } - fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) { - walk_variant(self, v, g, item_id) + fn visit_variant(&mut self, v: &'ast Variant) { + walk_variant(self, v) } fn visit_label(&mut self, label: &'ast Label) { walk_label(self, label) @@ -163,6 +162,12 @@ pub trait Visitor<'ast>: Sized { fn visit_fn_header(&mut self, _header: &'ast FnHeader) { // Nothing to do } + fn visit_field(&mut self, f: &'ast Field) { + walk_field(self, f) + } + fn visit_field_pattern(&mut self, fp: &'ast FieldPat) { + walk_field_pattern(self, fp) + } } #[macro_export] @@ -280,8 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::Struct(ref struct_definition, ref generics) | ItemKind::Union(ref struct_definition, ref generics) => { visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition, item.ident, - generics, item.id, item.span); + visitor.visit_variant_data(struct_definition); } ItemKind::Trait(.., ref generics, ref bounds, ref methods) => { visitor.visit_generics(generics); @@ -298,24 +302,34 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { walk_list!(visitor, visit_attribute, &item.attrs); } -pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, - enum_definition: &'a EnumDef, - generics: &'a Generics, - item_id: NodeId) { - walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id); +pub fn walk_enum_def<'a, V: Visitor<'a>>( + visitor: &mut V, + enum_definition: &'a EnumDef, + _: &'a Generics, + _: NodeId, +) { + walk_list!(visitor, visit_variant, &enum_definition.variants); } -pub fn walk_variant<'a, V>(visitor: &mut V, - variant: &'a Variant, - generics: &'a Generics, - item_id: NodeId) +pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) where V: Visitor<'a>, { - visitor.visit_ident(variant.node.ident); - visitor.visit_variant_data(&variant.node.data, variant.node.ident, - generics, item_id, variant.span); - walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); + visitor.visit_ident(variant.ident); + visitor.visit_variant_data(&variant.data); + walk_list!(visitor, visit_anon_const, &variant.disr_expr); + walk_list!(visitor, visit_attribute, &variant.attrs); +} + +pub fn walk_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a Field) { + visitor.visit_expr(&f.expr); + visitor.visit_ident(f.ident); + walk_list!(visitor, visit_attribute, f.attrs.iter()); +} + +pub fn walk_field_pattern<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a FieldPat) { + visitor.visit_ident(fp.ident); + visitor.visit_pat(&fp.pat); + walk_list!(visitor, visit_attribute, fp.attrs.iter()); } pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { @@ -330,7 +344,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { walk_list!(visitor, visit_lifetime, opt_lifetime); visitor.visit_ty(&mutable_type.ty) } - TyKind::Never | TyKind::CVarArgs => {} TyKind::Tup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } @@ -359,6 +372,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Mac(ref mac) => { visitor.visit_mac(mac) } + TyKind::Never | + TyKind::CVarArgs => {} } } @@ -374,7 +389,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>( visitor.visit_path(&use_tree.prefix, id); match use_tree.kind { UseTreeKind::Simple(rename, ..) => { - // the extra IDs are handled during HIR lowering + // The extra IDs are handled during HIR lowering. if let Some(rename) = rename { visitor.visit_ident(rename); } @@ -441,14 +456,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } PatKind::Struct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.node.attrs.iter()); - visitor.visit_ident(field.node.ident); - visitor.visit_pat(&field.node.pat) - } - } - PatKind::Tuple(ref elems) => { - walk_list!(visitor, visit_pat, elems); + walk_list!(visitor, visit_field_pattern, fields); } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) | @@ -465,7 +473,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_expr(upper_bound); } PatKind::Wild | PatKind::Rest => {}, - PatKind::Slice(ref elems) => { + PatKind::Tuple(ref elems) + | PatKind::Slice(ref elems) + | PatKind::Or(ref elems) => { walk_list!(visitor, visit_pat, elems); } PatKind::Mac(ref mac) => visitor.visit_mac(mac), @@ -548,8 +558,8 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR } pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { - for arg in &function_declaration.inputs { - visitor.visit_arg(arg); + for param in &function_declaration.inputs { + visitor.visit_param(param); } visitor.visit_fn_ret_ty(&function_declaration.output); } @@ -663,7 +673,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { } pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) { - visitor.visit_path(&mac.node.path, DUMMY_NODE_ID); + visitor.visit_path(&mac.path, DUMMY_NODE_ID); } pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { @@ -671,9 +681,8 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo } pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { - for attr in expression.attrs.iter() { - visitor.visit_attribute(attr); - } + walk_list!(visitor, visit_attribute, expression.attrs.iter()); + match expression.node { ExprKind::Box(ref subexpression) => { visitor.visit_expr(subexpression) @@ -687,11 +696,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Struct(ref path, ref fields, ref optional_base) => { visitor.visit_path(path, expression.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.attrs.iter()); - visitor.visit_ident(field.ident); - visitor.visit_expr(&field.expr) - } + walk_list!(visitor, visit_field, fields); walk_list!(visitor, visit_expr, optional_base); } ExprKind::Tup(ref subexpressions) => { @@ -716,8 +721,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(subexpression); visitor.visit_ty(typ) } - ExprKind::Let(ref pats, ref scrutinee) => { - walk_list!(visitor, visit_pat, pats); + ExprKind::Let(ref pat, ref scrutinee) => { + visitor.visit_pat(pat); visitor.visit_expr(scrutinee); } ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { @@ -821,17 +826,17 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr_post(expression) } -pub fn walk_arg<'a, V: Visitor<'a>>(visitor: &mut V, arg: &'a Arg) { - walk_list!(visitor, visit_attribute, arg.attrs.iter()); - visitor.visit_pat(&arg.pat); - visitor.visit_ty(&arg.ty); +pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { + walk_list!(visitor, visit_attribute, param.attrs.iter()); + visitor.visit_pat(¶m.pat); + visitor.visit_ty(¶m.ty); } pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { - walk_list!(visitor, visit_pat, &arm.pats); - if let Some(ref e) = &arm.guard { - visitor.visit_expr(e); - } + visitor.visit_pat(&arm.pat); + // NOTE(or_patterns; Centril | dlrobertson): + // If you change this, also change the hack in `lowering.rs`. + walk_list!(visitor, visit_expr, &arm.guard); visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 73310df305..791ee94b4f 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -18,3 +18,4 @@ rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +rustc_lexer = { path = "../librustc_lexer" } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index c1c2732605..75d727b9fb 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -8,13 +8,12 @@ use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base::{self, *}; -use syntax::parse; use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax::ast::AsmDialect; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::{self, TokenStream}; use syntax::{span_err, struct_span_err}; enum State { @@ -43,14 +42,14 @@ const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let mut inline_asm = match parse_inline_asm(cx, sp, tts) { Ok(Some(inline_asm)) => inline_asm, - Ok(None) => return DummyResult::expr(sp), + Ok(None) => return DummyResult::any(sp), Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; @@ -63,7 +62,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp, + span: cx.with_def_site_ctxt(sp), attrs: ThinVec::new(), })) } @@ -71,20 +70,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, fn parse_inline_asm<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Result, DiagnosticBuilder<'a>> { // Split the tts before the first colon, to avoid `asm!("x": y)` being // parsed as `asm!(z)` with `z = "x": y` which is type ascription. - let first_colon = tts.iter() + let first_colon = tts.trees() .position(|tt| { - match *tt { + match tt { tokenstream::TokenTree::Token(Token { kind: token::Colon, .. }) | tokenstream::TokenTree::Token(Token { kind: token::ModSep, .. }) => true, _ => false, } }) .unwrap_or(tts.len()); - let mut p = cx.new_parser_from_tts(&tts[first_colon..]); + let mut p = cx.new_parser_from_tts(tts.trees().skip(first_colon).collect()); let mut asm = kw::Invalid; let mut asm_str_style = None; let mut outputs = Vec::new(); @@ -110,7 +109,8 @@ fn parse_inline_asm<'a>( )); } // Nested parser, stop before the first colon (see above). - let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]); + let mut p2 = + cx.new_parser_from_tts(tts.trees().take(first_colon).collect()); if p2.token == token::Eof { let mut err = @@ -129,12 +129,8 @@ fn parse_inline_asm<'a>( // This is most likely malformed. if p2.token != token::Eof { let mut extra_tts = p2.parse_all_token_trees()?; - extra_tts.extend(tts[first_colon..].iter().cloned()); - p = parse::stream_to_parser( - cx.parse_sess, - extra_tts.into_iter().collect(), - Some("inline assembly"), - ); + extra_tts.extend(tts.trees().skip(first_colon)); + p = cx.new_parser_from_tts(extra_tts.into_iter().collect()); } asm = s; @@ -277,6 +273,5 @@ fn parse_inline_asm<'a>( volatile, alignstack, dialect, - ctxt: cx.backtrace(), })) } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index d7571f43ed..cbfe14fa43 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -1,7 +1,6 @@ use errors::{Applicability, DiagnosticBuilder}; use syntax::ast::{self, *}; -use syntax::source_map::Spanned; use syntax::ext::base::*; use syntax::parse::token::{self, TokenKind}; use syntax::parse::parser::Parser; @@ -14,18 +13,20 @@ use syntax_pos::{Span, DUMMY_SP}; pub fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[TokenTree], + tts: TokenStream, ) -> Box { let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) { Ok(assert) => assert, Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; - let sp = sp.apply_mark(cx.current_expansion.id); - let panic_call = Mac_ { + // `core::panic` and `std::panic` are different macros, so we use call-site + // context to pick up whichever is currently in scope. + let sp = cx.with_call_site_ctxt(sp); + let panic_call = Mac { path: Path::from_ident(Ident::new(sym::panic, sp)), tts: custom_message.unwrap_or_else(|| { TokenStream::from(TokenTree::token( @@ -37,6 +38,7 @@ pub fn expand_assert<'cx>( )) }).into(), delim: MacDelimiter::Parenthesis, + span: sp, prior_type_ascription: None, }; let if_expr = cx.expr_if( @@ -44,10 +46,7 @@ pub fn expand_assert<'cx>( cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), cx.expr( sp, - ExprKind::Mac(Spanned { - span: sp, - node: panic_call, - }), + ExprKind::Mac(panic_call), ), None, ); @@ -62,9 +61,9 @@ struct Assert { fn parse_assert<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[TokenTree] + stream: TokenStream ) -> Result> { - let mut parser = cx.new_parser_from_tts(tts); + let mut parser = cx.new_parser_from_tts(stream); if parser.token == token::Eof { let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument"); diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 84830e6ddd..3c33baf95a 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -7,16 +7,16 @@ use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base::{self, *}; use syntax::attr; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use syntax::parse::token; use syntax_pos::Span; pub fn expand_cfg( cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_def_site_ctxt(sp); match parse_cfg(cx, sp, tts) { Ok(cfg) => { @@ -25,7 +25,7 @@ pub fn expand_cfg( } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } @@ -33,7 +33,7 @@ pub fn expand_cfg( fn parse_cfg<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Result> { let mut p = cx.new_parser_from_tts(tts); diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs new file mode 100644 index 0000000000..bb8e3df3db --- /dev/null +++ b/src/libsyntax_ext/cmdline_attrs.rs @@ -0,0 +1,30 @@ +//! Attributes injected into the crate root from command line using `-Z crate-attr`. + +use syntax::ast::{self, AttrStyle}; +use syntax::attr::mk_attr; +use syntax::panictry; +use syntax::parse::{self, token, ParseSess}; +use syntax_pos::FileName; + +pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { + for raw_attr in attrs { + let mut parser = parse::new_parser_from_source_str( + parse_sess, + FileName::cli_crate_attr_source_code(&raw_attr), + raw_attr.clone(), + ); + + let start_span = parser.token.span; + let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted()); + let end_span = parser.token.span; + if parser.token != token::Eof { + parse_sess.span_diagnostic + .span_err(start_span.to(end_span), "invalid crate attribute"); + continue; + } + + krate.attrs.push(mk_attr(AttrStyle::Inner, path, tokens, start_span.to(end_span))); + } + + krate +} diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs index 59d3f2c9c7..24f3a66d4a 100644 --- a/src/libsyntax_ext/compile_error.rs +++ b/src/libsyntax_ext/compile_error.rs @@ -2,11 +2,11 @@ use syntax::ext::base::{self, *}; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { None => return DummyResult::any(sp), diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index f1d079eb05..16f016036e 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -1,18 +1,18 @@ use syntax::ast; -use syntax::ext::base; +use syntax::ext::base::{self, DummyResult}; use syntax::symbol::Symbol; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use std::string::String; -pub fn expand_syntax_ext( +pub fn expand_concat( cx: &mut base::ExtCtxt<'_>, sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, - None => return base::DummyResult::expr(sp), + None => return DummyResult::any(sp), }; let mut accumulator = String::new(); let mut missing_literal = vec![]; @@ -55,10 +55,10 @@ pub fn expand_syntax_ext( let mut err = cx.struct_span_err(missing_literal, "expected a literal"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } else if has_errors { - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_def_site_ctxt(sp); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 8184fc4426..f344706d4e 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -6,21 +6,21 @@ use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax_pos::Span; use syntax_pos::symbol::Symbol; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; -pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[TokenTree]) - -> Box { +pub fn expand_concat_idents<'cx>(cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream) + -> Box { if tts.is_empty() { cx.span_err(sp, "concat_idents! takes 1 or more arguments."); return DummyResult::any(sp); } let mut res_str = String::new(); - for (i, e) in tts.iter().enumerate() { + for (i, e) in tts.into_trees().enumerate() { if i & 1 == 1 { - match *e { + match e { TokenTree::Token(Token { kind: token::Comma, .. }) => {} _ => { cx.span_err(sp, "concat_idents! expecting comma."); @@ -28,7 +28,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, } } } else { - match *e { + match e { TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => res_str.push_str(&name.as_str()), _ => { @@ -39,7 +39,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, } } - let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.id)); + let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp)); struct ConcatIdentsResult { ident: ast::Ident } diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 3b1edf90d6..9a4c540dc6 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -35,7 +35,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>, match annitem.node { ItemKind::Struct(_, Generics { ref params, .. }) | ItemKind::Enum(_, Generics { ref params, .. }) => { - let container_id = cx.current_expansion.id.parent(); + let container_id = cx.current_expansion.id.expn_data().parent; if cx.resolver.has_derives(container_id, SpecialDerives::COPY) && !params.iter().any(|param| match param.kind { ast::GenericParamKind::Type { .. } => true, @@ -112,10 +112,10 @@ fn cs_clone_shallow(name: &str, ty: P, span: Span, helper_name: &str) { // Generate statement `let _: helper_name;`, // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(&[sym::clone, Symbol::intern(helper_name)]), - vec![GenericArg::Type(ty)], vec![]); + vec![GenericArg::Type(ty)]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt<'_>, stmts: &mut Vec, variant: &VariantData) { @@ -129,7 +129,7 @@ fn cs_clone_shallow(name: &str, if is_union { // let _: AssertParamIsCopy; let self_ty = - cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_empty_ctxt(kw::SelfUpper))); + cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_dummy_span(kw::SelfUpper))); assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy"); } else { match *substr.fields { @@ -138,7 +138,7 @@ fn cs_clone_shallow(name: &str, } StaticEnum(enum_def, ..) => { for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); + process_variant(cx, &mut stmts, &variant.data); } } _ => cx.span_bug(trait_span, &format!("unexpected substructure in \ @@ -170,9 +170,9 @@ fn cs_clone(name: &str, vdata = vdata_; } EnumMatching(.., variant, ref af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]); + ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); all_fields = af; - vdata = &variant.node.data; + vdata = &variant.data; } EnumNonMatchingCollapsed(..) => { cx.span_bug(trait_span, diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 1909729f4a..c92339dd2f 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -2,7 +2,7 @@ use crate::deriving::path_std; use crate::deriving::generic::*; use crate::deriving::generic::ty::*; -use syntax::ast::{self, Expr, MetaItem, GenericArg}; +use syntax::ast::{self, Ident, Expr, MetaItem, GenericArg}; use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::ptr::P; use syntax::symbol::{sym, Symbol}; @@ -13,11 +13,11 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>, mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { - cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::EQ); + cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::EQ); let inline = cx.meta_word(span, sym::inline); - let hidden = cx.meta_list_item_word(span, sym::hidden); - let doc = cx.meta_list(span, sym::doc, vec![hidden]); + let hidden = syntax::attr::mk_nested_word_item(Ident::new(sym::hidden, span)); + let doc = syntax::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]); let attrs = vec![cx.attribute(inline), cx.attribute(doc)]; let trait_def = TraitDef { span, @@ -53,10 +53,10 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>, ty: P, span: Span, helper_name: &str) { // Generate statement `let _: helper_name;`, // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]), - vec![GenericArg::Type(ty)], vec![]); + vec![GenericArg::Type(ty)]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt<'_>, @@ -75,7 +75,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>, } StaticEnum(enum_def, ..) => { for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); + process_variant(cx, &mut stmts, &variant.data); } } _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`") diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 885cfee356..1f4f5aa370 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -43,17 +43,18 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>, } -pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - self_arg_tags: &[ast::Ident]) - -> P { +pub fn ordering_collapsed( + cx: &mut ExtCtxt<'_>, + span: Span, + self_arg_tags: &[ast::Ident], +) -> P { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) + cx.expr_method_call(span, lft, ast::Ident::new(sym::cmp, span), vec![rgt]) } pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - let test_id = cx.ident_of("cmp").gensym(); + let test_id = ast::Ident::new(sym::cmp, span); let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); @@ -75,34 +76,32 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< // as the outermost one, and the last as the innermost. false, |cx, span, old, self_f, other_fs| { - // match new { - // ::std::cmp::Ordering::Equal => old, - // cmp => cmp - // } + // match new { + // ::std::cmp::Ordering::Equal => old, + // cmp => cmp + // } - let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), - }; + let new = { + let other_f = match other_fs { + [o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), + }; - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; - cx.expr_call_global(span, cmp_path.clone(), args) - }; + cx.expr_call_global(span, cmp_path.clone(), args) + }; - let eq_arm = cx.arm(span, - vec![cx.pat_path(span, equals_path.clone())], - old); - let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], - cx.expr_ident(span, test_id)); + let eq_arm = cx.arm(span, cx.pat_path(span, equals_path.clone()), old); + let neq_arm = cx.arm(span, + cx.pat_ident(span, test_id), + cx.expr_ident(span, test_id)); - cx.expr_match(span, new, vec![eq_arm, neq_arm]) - }, + cx.expr_match(span, new, vec![eq_arm, neq_arm]) + }, cx.expr_path(equals_path.clone()), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 7d7c4ae22a..91e1e80e4f 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -13,7 +13,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>, mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { - cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::PARTIAL_EQ); + cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::PARTIAL_EQ); // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 0ec30f5924..13d63aaf2a 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -94,11 +94,12 @@ pub enum OrderingOp { GeOp, } -pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - op: OrderingOp, - self_arg_tags: &[ast::Ident]) - -> P { +pub fn some_ordering_collapsed( + cx: &mut ExtCtxt<'_>, + span: Span, + op: OrderingOp, + self_arg_tags: &[ast::Ident], +) -> P { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); let op_str = match op { @@ -108,11 +109,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>, GtOp => "gt", GeOp => "ge", }; - cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) + cx.expr_method_call(span, lft, cx.ident_of(op_str, span), vec![rgt]) } pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - let test_id = cx.ident_of("cmp").gensym(); + let test_id = ast::Ident::new(sym::cmp, span); let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let ordering_expr = cx.expr_path(ordering.clone()); let equals_expr = cx.expr_some(span, ordering_expr); @@ -159,10 +160,10 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ }; let eq_arm = cx.arm(span, - vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))], + cx.pat_some(span, cx.pat_path(span, ordering.clone())), old); let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], + cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); cx.expr_match(span, new, vec![eq_arm, neq_arm]) diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 0f709630bf..088b61be8b 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -53,16 +53,16 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // based on the "shape". let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (substr.type_ident, *vdata, fields), - EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields), + EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), }; // We want to make sure we have the ctxt set so that we can use unstable methods - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); - let builder = Ident::from_str("debug_trait_builder").gensym(); + let builder = cx.ident_of("debug_trait_builder", span); let builder_expr = cx.expr_ident(span, builder.clone()); let fmt = substr.nonself_args[0].clone(); @@ -72,8 +72,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { // tuple struct/"normal" variant let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]); + stmts.push(cx.stmt_let(span, true, builder, expr)); for field in fields { // Use double indirection to make sure this works for unsized types @@ -82,7 +82,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let expr = cx.expr_method_call(span, builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), + Ident::new(sym::field, span), vec![field]); // Use `let _ = expr;` to avoid triggering the @@ -93,7 +93,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> ast::VariantData::Struct(..) => { // normal struct/struct variant let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); + cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]); stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); for field in fields { @@ -106,14 +106,14 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let field = cx.expr_addr_of(field.span, field); let expr = cx.expr_method_call(span, builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), + Ident::new(sym::field, span), vec![name, field]); stmts.push(stmt_let_undescore(cx, span, expr)); } } } - let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]); + let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]); stmts.push(cx.stmt_expr(expr)); let block = cx.block(span, stmts); diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 293c5a1e7e..cde72abbde 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -1,6 +1,6 @@ -//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more. +//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more. -use crate::deriving::{self, pathvec_std}; +use crate::deriving::pathvec_std; use crate::deriving::generic::*; use crate::deriving::generic::ty::*; @@ -17,7 +17,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { let krate = "rustc_serialize"; - let typaram = &*deriving::hygienic_type_parameter(item, "__D"); + let typaram = "__D"; let trait_def = TraitDef { span, @@ -66,10 +66,14 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>, krate: &str) -> P { let decoder = substr.nonself_args[0].clone(); - let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")]; + let recurse = vec![ + cx.ident_of(krate, trait_span), + cx.ident_of("Decodable", trait_span), + cx.ident_of("decode", trait_span), + ]; let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse)); // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_d"); + let blkarg = cx.ident_of("_d", trait_span); let blkdecoder = cx.expr_ident(trait_span, blkarg); return match *substr.fields { @@ -78,7 +82,7 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>, Unnamed(ref fields, _) => fields.len(), Named(ref fields) => fields.len(), }; - let read_struct_field = cx.ident_of("read_struct_field"); + let read_struct_field = cx.ident_of("read_struct_field", trait_span); let path = cx.path_ident(trait_span, substr.type_ident); let result = @@ -94,17 +98,17 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>, let result = cx.expr_ok(trait_span, result); cx.expr_method_call(trait_span, decoder, - cx.ident_of("read_struct"), + cx.ident_of("read_struct", trait_span), vec![cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, nfields), cx.lambda1(trait_span, result, blkarg)]) } StaticEnum(_, ref fields) => { - let variant = cx.ident_of("i"); + let variant = cx.ident_of("i", trait_span); let mut arms = Vec::with_capacity(fields.len() + 1); let mut variants = Vec::with_capacity(fields.len()); - let rvariant_arg = cx.ident_of("read_enum_variant_arg"); + let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span); for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { variants.push(cx.expr_str(v_span, ident.name)); @@ -119,9 +123,7 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>, vec![idx, exprdecode.clone()])) }); - arms.push(cx.arm(v_span, - vec![cx.pat_lit(v_span, cx.expr_usize(v_span, i))], - decoded)); + arms.push(cx.arm(v_span, cx.pat_lit(v_span, cx.expr_usize(v_span, i)), decoded)); } arms.push(cx.arm_unreachable(trait_span)); @@ -134,11 +136,11 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>, let variant_vec = cx.expr_addr_of(trait_span, variant_vec); let result = cx.expr_method_call(trait_span, blkdecoder, - cx.ident_of("read_enum_variant"), + cx.ident_of("read_enum_variant", trait_span), vec![variant_vec, lambda]); cx.expr_method_call(trait_span, decoder, - cx.ident_of("read_enum"), + cx.ident_of("read_enum", trait_span), vec![cx.expr_str(trait_span, substr.type_ident.name), cx.lambda1(trait_span, result, blkarg)]) } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 6d0d3b96a5..655d3bb7c4 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -1,11 +1,12 @@ -//! The compiler code necessary to implement the `#[derive(Encodable)]` -//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that -//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`. +//! The compiler code necessary to implement the `#[derive(RustcEncodable)]` +//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that +//! type-defining items may be tagged with +//! `#[derive(RustcEncodable, RustcDecodable)]`. //! //! For example, a type like: //! //! ``` -//! #[derive(Encodable, Decodable)] +//! #[derive(RustcEncodable, RustcDecodable)] //! struct Node { id: usize } //! ``` //! @@ -40,15 +41,17 @@ //! references other non-built-in types. A type definition like: //! //! ``` -//! # #[derive(Encodable, Decodable)] struct Span; -//! #[derive(Encodable, Decodable)] +//! # #[derive(RustcEncodable, RustcDecodable)] +//! # struct Span; +//! #[derive(RustcEncodable, RustcDecodable)] //! struct Spanned { node: T, span: Span } //! ``` //! //! would yield functions like: //! //! ``` -//! # #[derive(Encodable, Decodable)] struct Span; +//! # #[derive(RustcEncodable, RustcDecodable)] +//! # struct Span; //! # struct Spanned { node: T, span: Span } //! impl< //! S: Encoder, @@ -82,7 +85,7 @@ //! } //! ``` -use crate::deriving::{self, pathvec_std}; +use crate::deriving::pathvec_std; use crate::deriving::generic::*; use crate::deriving::generic::ty::*; @@ -98,7 +101,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { let krate = "rustc_serialize"; - let typaram = &*deriving::hygienic_type_parameter(item, "__S"); + let typaram = "__S"; let trait_def = TraitDef { span, @@ -150,16 +153,16 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, -> P { let encoder = substr.nonself_args[0].clone(); // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_e"); + let blkarg = cx.ident_of("_e", trait_span); let blkencoder = cx.expr_ident(trait_span, blkarg); let fn_path = cx.expr_path(cx.path_global(trait_span, - vec![cx.ident_of(krate), - cx.ident_of("Encodable"), - cx.ident_of("encode")])); + vec![cx.ident_of(krate, trait_span), + cx.ident_of("Encodable", trait_span), + cx.ident_of("encode", trait_span)])); return match *substr.fields { Struct(_, ref fields) => { - let emit_struct_field = cx.ident_of("emit_struct_field"); + let emit_struct_field = cx.ident_of("emit_struct_field", trait_span); let mut stmts = Vec::new(); for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { let name = match name { @@ -198,7 +201,7 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, cx.expr_method_call(trait_span, encoder, - cx.ident_of("emit_struct"), + cx.ident_of("emit_struct", trait_span), vec![cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, fields.len()), blk]) @@ -211,7 +214,7 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, // actually exist. let me = cx.stmt_let(trait_span, false, blkarg, encoder); let encoder = cx.expr_ident(trait_span, blkarg); - let emit_variant_arg = cx.ident_of("emit_enum_variant_arg"); + let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span); let mut stmts = Vec::new(); if !fields.is_empty() { let last = fields.len() - 1; @@ -238,10 +241,10 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, } let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); - let name = cx.expr_str(trait_span, variant.node.ident.name); + let name = cx.expr_str(trait_span, variant.ident.name); let call = cx.expr_method_call(trait_span, blkencoder, - cx.ident_of("emit_enum_variant"), + cx.ident_of("emit_enum_variant", trait_span), vec![name, cx.expr_usize(trait_span, idx), cx.expr_usize(trait_span, fields.len()), @@ -249,7 +252,7 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, let blk = cx.lambda1(trait_span, call, blkarg); let ret = cx.expr_method_call(trait_span, encoder, - cx.ident_of("emit_enum"), + cx.ident_of("emit_enum", trait_span), vec![cx.expr_str(trait_span ,substr.type_ident.name), blk]); cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 7e6d9126c8..fec035d331 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -187,7 +187,7 @@ use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; -use syntax::source_map::{self, respan}; +use syntax::source_map::respan; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; use syntax::symbol::{Symbol, kw, sym}; @@ -237,7 +237,7 @@ pub struct MethodDef<'a> { /// Whether there is a self argument (outer Option) i.e., whether /// this is a static function, and whether it is a pointer (inner /// Option) - pub explicit_self: Option>>, + pub explicit_self: Option>, /// Arguments other than the self argument pub args: Vec<(Ty<'a>, &'a str)>, @@ -425,7 +425,7 @@ impl<'a> TraitDef<'a> { return; } }; - let container_id = cx.current_expansion.id.parent(); + let container_id = cx.current_expansion.id.expn_data().parent; let is_always_copy = cx.resolver.has_derives(container_id, SpecialDerives::COPY) && has_no_type_params; @@ -664,7 +664,7 @@ impl<'a> TraitDef<'a> { }).collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]); + let path = cx.path_all(self.span, false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived)); @@ -672,8 +672,11 @@ impl<'a> TraitDef<'a> { attr::mark_used(&attr); let opt_trait_ref = Some(trait_ref); let unused_qual = { - let word = cx.meta_list_item_word(self.span, Symbol::intern("unused_qualifications")); - cx.attribute(cx.meta_list(self.span, sym::allow, vec![word])) + let word = syntax::attr::mk_nested_word_item( + Ident::new(Symbol::intern("unused_qualifications"), self.span)); + let list = syntax::attr::mk_list_item( + Ident::new(sym::allow, self.span), vec![word]); + cx.attribute(list) }; let mut a = vec![attr, unused_qual]; @@ -758,7 +761,7 @@ impl<'a> TraitDef<'a> { let mut field_tys = Vec::new(); for variant in &enum_def.variants { - field_tys.extend(variant.node + field_tys.extend(variant .data .fields() .iter() @@ -843,7 +846,7 @@ impl<'a> MethodDef<'a> { -> P { let substructure = Substructure { type_ident, - method_ident: cx.ident_of(self.name), + method_ident: cx.ident_of(self.name, trait_.span), self_args, nonself_args, fields, @@ -890,7 +893,7 @@ impl<'a> MethodDef<'a> { for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(name).gensym(); + let ident = cx.ident_of(name, trait_.span); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -928,17 +931,17 @@ impl<'a> MethodDef<'a> { let args = { let self_args = explicit_self.map(|explicit_self| { - let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span); - ast::Arg::from_self(ThinVec::default(), explicit_self, ident) + let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span); + ast::Param::from_self(ThinVec::default(), explicit_self, ident) }); let nonself_args = arg_types.into_iter() - .map(|(name, ty)| cx.arg(trait_.span, name, ty)); + .map(|(name, ty)| cx.param(trait_.span, name, ty)); self_args.into_iter().chain(nonself_args).collect() }; let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); - let method_ident = cx.ident_of(self.name); + let method_ident = cx.ident_of(self.name, trait_.span); let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); @@ -1071,7 +1074,7 @@ impl<'a> MethodDef<'a> { for (arg_expr, pat) in self_args.iter().zip(patterns) { body = cx.expr_match(trait_.span, arg_expr.clone(), - vec![cx.arm(trait_.span, vec![pat.clone()], body)]) + vec![cx.arm(trait_.span, pat.clone(), body)]) } body @@ -1201,7 +1204,7 @@ impl<'a> MethodDef<'a> { ).collect::>(); let self_arg_idents = self_arg_names.iter() - .map(|name| cx.ident_of(&name[..])) + .map(|name| cx.ident_of(name, sp)) .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to @@ -1210,7 +1213,7 @@ impl<'a> MethodDef<'a> { let vi_idents = self_arg_names.iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[..]); - cx.ident_of(&vi_suffix[..]).gensym() + cx.ident_of(&vi_suffix[..], trait_.span) }) .collect::>(); @@ -1220,7 +1223,7 @@ impl<'a> MethodDef<'a> { let catch_all_substructure = EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]); - let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty()); + let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); // These arms are of the form: // (Variant1, Variant1, ...) => Body1 @@ -1229,7 +1232,7 @@ impl<'a> MethodDef<'a> { // where each tuple has length = self_args.len() let mut match_arms: Vec = variants.iter() .enumerate() - .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty())) + .filter(|&(_, v)| !(self.unify_fieldless_variants && v.data.fields().is_empty())) .map(|(index, variant)| { let mk_self_pat = |cx: &mut ExtCtxt<'_>, self_arg_name: &str| { let (p, idents) = trait_.create_enum_variant_pattern(cx, @@ -1311,7 +1314,7 @@ impl<'a> MethodDef<'a> { nonself_args, &substructure); - cx.arm(sp, vec![single_pat], arm_expr) + cx.arm(sp, single_pat, arm_expr) }) .collect(); @@ -1337,7 +1340,7 @@ impl<'a> MethodDef<'a> { _ => None, }; if let Some(arm) = default { - match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm)); + match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm)); } // We will usually need the catch-all after matching the @@ -1387,7 +1390,10 @@ impl<'a> MethodDef<'a> { let variant_value = deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]); - let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); + let target_ty = cx.ty_ident( + sp, + cx.ident_of(target_type_name, sp), + ); let variant_disr = cx.expr_cast(sp, variant_value, target_ty); let let_stmt = cx.stmt_let(sp, false, ident, variant_disr); index_let_stmts.push(let_stmt); @@ -1513,8 +1519,8 @@ impl<'a> MethodDef<'a> { .iter() .map(|v| { let sp = v.span.with_ctxt(trait_.span.ctxt()); - let summary = trait_.summarise_struct(cx, &v.node.data); - (v.node.ident, sp, summary) + let summary = trait_.summarise_struct(cx, &v.data); + (v.ident, sp, summary) }) .collect(); self.call_substructure_method(cx, @@ -1588,7 +1594,7 @@ impl<'a> TraitDef<'a> { let mut ident_exprs = Vec::new(); for (i, struct_field) in struct_def.fields().iter().enumerate() { let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym(); + let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span); paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { @@ -1610,14 +1616,14 @@ impl<'a> TraitDef<'a> { if ident.is_none() { cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); } - source_map::Spanned { + ast::FieldPat { + ident: ident.unwrap(), + is_shorthand: false, + attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, span: pat.span.with_ctxt(self.span.ctxt()), - node: ast::FieldPat { - ident: ident.unwrap(), - pat, - is_shorthand: false, - attrs: ThinVec::new(), - }, + pat, + is_placeholder: false } }) .collect(); @@ -1643,9 +1649,9 @@ impl<'a> TraitDef<'a> { mutbl: ast::Mutability) -> (P, Vec<(Span, Option, P, &'a [ast::Attribute])>) { let sp = variant.span.with_ctxt(self.span.ctxt()); - let variant_path = cx.path(sp, vec![enum_ident, variant.node.ident]); + let variant_path = cx.path(sp, vec![enum_ident, variant.ident]); let use_temporaries = false; // enums can't be repr(packed) - self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl, + self.create_struct_pattern(cx, variant_path, &variant.data, prefix, mutbl, use_temporaries) } } @@ -1776,7 +1782,7 @@ pub fn is_type_without_fields(item: &Annotatable) -> bool { if let Annotatable::Item(ref item) = *item { match item.node { ast::ItemKind::Enum(ref enum_def, _) => { - enum_def.variants.iter().all(|v| v.node.data.fields().is_empty()) + enum_def.variants.iter().all(|v| v.data.fields().is_empty()) } ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(), _ => false, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 399829eaef..6ae02a5cab 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -13,9 +13,9 @@ use syntax_pos::symbol::kw; /// The types of pointers #[derive(Clone)] -pub enum PtrTy<'a> { +pub enum PtrTy { /// &'lifetime mut - Borrowed(Option<&'a str>, ast::Mutability), + Borrowed(Option, ast::Mutability), /// *mut #[allow(dead_code)] Raw(ast::Mutability), @@ -26,7 +26,7 @@ pub enum PtrTy<'a> { #[derive(Clone)] pub struct Path<'a> { path: Vec<&'a str>, - lifetime: Option<&'a str>, + lifetime: Option, params: Vec>>, kind: PathKind, } @@ -46,7 +46,7 @@ impl<'a> Path<'a> { Path::new_(vec![path], None, Vec::new(), PathKind::Local) } pub fn new_<'r>(path: Vec<&'r str>, - lifetime: Option<&'r str>, + lifetime: Option, params: Vec>>, kind: PathKind) -> Path<'r> { @@ -72,7 +72,7 @@ impl<'a> Path<'a> { self_ty: Ident, self_generics: &Generics) -> ast::Path { - let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect(); + let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); let tys: Vec> = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); @@ -82,12 +82,12 @@ impl<'a> Path<'a> { .collect(); match self.kind { - PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()), - PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()), + PathKind::Global => cx.path_all(span, true, idents, params), + PathKind::Local => cx.path_all(span, false, idents, params), PathKind::Std => { - let def_site = DUMMY_SP.apply_mark(cx.current_expansion.id); + let def_site = cx.with_def_site_ctxt(DUMMY_SP); idents.insert(0, Ident::new(kw::DollarCrate, def_site)); - cx.path_all(span, false, idents, params, Vec::new()) + cx.path_all(span, false, idents, params) } } @@ -99,7 +99,7 @@ impl<'a> Path<'a> { pub enum Ty<'a> { Self_, /// &/Box/ Ty - Ptr(Box>, PtrTy<'a>), + Ptr(Box>, PtrTy), /// mod::mod::Type<[lifetime], [Params...]>, including a plain type /// parameter, and things like `i32` Literal(Path<'a>), @@ -107,14 +107,14 @@ pub enum Ty<'a> { Tuple(Vec>), } -pub fn borrowed_ptrty<'r>() -> PtrTy<'r> { +pub fn borrowed_ptrty() -> PtrTy { Borrowed(None, ast::Mutability::Immutable) } pub fn borrowed(ty: Box>) -> Ty<'_> { Ptr(ty, borrowed_ptrty()) } -pub fn borrowed_explicit_self<'r>() -> Option>> { +pub fn borrowed_explicit_self() -> Option> { Some(Some(borrowed_ptrty())) } @@ -126,13 +126,11 @@ pub fn nil_ty<'r>() -> Ty<'r> { Tuple(Vec::new()) } -fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option { - lt.map(|s| - cx.lifetime(span, Ident::from_str(s)) - ) +fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option) -> Option { + lt.map(|ident| cx.lifetime(span, ident)) } -fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec { +fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option) -> Vec { mk_lifetime(cx, span, lt).into_iter().collect() } @@ -185,7 +183,7 @@ impl<'a> Ty<'a> { } }).collect(); - cx.path_all(span, false, vec![self_ty], params, vec![]) + cx.path_all(span, false, vec![self_ty], params) } Literal(ref p) => p.to_path(cx, span, self_ty, generics), Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"), @@ -209,7 +207,7 @@ fn mk_ty_param(cx: &ExtCtxt<'_>, cx.trait_bound(path) }) .collect(); - cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) + cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None) } fn mk_generics(params: Vec, span: Span) -> Generics { @@ -265,7 +263,7 @@ impl<'a> LifetimeBounds<'a> { pub fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span, - self_ptr: &Option>) + self_ptr: &Option) -> (P, ast::ExplicitSelf) { // this constructs a fresh `self` path let self_path = cx.expr_self(span); @@ -276,7 +274,7 @@ pub fn get_explicit_self(cx: &ExtCtxt<'_>, respan(span, match *ptr { Borrowed(ref lt, mutbl) => { - let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s))); + let lt = lt.map(|s| cx.lifetime(span, s)); SelfKind::Region(lt, mutbl) } Raw(_) => { diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 9787722e81..2fc594abd7 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -16,7 +16,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>, let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std); - let typaram = &*deriving::hygienic_type_parameter(item, "__H"); + let typaram = "__H"; let arg = Path::new_local(typaram); let hash_trait_def = TraitDef { diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 8cd2853e53..60b6eba7a4 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -48,46 +48,22 @@ impl MultiItemModifier for BuiltinDerive { meta_item: &MetaItem, item: Annotatable) -> Vec { + // FIXME: Built-in derives often forget to give spans contexts, + // so we are doing it here in a centralized way. + let span = ecx.with_def_site_ctxt(span); let mut items = Vec::new(); (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); items } } -/// Construct a name for the inner type parameter that can't collide with any type parameters of -/// the item. This is achieved by starting with a base and then concatenating the names of all -/// other type parameters. -// FIXME(aburka): use real hygiene when that becomes possible -fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { - let mut typaram = String::from(base); - if let Annotatable::Item(ref item) = *item { - match item.node { - ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) | - ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { - for param in params { - match param.kind { - ast::GenericParamKind::Type { .. } => { - typaram.push_str(¶m.ident.as_str()); - } - _ => {} - } - } - } - - _ => {} - } - } - - typaram -} - /// Constructs an expression that calls an intrinsic fn call_intrinsic(cx: &ExtCtxt<'_>, span: Span, intrinsic: &str, args: Vec>) -> P { - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]); let call = cx.expr_call_global(span, path, args); diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 39fc90decc..02757bf6b1 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -7,32 +7,32 @@ use syntax::ast::{self, Ident, GenericArg}; use syntax::ext::base::{self, *}; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use std::env; pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(v) => v, }; - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_def_site_ctxt(sp); let e = match env::var(&*var.as_str()) { Err(..) => { - let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime)); + let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); cx.expr_path(cx.path_all(sp, true, cx.std_path(&[sym::option, sym::Option, sym::None]), vec![GenericArg::Type(cx.ty_rptr(sp, cx.ty_ident(sp, - Ident::with_empty_ctxt(sym::str)), + Ident::new(sym::str, sp)), Some(lt), ast::Mutability::Immutable))], - vec![])) + )) } Ok(s) => { cx.expr_call_global(sp, @@ -45,26 +45,26 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let mut exprs = match get_exprs_from_tts(cx, sp, tts) { Some(ref exprs) if exprs.is_empty() => { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(exprs) => exprs.into_iter(), }; let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((v, _style)) => v, }; let msg = match exprs.next() { None => Symbol::intern(&format!("environment variable `{}` not defined", var)), Some(second) => { match expr_to_string(cx, second, "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((s, _style)) => s, } } @@ -72,13 +72,13 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, if exprs.next().is_some() { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); - return DummyResult::expr(sp); + return DummyResult::any(sp); } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; diff --git a/src/libsyntax_ext/error_codes.rs b/src/libsyntax_ext/error_codes.rs index 5982a4df22..2bc990574f 100644 --- a/src/libsyntax_ext/error_codes.rs +++ b/src/libsyntax_ext/error_codes.rs @@ -1,9 +1,8 @@ -use syntax::register_long_diagnostics; - // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +syntax::register_diagnostics! { E0660: r##" The argument to the `asm` macro is not well-formed. diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 2ae13b66e2..26455df17b 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -5,14 +5,15 @@ use fmt_macros as parse; use errors::DiagnosticBuilder; use errors::Applicability; +use errors::pluralise; use syntax::ast; use syntax::ext::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; -use syntax::tokenstream; -use syntax_pos::{MultiSpan, Span, DUMMY_SP}; +use syntax::tokenstream::TokenStream; +use syntax_pos::{MultiSpan, Span}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::borrow::Cow; @@ -126,7 +127,7 @@ struct Context<'a, 'b> { fn parse_args<'a>( ecx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree] + tts: TokenStream, ) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { let mut args = Vec::>::new(); let mut names = FxHashMap::::default(); @@ -138,15 +139,23 @@ fn parse_args<'a>( } let fmtstr = p.parse_expr()?; + let mut first = true; let mut named = false; while p.token != token::Eof { if !p.eat(&token::Comma) { - let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); - err.span_label(p.token.span, "expected `,`"); - p.maybe_annotate_with_ascription(&mut err, false); - return Err(err); + if first { + // After `format!(""` we always expect *only* a comma... + let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); + err.span_label(p.token.span, "expected `,`"); + p.maybe_annotate_with_ascription(&mut err, false); + return Err(err); + } else { + // ...after that delegate to `expect` to also include the other expected tokens. + return Err(p.expect(&token::Comma).err().unwrap()); + } } + first = false; if p.token == token::Eof { break; } // accept trailing commas @@ -291,7 +300,7 @@ impl<'a, 'b> Context<'a, 'b> { &format!( "{} positional argument{} in format string, but {}", count, - if count > 1 { "s" } else { "" }, + pluralise!(count), self.describe_num_args(), ), ); @@ -478,7 +487,7 @@ impl<'a, 'b> Context<'a, 'b> { let sp = self.macsp; let count = |c, arg| { let mut path = Context::rtpath(self.ecx, "Count"); - path.push(self.ecx.ident_of(c)); + path.push(self.ecx.ident_of(c, sp)); match arg { Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]), None => self.ecx.expr_path(self.ecx.path_global(sp, path)), @@ -526,7 +535,7 @@ impl<'a, 'b> Context<'a, 'b> { let pos = { let pos = |c, arg| { let mut path = Context::rtpath(self.ecx, "Position"); - path.push(self.ecx.ident_of(c)); + path.push(self.ecx.ident_of(c, sp)); match arg { Some(i) => { let arg = self.ecx.expr_usize(sp, i); @@ -595,7 +604,7 @@ impl<'a, 'b> Context<'a, 'b> { let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill)); let align = |name| { let mut p = Context::rtpath(self.ecx, "Alignment"); - p.push(self.ecx.ident_of(name)); + p.push(self.ecx.ident_of(name, sp)); self.ecx.path_global(sp, p) }; let align = match arg.format.align { @@ -613,11 +622,11 @@ impl<'a, 'b> Context<'a, 'b> { sp, path, vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill), - self.ecx.field_imm(sp, self.ecx.ident_of("align"), align), - self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags), - self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec), - self.ecx.field_imm(sp, self.ecx.ident_of("width"), width), + self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill), + self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align), + self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags), + self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec), + self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width), ], ); @@ -626,8 +635,8 @@ impl<'a, 'b> Context<'a, 'b> { sp, path, vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos), - self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt), + self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos), + self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt), ], )) } @@ -645,7 +654,7 @@ impl<'a, 'b> Context<'a, 'b> { let mut heads = Vec::with_capacity(self.args.len()); let names_pos: Vec<_> = (0..self.args.len()) - .map(|i| ast::Ident::from_str_and_span(&format!("arg{}", i), self.macsp)) + .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp)) .collect(); // First, build up the static array which will become our precompiled @@ -666,8 +675,7 @@ impl<'a, 'b> Context<'a, 'b> { // passed to this function. for (i, e) in self.args.into_iter().enumerate() { let name = names_pos[i]; - let span = - DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.id)); + let span = self.ecx.with_def_site_ctxt(e.span); pats.push(self.ecx.pat_ident(span, name)); for ref arg_ty in self.arg_unique_types[i].iter() { locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name)); @@ -717,7 +725,7 @@ impl<'a, 'b> Context<'a, 'b> { // But the nested match expression is proved to perform not as well // as series of let's; the first approach does. let pat = self.ecx.pat_tuple(self.fmtsp, pats); - let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array); + let arm = self.ecx.arm(self.fmtsp, pat, args_array); let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads)); let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]); @@ -745,7 +753,7 @@ impl<'a, 'b> Context<'a, 'b> { ty: &ArgumentType, arg: ast::Ident, ) -> P { - sp = sp.apply_mark(ecx.current_expansion.id); + sp = ecx.with_def_site_ctxt(sp); let arg = ecx.expr_ident(sp, arg); let trait_ = match *ty { Placeholder(ref tyname) => { @@ -795,17 +803,17 @@ impl<'a, 'b> Context<'a, 'b> { fn expand_format_args_impl<'cx>( ecx: &'cx mut ExtCtxt<'_>, mut sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, nl: bool, ) -> Box { - sp = sp.apply_mark(ecx.current_expansion.id); + sp = ecx.with_def_site_ctxt(sp); match parse_args(ecx, sp, tts) { Ok((efmt, args, names)) => { MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl)) } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } @@ -813,7 +821,7 @@ fn expand_format_args_impl<'cx>( pub fn expand_format_args<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { expand_format_args_impl(ecx, sp, tts, false) } @@ -821,7 +829,7 @@ pub fn expand_format_args<'cx>( pub fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { expand_format_args_impl(ecx, sp, tts, true) } @@ -842,13 +850,13 @@ pub fn expand_preparsed_format_args( let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); let mut macsp = ecx.call_site(); - macsp = macsp.with_ctxt(ecx.backtrace()); + macsp = ecx.with_def_site_ctxt(macsp); let msg = "format argument must be a string literal"; let fmt_sp = efmt.span; - let fmt = match expr_to_spanned_string(ecx, efmt, msg) { + let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) { Ok(mut fmt) if append_newline => { - fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0)); + fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); fmt } Ok(fmt) => fmt, @@ -875,7 +883,7 @@ pub fn expand_preparsed_format_args( _ => (false, None), }; - let str_style = match fmt.node.1 { + let str_style = match fmt_style { ast::StrStyle::Cooked => None, ast::StrStyle::Raw(raw) => { Some(raw as usize) @@ -981,7 +989,7 @@ pub fn expand_preparsed_format_args( vec![] }; - let fmt_str = &*fmt.node.0.as_str(); // for the suggestions below + let fmt_str = &*fmt_str.as_str(); // for the suggestions below let mut parser = parse::Parser::new(fmt_str, str_style, skips, append_newline); let mut unverified_pieces = Vec::new(); @@ -995,7 +1003,7 @@ pub fn expand_preparsed_format_args( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let sp = fmt.span.from_inner(err.span); + let sp = fmt_span.from_inner(err.span); let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); @@ -1003,7 +1011,7 @@ pub fn expand_preparsed_format_args( e.note(¬e); } if let Some((label, span)) = err.secondary_label { - let sp = fmt.span.from_inner(span); + let sp = fmt_span.from_inner(span); e.span_label(sp, label); } e.emit(); @@ -1011,7 +1019,7 @@ pub fn expand_preparsed_format_args( } let arg_spans = parser.arg_places.iter() - .map(|span| fmt.span.from_inner(*span)) + .map(|span| fmt_span.from_inner(*span)) .collect(); let named_pos: FxHashSet = names.values().cloned().collect(); @@ -1034,7 +1042,7 @@ pub fn expand_preparsed_format_args( str_pieces: Vec::with_capacity(unverified_pieces.len()), all_pieces_simple: true, macsp, - fmtsp: fmt.span, + fmtsp: fmt_span, invalid_refs: Vec::new(), arg_spans, arg_with_formatting: Vec::new(), diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index f788b51380..19a87e6dc6 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -1,9 +1,8 @@ use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety}; -use syntax::ast::{self, Arg, Attribute, Expr, FnHeader, Generics, Ident}; +use syntax::ast::{self, Param, Attribute, Expr, FnHeader, Generics, Ident}; use syntax::attr::check_builtin_macro_attribute; use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; @@ -29,7 +28,7 @@ pub fn expand( }; // Generate a bunch of new items using the AllocFnFactory - let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id)); + let span = ecx.with_def_site_ctxt(item.span); let f = AllocFnFactory { span, kind: AllocatorKind::Global, @@ -44,7 +43,7 @@ pub fn expand( let const_ty = ecx.ty(span, TyKind::Tup(Vec::new())); let const_body = ecx.expr_block(ecx.block(span, stmts)); let const_item = - ecx.item_const(span, Ident::with_empty_ctxt(kw::Underscore), const_ty, const_body); + ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); // Return the original item and the new methods. vec![Annotatable::Item(item), Annotatable::Item(const_item)] @@ -62,7 +61,7 @@ impl AllocFnFactory<'_, '_> { let mut abi_args = Vec::new(); let mut i = 0; let ref mut mk = || { - let name = Ident::from_str(&format!("arg{}", i)); + let name = self.cx.ident_of(&format!("arg{}", i), self.span); i += 1; name }; @@ -84,7 +83,7 @@ impl AllocFnFactory<'_, '_> { ); let item = self.cx.item( self.span, - Ident::from_str(&self.kind.fn_name(method.name)), + self.cx.ident_of(&self.kind.fn_name(method.name), self.span), self.attrs(), kind, ); @@ -115,17 +114,17 @@ impl AllocFnFactory<'_, '_> { fn arg_ty( &self, ty: &AllocatorTy, - args: &mut Vec, + args: &mut Vec, ident: &mut dyn FnMut() -> Ident, ) -> P { match *ty { AllocatorTy::Layout => { - let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize)); + let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span)); let ty_usize = self.cx.ty_path(usize); let size = ident(); let align = ident(); - args.push(self.cx.arg(self.span, size, ty_usize.clone())); - args.push(self.cx.arg(self.span, align, ty_usize)); + args.push(self.cx.param(self.span, size, ty_usize.clone())); + args.push(self.cx.param(self.span, align, ty_usize)); let layout_new = self.cx.std_path(&[ Symbol::intern("alloc"), @@ -141,14 +140,14 @@ impl AllocFnFactory<'_, '_> { AllocatorTy::Ptr => { let ident = ident(); - args.push(self.cx.arg(self.span, ident, self.ptr_u8())); + args.push(self.cx.param(self.span, ident, self.ptr_u8())); let arg = self.cx.expr_ident(self.span, ident); self.cx.expr_cast(self.span, arg, self.ptr_u8()) } AllocatorTy::Usize => { let ident = ident(); - args.push(self.cx.arg(self.span, ident, self.usize())); + args.push(self.cx.param(self.span, ident, self.usize())); self.cx.expr_ident(self.span, ident) } @@ -178,12 +177,12 @@ impl AllocFnFactory<'_, '_> { } fn usize(&self) -> P { - let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize)); + let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span)); self.cx.ty_path(usize) } fn ptr_u8(&self) -> P { - let u8 = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::u8)); + let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span)); let ty_u8 = self.cx.ty_path(u8); self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable) } diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 112192fac5..c56b3f3fc8 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -16,12 +16,12 @@ use syntax::ext::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use smallvec::smallvec; pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) -> Box { + tts: TokenStream) -> Box { match parse_global_asm(cx, sp, tts) { Ok(Some(global_asm)) => { MacEager::items(smallvec![P(ast::Item { @@ -30,7 +30,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, id: ast::DUMMY_NODE_ID, node: ast::ItemKind::GlobalAsm(P(global_asm)), vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - span: sp, + span: cx.with_def_site_ctxt(sp), tokens: None, })]) } @@ -45,7 +45,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, fn parse_global_asm<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree] + tts: TokenStream ) -> Result, DiagnosticBuilder<'a>> { let mut p = cx.new_parser_from_tts(tts); @@ -61,8 +61,5 @@ fn parse_global_asm<'a>( None => return Ok(None), }; - Ok(Some(ast::GlobalAsm { - asm, - ctxt: cx.backtrace(), - })) + Ok(Some(ast::GlobalAsm { asm })) } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 0f3f5c0cd0..631ab7a331 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -7,13 +7,17 @@ #![feature(decl_macro)] #![feature(mem_take)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] +#![feature(proc_macro_internals)] +#![feature(proc_macro_quote)] + +extern crate proc_macro; use crate::deriving::*; use syntax::ast::Ident; use syntax::edition::Edition; use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; +use syntax::ext::proc_macro::BangProcMacro; use syntax::symbol::sym; mod error_codes; @@ -35,6 +39,7 @@ mod source_util; mod test; mod trace_macros; +pub mod cmdline_attrs; pub mod plugin_macro_defs; pub mod proc_macro_harness; pub mod standard_library_imports; @@ -42,7 +47,7 @@ pub mod test_harness; pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { let mut register = |name, kind| resolver.register_builtin_macro( - Ident::with_empty_ctxt(name), SyntaxExtension { + Ident::with_dummy_span(name), SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) }, ); @@ -57,14 +62,13 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e } register_bang! { - __rust_unstable_column: source_util::expand_column, asm: asm::expand_asm, assert: assert::expand_assert, cfg: cfg::expand_cfg, column: source_util::expand_column, compile_error: compile_error::expand_compile_error, - concat_idents: concat_idents::expand_syntax_ext, - concat: concat::expand_syntax_ext, + concat_idents: concat_idents::expand_concat_idents, + concat: concat::expand_concat, env: env::expand_env, file: source_util::expand_file, format_args_nl: format::expand_format_args_nl, @@ -74,7 +78,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e include_str: source_util::expand_include_str, include: source_util::expand_include, line: source_util::expand_line, - log_syntax: log_syntax::expand_syntax_ext, + log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, option_env: env::expand_option_env, stringify: source_util::expand_stringify, @@ -101,4 +105,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e RustcDecodable: decodable::expand_deriving_rustc_decodable, RustcEncodable: encodable::expand_deriving_rustc_encodable, } + + let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); + register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }))); } diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index cbdfd08b49..92130bfaf6 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -1,11 +1,11 @@ use syntax::ext::base; use syntax::print; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use syntax_pos; -pub fn expand_syntax_ext<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, +pub fn expand_log_syntax<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { println!("{}", print::pprust::tts_to_string(tts)); diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs index a725f5e46a..ccdc5bd81a 100644 --- a/src/libsyntax_ext/plugin_macro_defs.rs +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -11,7 +11,7 @@ use syntax::source_map::respan; use syntax::symbol::sym; use syntax::tokenstream::*; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind}; +use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass}; use std::mem; @@ -43,12 +43,12 @@ pub fn inject( ) { if !named_exts.is_empty() { let mut extra_items = Vec::new(); - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition, + let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( + ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition, [sym::rustc_attrs][..].into(), )); for (name, ext) in named_exts { - resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext); + resolver.register_builtin_macro(Ident::with_dummy_span(name), ext); extra_items.push(plugin_macro_def(name, span)); } // The `macro_rules` items must be inserted before any other items. diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 7913a7442e..f33c813d86 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -1,19 +1,17 @@ use std::mem; +use smallvec::smallvec; use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::source_map::{ExpnInfo, ExpnKind, respan}; -use syntax::ext::base::{ExtCtxt, MacroKind}; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::ExpnId; +use syntax::ext::base::ExtCtxt; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::proc_macro::is_proc_macro_attr; -use syntax::mut_visit::MutVisitor; use syntax::parse::ParseSess; use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; - use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::AstPass; struct ProcMacroDerive { trait_name: ast::Name, @@ -22,15 +20,24 @@ struct ProcMacroDerive { attrs: Vec, } +enum ProcMacroDefType { + Attr, + Bang +} + struct ProcMacroDef { function_name: Ident, span: Span, + def_type: ProcMacroDefType +} + +enum ProcMacro { + Derive(ProcMacroDerive), + Def(ProcMacroDef) } struct CollectProcMacros<'a> { - derives: Vec, - attr_macros: Vec, - bang_macros: Vec, + macros: Vec, in_root: bool, handler: &'a errors::Handler, is_proc_macro_crate: bool, @@ -48,22 +55,22 @@ pub fn inject(sess: &ParseSess, let ecfg = ExpansionConfig::default("proc_macro".to_string()); let mut cx = ExtCtxt::new(sess, ecfg, resolver); - let (derives, attr_macros, bang_macros) = { - let mut collect = CollectProcMacros { - derives: Vec::new(), - attr_macros: Vec::new(), - bang_macros: Vec::new(), - in_root: true, - handler, - is_proc_macro_crate, - is_test_crate, - }; - if has_proc_macro_decls || is_proc_macro_crate { - visit::walk_crate(&mut collect, &krate); - } - (collect.derives, collect.attr_macros, collect.bang_macros) + let mut collect = CollectProcMacros { + macros: Vec::new(), + in_root: true, + handler, + is_proc_macro_crate, + is_test_crate, }; + if has_proc_macro_decls || is_proc_macro_crate { + visit::walk_crate(&mut collect, &krate); + } + // NOTE: If you change the order of macros in this vec + // for any reason, you must also update 'raw_proc_macro' + // in src/librustc_metadata/decoder.rs + let macros = collect.macros; + if !is_proc_macro_crate { return krate } @@ -76,7 +83,7 @@ pub fn inject(sess: &ParseSess, return krate; } - krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros)); + krate.module.items.push(mk_decls(&mut cx, ¯os)); krate } @@ -163,12 +170,12 @@ impl<'a> CollectProcMacros<'a> { }; if self.in_root && item.vis.node.is_pub() { - self.derives.push(ProcMacroDerive { + self.macros.push(ProcMacro::Derive(ProcMacroDerive { span: item.span, trait_name: trait_ident.name, function_name: item.ident, attrs: proc_attrs, - }); + })); } else { let msg = if !self.in_root { "functions tagged with `#[proc_macro_derive]` must \ @@ -182,10 +189,11 @@ impl<'a> CollectProcMacros<'a> { fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { if self.in_root && item.vis.node.is_pub() { - self.attr_macros.push(ProcMacroDef { + self.macros.push(ProcMacro::Def(ProcMacroDef { span: item.span, function_name: item.ident, - }); + def_type: ProcMacroDefType::Attr + })); } else { let msg = if !self.in_root { "functions tagged with `#[proc_macro_attribute]` must \ @@ -199,10 +207,11 @@ impl<'a> CollectProcMacros<'a> { fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) { if self.in_root && item.vis.node.is_pub() { - self.bang_macros.push(ProcMacroDef { + self.macros.push(ProcMacro::Def(ProcMacroDef { span: item.span, function_name: item.ident, - }); + def_type: ProcMacroDefType::Bang + })); } else { let msg = if !self.in_root { "functions tagged with `#[proc_macro]` must \ @@ -310,8 +319,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // Creates a new module which looks like: // -// #[doc(hidden)] -// mod $gensym { +// const _: () = { // extern crate proc_macro; // // use proc_macro::bridge::client::ProcMacro; @@ -325,65 +333,67 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // } fn mk_decls( cx: &mut ExtCtxt<'_>, - custom_derives: &[ProcMacroDerive], - custom_attrs: &[ProcMacroDef], - custom_macros: &[ProcMacroDef], + macros: &[ProcMacro], ) -> P { - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, - [sym::rustc_attrs, sym::proc_macro_internals][..].into(), - )); - - let hidden = cx.meta_list_item_word(span, sym::hidden); - let doc = cx.meta_list(span, sym::doc, vec![hidden]); - let doc_hidden = cx.attribute(doc); - - let proc_macro = Ident::with_empty_ctxt(sym::proc_macro); + let expn_id = cx.resolver.expansion_for_ast_pass( + DUMMY_SP, + AstPass::ProcMacroHarness, + &[sym::rustc_attrs, sym::proc_macro_internals], + None, + ); + let span = DUMMY_SP.with_def_site_ctxt(expn_id); + + let proc_macro = Ident::new(sym::proc_macro, span); let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); - let bridge = Ident::from_str("bridge"); - let client = Ident::from_str("client"); - let proc_macro_ty = Ident::from_str("ProcMacro"); - let custom_derive = Ident::from_str("custom_derive"); - let attr = Ident::from_str("attr"); - let bang = Ident::from_str("bang"); - let crate_kw = Ident::with_empty_ctxt(kw::Crate); + let bridge = cx.ident_of("bridge", span); + let client = cx.ident_of("client", span); + let proc_macro_ty = cx.ident_of("ProcMacro", span); + let custom_derive = cx.ident_of("custom_derive", span); + let attr = cx.ident_of("attr", span); + let bang = cx.ident_of("bang", span); let decls = { let local_path = |sp: Span, name| { - cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name])) + cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name])) }; let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![ proc_macro, bridge, client, proc_macro_ty, method, ])); - custom_derives.iter().map(|cd| { - cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ - cx.expr_str(cd.span, cd.trait_name), - cx.expr_vec_slice( - span, - cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::>() - ), - local_path(cd.span, cd.function_name), - ]) - }).chain(custom_attrs.iter().map(|ca| { - cx.expr_call(span, proc_macro_ty_method_path(attr), vec![ - cx.expr_str(ca.span, ca.function_name.name), - local_path(ca.span, ca.function_name), - ]) - })).chain(custom_macros.iter().map(|cm| { - cx.expr_call(span, proc_macro_ty_method_path(bang), vec![ - cx.expr_str(cm.span, cm.function_name.name), - local_path(cm.span, cm.function_name), - ]) - })).collect() + macros.iter().map(|m| { + match m { + ProcMacro::Derive(cd) => { + cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ + cx.expr_str(cd.span, cd.trait_name), + cx.expr_vec_slice( + span, + cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::>() + ), + local_path(cd.span, cd.function_name), + ]) + }, + ProcMacro::Def(ca) => { + let ident = match ca.def_type { + ProcMacroDefType::Attr => attr, + ProcMacroDefType::Bang => bang + }; + + cx.expr_call(span, proc_macro_ty_method_path(ident), vec![ + cx.expr_str(ca.span, ca.function_name.name), + local_path(ca.span, ca.function_name), + ]) + + } + } + }).collect() }; let decls_static = cx.item_static( span, - Ident::from_str("_DECLS"), + cx.ident_of("_DECLS", span), cx.ty_rptr(span, cx.ty(span, ast::TyKind::Slice( cx.ty_path(cx.path(span, @@ -394,20 +404,22 @@ fn mk_decls( ).map(|mut i| { let attr = cx.meta_word(span, sym::rustc_proc_macro_decls); i.attrs.push(cx.attribute(attr)); - i.vis = respan(span, ast::VisibilityKind::Public); i }); - let module = cx.item_mod( - span, + let block = cx.expr_block(cx.block( span, - ast::Ident::from_str("decls").gensym(), - vec![doc_hidden], - vec![krate, decls_static], - ).map(|mut i| { - i.vis = respan(span, ast::VisibilityKind::Public); - i - }); + vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)], + )); - cx.monotonic_expander().flat_map_item(module).pop().unwrap() + let anon_constant = cx.item_const( + span, + ast::Ident::new(kw::Underscore, span), + cx.ty(span, ast::TyKind::Tup(Vec::new())), + block, + ); + + // Integrate the new item into existing module structures. + let items = AstFragment::Items(smallvec![anon_constant]); + cx.monotonic_expander().fully_expand_fragment(items).make_items().pop().unwrap() } diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 2c8d53a231..9dc9d66b86 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -4,13 +4,11 @@ use syntax::parse::{self, token, DirectoryOwnership}; use syntax::print::pprust; use syntax::ptr::P; use syntax::symbol::Symbol; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use smallvec::SmallVec; use syntax_pos::{self, Pos, Span}; -use std::fs; -use std::io::ErrorKind; use rustc_data_structures::sync::Lrc; // These macros all relate to the file system; they either return @@ -18,7 +16,7 @@ use rustc_data_structures::sync::Lrc; // a given file into the current one. /// line!(): expands to the current line number -pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "line!"); @@ -29,7 +27,7 @@ pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree } /* column!(): expands to the current column number */ -pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "column!"); @@ -42,7 +40,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTr /// file!(): expands to the current filename */ /// The source_file (`loc.file`) contains a bunch more information we could spit /// out if we wanted. -pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "file!"); @@ -51,13 +49,13 @@ pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string()))) } -pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let s = pprust::tts_to_string(tts); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } -pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; @@ -69,7 +67,7 @@ pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree] /// include! : parse the given file as an expr /// This is generally a bad idea because it's going to behave /// unhygienically. -pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, @@ -107,58 +105,45 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea } // include_str! : read the given file, insert it as a literal string expr -pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); - match fs::read_to_string(&file) { - Ok(src) => { - let interned_src = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - cx.source_map().new_source_file(file.into(), src); - - base::MacEager::expr(cx.expr_str(sp, interned_src)) + match cx.source_map().load_binary_file(&file) { + Ok(bytes) => match std::str::from_utf8(&bytes) { + Ok(src) => { + let interned_src = Symbol::intern(&src); + base::MacEager::expr(cx.expr_str(sp, interned_src)) + } + Err(_) => { + cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); + DummyResult::any(sp) + } }, - Err(ref e) if e.kind() == ErrorKind::InvalidData => { - cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); - DummyResult::expr(sp) - } Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } -pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); - match fs::read(&file) { + match cx.source_map().load_binary_file(&file) { Ok(bytes) => { - // Add the contents to the source map if it contains UTF-8. - let (contents, bytes) = match String::from_utf8(bytes) { - Ok(s) => { - let bytes = s.as_bytes().to_owned(); - (s, bytes) - }, - Err(e) => (String::new(), e.into_bytes()), - }; - cx.source_map().new_source_file(file.into(), contents); - base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) }, Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index 68b13bdd17..c577b1e33c 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -1,86 +1,86 @@ use syntax::{ast, attr}; use syntax::edition::Edition; -use syntax::ext::hygiene::{ExpnId, MacroKind}; +use syntax::ext::expand::ExpansionConfig; +use syntax::ext::hygiene::AstPass; +use syntax::ext::base::{ExtCtxt, Resolver}; +use syntax::parse::ParseSess; use syntax::ptr::P; -use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan}; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_pos::DUMMY_SP; -use std::iter; - pub fn inject( - mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition + mut krate: ast::Crate, + resolver: &mut dyn Resolver, + sess: &ParseSess, + alt_std_name: Option, ) -> (ast::Crate, Option) { - let rust_2018 = edition >= Edition::Edition2018; + let rust_2018 = sess.edition >= Edition::Edition2018; // the first name in this list is the crate name of the crate with the prelude - let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) { + let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) { return (krate, None); } else if attr::contains_name(&krate.attrs, sym::no_std) { if attr::contains_name(&krate.attrs, sym::compiler_builtins) { - &["core"] + &[sym::core] } else { - &["core", "compiler_builtins"] + &[sym::core, sym::compiler_builtins] } } else { - &["std"] + &[sym::std] }; + let expn_id = resolver.expansion_for_ast_pass( + DUMMY_SP, + AstPass::StdImports, + &[sym::prelude_import], + None, + ); + let span = DUMMY_SP.with_def_site_ctxt(expn_id); + let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); + + let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); + let cx = ExtCtxt::new(sess, ecfg, resolver); + + // .rev() to preserve ordering above in combination with insert(0, ...) - let alt_std_name = alt_std_name.map(Symbol::intern); - for orig_name_str in names.iter().rev() { - // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, - // so they don't accidentally interfere with the new import paths. - let orig_name_sym = Symbol::intern(orig_name_str); - let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym); - let (rename, orig_name) = if rust_2018 { - (orig_name_ident.gensym(), Some(orig_name_sym)) + for &name in names.iter().rev() { + let ident = if rust_2018 { + Ident::new(name, span) } else { - (orig_name_ident, None) + Ident::new(name, call_site) }; - krate.module.items.insert(0, P(ast::Item { - attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use)) - )], - vis: dummy_spanned(ast::VisibilityKind::Inherited), - node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), - ident: rename, - id: ast::DUMMY_NODE_ID, - span: DUMMY_SP, - tokens: None, - })); + krate.module.items.insert(0, cx.item( + span, + ident, + vec![cx.attribute(cx.meta_word(span, sym::macro_use))], + ast::ItemKind::ExternCrate(alt_std_name), + )); } - // the crates have been injected, the assumption is that the first one is the one with - // the prelude. + // The crates have been injected, the assumption is that the first one is + // the one with the prelude. let name = names[0]; - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition, - [sym::prelude_import][..].into(), - )); + let import_path = if rust_2018 { + [name, sym::prelude, sym::v1].iter() + .map(|symbol| ast::Ident::new(*symbol, span)).collect() + } else { + [kw::PathRoot, name, sym::prelude, sym::v1].iter() + .map(|symbol| ast::Ident::new(*symbol, span)).collect() + }; - krate.module.items.insert(0, P(ast::Item { - attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::new(sym::prelude_import, span)))], - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - node: ast::ItemKind::Use(P(ast::UseTree { - prefix: ast::Path { - segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot)) - .chain( - [name, "prelude", "v1"].iter().cloned() - .map(ast::Ident::from_str) - ).map(ast::PathSegment::from_ident).collect(), - span, - }, + let use_item = cx.item( + span, + ast::Ident::invalid(), + vec![cx.attribute(cx.meta_word(span, sym::prelude_import))], + ast::ItemKind::Use(P(ast::UseTree { + prefix: cx.path(span, import_path), kind: ast::UseTreeKind::Glob, span, })), - id: ast::DUMMY_NODE_ID, - ident: ast::Ident::invalid(), - span, - tokens: None, - })); + ); + + krate.module.items.insert(0, use_item); - (krate, Some(Symbol::intern(name))) + (krate, Some(name)) } diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 993ef25752..6c7e3e3eb9 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -4,7 +4,6 @@ use syntax::ast; use syntax::attr::{self, check_builtin_macro_attribute}; use syntax::ext::base::*; -use syntax::ext::hygiene::SyntaxContext; use syntax::print::pprust; use syntax::source_map::respan; use syntax::symbol::{Symbol, sym}; @@ -29,11 +28,11 @@ pub fn expand_test_case( if !ecx.ecfg.should_test { return vec![]; } - let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id)); + let sp = ecx.with_def_site_ctxt(attr_sp); let mut item = anno_item.expect_item(); item = item.map(|mut item| { item.vis = respan(item.vis.span, ast::VisibilityKind::Public); - item.ident = item.ident.gensym(); + item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); item.attrs.push( ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)) ); @@ -93,28 +92,26 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let ctxt = SyntaxContext::empty().apply_mark(cx.current_expansion.id); - let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt)); + let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp)); - // Gensym "test" so we can extern crate without conflicting with any local names - let test_id = cx.ident_of("test").gensym(); + let test_id = ast::Ident::new(sym::test, attr_sp); // creates test::$name let test_path = |name| { - cx.path(sp, vec![test_id, cx.ident_of(name)]) + cx.path(sp, vec![test_id, cx.ident_of(name, sp)]) }; // creates test::ShouldPanic::$name let should_panic_path = |name| { - cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)]) + cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)]) }; // creates $name: $expr - let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr); + let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr); let test_fn = if is_bench { // A simple ident for a lambda - let b = cx.ident_of("b"); + let b = cx.ident_of("b", attr_sp); cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![ // |b| self::test::assert_test_result( @@ -145,11 +142,11 @@ pub fn expand_test_or_bench( ]) }; - let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(), + let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp), vec![ // #[cfg(test)] - cx.attribute(cx.meta_list(attr_sp, sym::cfg, vec![ - cx.meta_list_item_word(attr_sp, sym::test) + cx.attribute(attr::mk_list_item(ast::Ident::new(sym::cfg, attr_sp), vec![ + attr::mk_nested_word_item(ast::Ident::new(sym::test, attr_sp)) ])), // #[rustc_test_marker] cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)), @@ -194,17 +191,17 @@ pub fn expand_test_or_bench( )); test_const = test_const.map(|mut tc| { tc.vis.node = ast::VisibilityKind::Public; tc}); - // extern crate test as test_gensym + // extern crate test let test_extern = cx.item(sp, test_id, vec![], - ast::ItemKind::ExternCrate(Some(sym::test)) + ast::ItemKind::ExternCrate(None) ); log::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); vec![ - // Access to libtest under a gensymed name + // Access to libtest under a hygienic name Annotatable::Item(test_extern), // The generated test case Annotatable::Item(test_const), diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index eec8a3f802..56de0c97f8 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -6,32 +6,29 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; use syntax::ext::base::{ExtCtxt, Resolver}; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::{ExpnId, MacroKind}; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; use syntax::parse::ParseSess; use syntax::ptr::P; -use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned}; -use syntax::symbol::{kw, sym, Symbol}; +use syntax::source_map::respan; +use syntax::symbol::{sym, Symbol}; use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::{AstPass, SyntaxContext, Transparency}; use std::{iter, mem}; struct Test { span: Span, - path: Vec, + ident: Ident, } struct TestCtxt<'a> { - span_diagnostic: &'a errors::Handler, - path: Vec, ext_cx: ExtCtxt<'a>, + def_site: Span, test_cases: Vec, reexport_test_harness_main: Option, test_runner: Option, - // top-level re-export submodule, filled out after folding is finished - toplevel_reexport: Option, } // Traverse the crate, collecting all the test functions, eliding any @@ -44,8 +41,8 @@ pub fn inject( span_diagnostic: &errors::Handler, features: &Features, ) { - // Check for #[reexport_test_harness_main = "some_name"] which - // creates a `use __test::main as some_name;`. This needs to be + // Check for #![reexport_test_harness_main = "some_name"] which gives the + // main test function the name `some_name` without hygiene. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = @@ -57,16 +54,13 @@ pub fn inject( if should_test { generate_test_harness(sess, resolver, reexport_test_harness_main, - krate, span_diagnostic, features, test_runner) + krate, features, test_runner) } } struct TestHarnessGenerator<'a> { cx: TestCtxt<'a>, - tests: Vec, - - // submodule name, gensym'd identifier for re-exports - tested_submods: Vec<(Ident, Ident)>, + tests: Vec, } impl<'a> MutVisitor for TestHarnessGenerator<'a> { @@ -74,58 +68,51 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { noop_visit_crate(c, self); // Create a main function to run our tests - let test_main = { - let unresolved = mk_main(&mut self.cx); - self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap() - }; - - c.module.items.push(test_main); + c.module.items.push(mk_main(&mut self.cx)); } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - let ident = i.ident; - if ident.name != kw::Invalid { - self.cx.path.push(ident); - } - debug!("current path: {}", path_name_i(&self.cx.path)); - let mut item = i.into_inner(); if is_test_case(&item) { debug!("this is a test item"); let test = Test { span: item.span, - path: self.cx.path.clone(), + ident: item.ident, }; - self.cx.test_cases.push(test); - self.tests.push(item.ident); + self.tests.push(test); } // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things if let ast::ItemKind::Mod(mut module) = item.node { let tests = mem::take(&mut self.tests); - let tested_submods = mem::take(&mut self.tested_submods); noop_visit_mod(&mut module, self); - let tests = mem::replace(&mut self.tests, tests); - let tested_submods = mem::replace(&mut self.tested_submods, tested_submods); + let mut tests = mem::replace(&mut self.tests, tests); - if !tests.is_empty() || !tested_submods.is_empty() { - let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods); - module.items.push(it); - - if !self.cx.path.is_empty() { - self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym)); + if !tests.is_empty() { + let parent = if item.id == ast::DUMMY_NODE_ID { + ast::CRATE_NODE_ID } else { - debug!("pushing nothing, sym: {:?}", sym); - self.cx.toplevel_reexport = Some(sym); + item.id + }; + // Create an identifier that will hygienically resolve the test + // case name, even in another module. + let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( + module.inner, + AstPass::TestHarness, + &[], + Some(parent), + ); + for test in &mut tests { + // See the comment on `mk_main` for why we're using + // `apply_mark` directly. + test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque); } + self.cx.test_cases.extend(tests); } item.node = ast::ItemKind::Mod(module); } - if ident.name != kw::Invalid { - self.cx.path.pop(); - } smallvec![P(item)] } @@ -139,6 +126,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { struct EntryPointCleaner { // Current depth in the ast depth: usize, + def_site: Span, } impl MutVisitor for EntryPointCleaner { @@ -155,8 +143,10 @@ impl MutVisitor for EntryPointCleaner { EntryPointType::MainAttr | EntryPointType::Start => item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| { - let allow_ident = Ident::with_empty_ctxt(sym::allow); - let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code")); + let allow_ident = Ident::new(sym::allow, self.def_site); + let dc_nested = attr::mk_nested_word_item( + Ident::from_str_and_span("dead_code", self.def_site), + ); let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); @@ -187,119 +177,99 @@ impl MutVisitor for EntryPointCleaner { } } -/// Creates an item (specifically a module) that "pub use"s the tests passed in. -/// Each tested submodule will contain a similar reexport module that we will export -/// under the name of the original module. That is, `submod::__test_reexports` is -/// reexported like so `pub use submod::__test_reexports as submod`. -fn mk_reexport_mod(cx: &mut TestCtxt<'_>, - parent: ast::NodeId, - tests: Vec, - tested_submods: Vec<(Ident, Ident)>) - -> (P, Ident) { - let super_ = Ident::with_empty_ctxt(kw::Super); - - let items = tests.into_iter().map(|r| { - cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - cx.ext_cx.path(DUMMY_SP, vec![super_, r])) - }).chain(tested_submods.into_iter().map(|(r, sym)| { - let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); - cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - Some(r), path) - })).collect(); - - let reexport_mod = ast::Mod { - inline: true, - inner: DUMMY_SP, - items, - }; - - let name = Ident::from_str("__test_reexports").gensym(); - let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; - cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent); - let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { - ident: name, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mod(reexport_mod), - vis: dummy_spanned(ast::VisibilityKind::Public), - span: DUMMY_SP, - tokens: None, - })).pop().unwrap(); - - (it, name) -} - /// Crawl over the crate, inserting test reexports and the test main function fn generate_test_harness(sess: &ParseSess, resolver: &mut dyn Resolver, reexport_test_harness_main: Option, krate: &mut ast::Crate, - sd: &errors::Handler, features: &Features, test_runner: Option) { - // Remove the entry points - let mut cleaner = EntryPointCleaner { depth: 0 }; - cleaner.visit_crate(krate); - let mut econfig = ExpansionConfig::default("test".to_string()); econfig.features = Some(features); + let ext_cx = ExtCtxt::new(sess, econfig, resolver); + + let expn_id = ext_cx.resolver.expansion_for_ast_pass( + DUMMY_SP, + AstPass::TestHarness, + &[sym::main, sym::test, sym::rustc_attrs], + None, + ); + let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); + + // Remove the entry points + let mut cleaner = EntryPointCleaner { depth: 0, def_site }; + cleaner.visit_crate(krate); + let cx = TestCtxt { - span_diagnostic: sd, - ext_cx: ExtCtxt::new(sess, econfig, resolver), - path: Vec::new(), + ext_cx, + def_site, test_cases: Vec::new(), reexport_test_harness_main, - toplevel_reexport: None, test_runner }; TestHarnessGenerator { cx, tests: Vec::new(), - tested_submods: Vec::new(), }.visit_crate(krate); } /// Creates a function item for use as the main function of a test build. /// This function will call the `test_runner` as specified by the crate attribute +/// +/// By default this expands to +/// +/// #[main] +/// pub fn main() { +/// extern crate test; +/// test::test_main_static(&[ +/// &test_const1, +/// &test_const2, +/// &test_const3, +/// ]); +/// } +/// +/// Most of the Ident have the usual def-site hygiene for the AST pass. The +/// exception is the `test_const`s. These have a syntax context that has two +/// opaque marks: one from the expansion of `test` or `test_case`, and one +/// generated in `TestHarnessGenerator::flat_map_item`. When resolving this +/// identifier after failing to find a matching identifier in the root module +/// we remove the outer mark, and try resolving at its def-site, which will +/// then resolve to `test_const`. +/// +/// The expansion here can be controlled by two attributes: +/// +/// `reexport_test_harness_main` provides a different name for the `main` +/// function and `test_runner` provides a path that replaces +/// `test::test_main_static`. fn mk_main(cx: &mut TestCtxt<'_>) -> P { - // Writing this out by hand: - // pub fn main() { - // #![main] - // test::test_main_static(&[..tests]); - // } - let sp = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition, - [sym::main, sym::test, sym::rustc_attrs][..].into(), - )); + let sp = cx.def_site; let ecx = &cx.ext_cx; - let test_id = Ident::with_empty_ctxt(sym::test); + let test_id = Ident::new(sym::test, sp); // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or( - ecx.path(sp, vec![ - test_id, ecx.ident_of("test_main_static") - ])); + ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)])); test_runner.span = sp; let test_main_path_expr = ecx.expr_path(test_runner); let call_test_main = ecx.expr_call(sp, test_main_path_expr, - vec![mk_tests_slice(cx)]); + vec![mk_tests_slice(cx, sp)]); let call_test_main = ecx.stmt_expr(call_test_main); - // #![main] - let main_meta = ecx.meta_word(sp, sym::main); - let main_attr = ecx.attribute(main_meta); - - // extern crate test as test_gensym + // extern crate test let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None) )); + // #[main] + let main_meta = ecx.meta_word(sp, sym::main); + let main_attr = ecx.attribute(main_meta); + // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); @@ -317,60 +287,39 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // Honor the reexport_test_harness_main attribute let main_id = match cx.reexport_test_harness_main { - Some(sym) => Ident::new(sym, sp), - None => Ident::from_str_and_span("main", sp).gensym(), + Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), + None => Ident::new(sym::main, sp), }; - P(ast::Item { + let main = P(ast::Item { ident: main_id, attrs: vec![main_attr], id: ast::DUMMY_NODE_ID, node: main, - vis: dummy_spanned(ast::VisibilityKind::Public), + vis: respan(sp, ast::VisibilityKind::Public), span: sp, tokens: None, - }) + }); -} - -fn path_name_i(idents: &[Ident]) -> String { - let mut path_name = "".to_string(); - let mut idents_iter = idents.iter().peekable(); - while let Some(ident) = idents_iter.next() { - path_name.push_str(&ident.as_str()); - if idents_iter.peek().is_some() { - path_name.push_str("::") - } - } - path_name + // Integrate the new item into existing module structures. + let main = AstFragment::Items(smallvec![main]); + cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap() } /// Creates a slice containing every test like so: -/// &[path::to::test1, path::to::test2] -fn mk_tests_slice(cx: &TestCtxt<'_>) -> P { +/// &[&test1, &test2] +fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { debug!("building test vector from {} tests", cx.test_cases.len()); let ref ecx = cx.ext_cx; - ecx.expr_vec_slice(DUMMY_SP, + + ecx.expr_vec_slice(sp, cx.test_cases.iter().map(|test| { ecx.expr_addr_of(test.span, - ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path)))) + ecx.expr_path(ecx.path(test.span, vec![test.ident]))) }).collect()) } -/// Creates a path from the top-level __test module to the test via __test_reexports -fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec{ - let mut visible_path = vec![]; - match cx.toplevel_reexport { - Some(id) => visible_path.push(id), - None => { - cx.span_diagnostic.bug("expected to find top-level re-export name, but found None"); - } - } - visible_path.extend_from_slice(path); - visible_path -} - fn is_test_case(i: &ast::Item) -> bool { attr::contains_name(&i.attrs, sym::rustc_test_marker) } diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 0dce8a36f4..d83c24046d 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -1,20 +1,27 @@ use syntax::ext::base::{self, ExtCtxt}; use syntax::symbol::kw; use syntax_pos::Span; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>, sp: Span, - tt: &[TokenTree]) + tt: TokenStream) -> Box { - match tt { - [TokenTree::Token(token)] if token.is_keyword(kw::True) => { - cx.set_trace_macros(true); - } - [TokenTree::Token(token)] if token.is_keyword(kw::False) => { - cx.set_trace_macros(false); - } - _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), + let mut cursor = tt.into_trees(); + let mut err = false; + let value = match &cursor.next() { + Some(TokenTree::Token(token)) if token.is_keyword(kw::True) => true, + Some(TokenTree::Token(token)) if token.is_keyword(kw::False) => false, + _ => { + err = true; + false + }, + }; + err |= cursor.next().is_some(); + if err { + cx.span_err(sp, "trace_macros! accepts only `true` or `false`") + } else { + cx.set_trace_macros(value); } base::DummyResult::any_valid(sp) diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index 2021656842..00cd00f283 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -1,7 +1,6 @@ use crate::symbol::{Symbol, sym}; use std::fmt; use std::str::FromStr; -use crate::GLOBALS; /// The edition of the compiler (RFC 2052) #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] @@ -39,10 +38,6 @@ impl fmt::Display for Edition { } impl Edition { - pub fn from_session() -> Edition { - GLOBALS.with(|globals| globals.edition) - } - pub fn lint_name(&self) -> &'static str { match *self { Edition::Edition2015 => "rust_2015_compatibility", diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index f91a229154..e28d932675 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -13,8 +13,8 @@ // // This explains why `HygieneData`, `SyntaxContext` and `ExpnId` have interfaces // with a certain amount of redundancy in them. For example, -// `SyntaxContext::outer_expn_info` combines `SyntaxContext::outer` and -// `ExpnId::expn_info` so that two `HygieneData` accesses can be performed within +// `SyntaxContext::outer_expn_data` combines `SyntaxContext::outer` and +// `ExpnId::expn_data` so that two `HygieneData` accesses can be performed within // a single `HygieneData::with` call. // // It also explains why many functions appear in `HygieneData` and again in @@ -56,16 +56,6 @@ struct SyntaxContextData { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct ExpnId(u32); -// FIXME: Find a way to merge this with `ExpnInfo`. -#[derive(Debug)] -struct InternalExpnData { - parent: ExpnId, - /// Each expansion should have an associated expansion info, but sometimes there's a delay - /// between creation of an expansion ID and obtaining its info (e.g. macros are collected - /// first and then resolved later), so we use an `Option` here. - expn_info: Option, -} - /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -86,8 +76,8 @@ pub enum Transparency { } impl ExpnId { - pub fn fresh(parent: ExpnId, expn_info: Option) -> Self { - HygieneData::with(|data| data.fresh_expn(parent, expn_info)) + pub fn fresh(expn_data: Option) -> Self { + HygieneData::with(|data| data.fresh_expn(expn_data)) } /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. @@ -107,21 +97,16 @@ impl ExpnId { } #[inline] - pub fn parent(self) -> ExpnId { - HygieneData::with(|data| data.parent_expn(self)) + pub fn expn_data(self) -> ExpnData { + HygieneData::with(|data| data.expn_data(self).clone()) } #[inline] - pub fn expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(self).cloned()) - } - - #[inline] - pub fn set_expn_info(self, info: ExpnInfo) { + pub fn set_expn_data(self, expn_data: ExpnData) { HygieneData::with(|data| { - let old_info = &mut data.expn_data[self.0 as usize].expn_info; - assert!(old_info.is_none(), "expansion info is reset for an expansion ID"); - *old_info = Some(info); + let old_expn_data = &mut data.expn_data[self.0 as usize]; + assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID"); + *old_expn_data = Some(expn_data); }) } @@ -134,26 +119,14 @@ impl ExpnId { pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool { HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt))) } - - // Used for enabling some compatibility fallback in resolve. - #[inline] - pub fn looks_like_proc_macro_derive(self) -> bool { - HygieneData::with(|data| { - if data.default_transparency(self) == Transparency::Opaque { - if let Some(expn_info) = data.expn_info(self) { - if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind { - return true; - } - } - } - false - }) - } } #[derive(Debug)] crate struct HygieneData { - expn_data: Vec, + /// Each expansion should have an associated expansion data, but sometimes there's a delay + /// between creation of an expansion ID and obtaining its data (e.g. macros are collected + /// first and then resolved later), so we use an `Option` here. + expn_data: Vec>, syntax_context_data: Vec, syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>, } @@ -161,10 +134,7 @@ crate struct HygieneData { impl HygieneData { crate fn new(edition: Edition) -> Self { HygieneData { - expn_data: vec![InternalExpnData { - parent: ExpnId::root(), - expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)), - }], + expn_data: vec![Some(ExpnData::default(ExpnKind::Root, DUMMY_SP, edition))], syntax_context_data: vec![SyntaxContextData { outer_expn: ExpnId::root(), outer_transparency: Transparency::Opaque, @@ -181,25 +151,14 @@ impl HygieneData { GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) } - fn fresh_expn(&mut self, parent: ExpnId, expn_info: Option) -> ExpnId { - self.expn_data.push(InternalExpnData { parent, expn_info }); + fn fresh_expn(&mut self, expn_data: Option) -> ExpnId { + self.expn_data.push(expn_data); ExpnId(self.expn_data.len() as u32 - 1) } - fn parent_expn(&self, expn_id: ExpnId) -> ExpnId { - self.expn_data[expn_id.0 as usize].parent - } - - fn expn_info(&self, expn_id: ExpnId) -> Option<&ExpnInfo> { - if expn_id != ExpnId::root() { - Some(self.expn_data[expn_id.0 as usize].expn_info.as_ref() - .expect("no expansion info for an expansion ID")) - } else { - // FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion". - // Introduce a method for checking for "no expansion" instead and always return - // `ExpnInfo` from this function instead of the `Option`. - None - } + fn expn_data(&self, expn_id: ExpnId) -> &ExpnData { + self.expn_data[expn_id.0 as usize].as_ref() + .expect("no expansion data for an expansion ID") } fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool { @@ -207,17 +166,11 @@ impl HygieneData { if expn_id == ExpnId::root() { return false; } - expn_id = self.parent_expn(expn_id); + expn_id = self.expn_data(expn_id).parent; } true } - fn default_transparency(&self, expn_id: ExpnId) -> Transparency { - self.expn_info(expn_id).map_or( - Transparency::SemiTransparent, |einfo| einfo.default_transparency - ) - } - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } @@ -230,24 +183,25 @@ impl HygieneData { self.syntax_context_data[ctxt.0 as usize].outer_expn } - fn outer_transparency(&self, ctxt: SyntaxContext) -> Transparency { - self.syntax_context_data[ctxt.0 as usize].outer_transparency + fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) { + let data = &self.syntax_context_data[ctxt.0 as usize]; + (data.outer_expn, data.outer_transparency) } fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].parent } - fn remove_mark(&self, ctxt: &mut SyntaxContext) -> ExpnId { - let outer_expn = self.outer_expn(*ctxt); + fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) { + let outer_mark = self.outer_mark(*ctxt); *ctxt = self.parent_ctxt(*ctxt); - outer_expn + outer_mark } fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> { let mut marks = Vec::new(); - while ctxt != SyntaxContext::empty() { - marks.push((self.outer_expn(ctxt), self.outer_transparency(ctxt))); + while ctxt != SyntaxContext::root() { + marks.push(self.outer_mark(ctxt)); ctxt = self.parent_ctxt(ctxt); } marks.reverse(); @@ -255,12 +209,8 @@ impl HygieneData { } fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span { - while span.ctxt() != crate::NO_EXPANSION && span.ctxt() != to { - if let Some(info) = self.expn_info(self.outer_expn(span.ctxt())) { - span = info.call_site; - } else { - break; - } + while span.from_expansion() && span.ctxt() != to { + span = self.expn_data(self.outer_expn(span.ctxt())).call_site; } span } @@ -268,32 +218,27 @@ impl HygieneData { fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option { let mut scope = None; while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) { - scope = Some(self.remove_mark(ctxt)); + scope = Some(self.remove_mark(ctxt).0); } scope } - fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext { - assert_ne!(expn_id, ExpnId::root()); - self.apply_mark_with_transparency(ctxt, expn_id, self.default_transparency(expn_id)) - } - - fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId, - transparency: Transparency) -> SyntaxContext { + fn apply_mark( + &mut self, ctxt: SyntaxContext, expn_id: ExpnId, transparency: Transparency + ) -> SyntaxContext { assert_ne!(expn_id, ExpnId::root()); if transparency == Transparency::Opaque { return self.apply_mark_internal(ctxt, expn_id, transparency); } - let call_site_ctxt = - self.expn_info(expn_id).map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()); + let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { self.modern(call_site_ctxt) } else { self.modern_and_legacy(call_site_ctxt) }; - if call_site_ctxt == SyntaxContext::empty() { + if call_site_ctxt == SyntaxContext::root() { return self.apply_mark_internal(ctxt, expn_id, transparency); } @@ -398,9 +343,41 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb })) } +pub fn debug_hygiene_data(verbose: bool) -> String { + HygieneData::with(|data| { + if verbose { + format!("{:#?}", data) + } else { + let mut s = String::from(""); + s.push_str("Expansions:"); + data.expn_data.iter().enumerate().for_each(|(id, expn_info)| { + let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID"); + s.push_str(&format!( + "\n{}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}", + id, + expn_info.parent, + expn_info.call_site.ctxt(), + expn_info.kind, + )); + }); + s.push_str("\n\nSyntaxContexts:"); + data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| { + s.push_str(&format!( + "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})", + id, + ctxt.parent, + ctxt.outer_expn, + ctxt.outer_transparency, + )); + }); + s + } + }) +} + impl SyntaxContext { #[inline] - pub const fn empty() -> Self { + pub const fn root() -> Self { SyntaxContext(0) } @@ -414,15 +391,9 @@ impl SyntaxContext { SyntaxContext(raw) } - /// Extend a syntax context with a given expansion and default transparency for that expansion. - pub fn apply_mark(self, expn_id: ExpnId) -> SyntaxContext { - HygieneData::with(|data| data.apply_mark(self, expn_id)) - } - /// Extend a syntax context with a given expansion and transparency. - pub fn apply_mark_with_transparency(self, expn_id: ExpnId, transparency: Transparency) - -> SyntaxContext { - HygieneData::with(|data| data.apply_mark_with_transparency(self, expn_id, transparency)) + crate fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { + HygieneData::with(|data| data.apply_mark(self, expn_id, transparency)) } /// Pulls a single mark off of the syntax context. This effectively moves the @@ -442,7 +413,7 @@ impl SyntaxContext { /// invocation of f that created g1. /// Returns the mark that was removed. pub fn remove_mark(&mut self) -> ExpnId { - HygieneData::with(|data| data.remove_mark(self)) + HygieneData::with(|data| data.remove_mark(self).0) } pub fn marks(self) -> Vec<(ExpnId, Transparency)> { @@ -515,8 +486,8 @@ impl SyntaxContext { let mut scope = None; let mut glob_ctxt = data.modern(glob_span.ctxt()); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { - scope = Some(data.remove_mark(&mut glob_ctxt)); - if data.remove_mark(self) != scope.unwrap() { + scope = Some(data.remove_mark(&mut glob_ctxt).0); + if data.remove_mark(self).0 != scope.unwrap() { return None; } } @@ -547,9 +518,9 @@ impl SyntaxContext { marks.push(data.remove_mark(&mut glob_ctxt)); } - let scope = marks.last().cloned(); - while let Some(mark) = marks.pop() { - *self = data.apply_mark(*self, mark); + let scope = marks.last().map(|mark| mark.0); + while let Some((expn_id, transparency)) = marks.pop() { + *self = data.apply_mark(*self, expn_id, transparency); } Some(scope) }) @@ -578,20 +549,18 @@ impl SyntaxContext { HygieneData::with(|data| data.outer_expn(self)) } - /// `ctxt.outer_expn_info()` is equivalent to but faster than - /// `ctxt.outer_expn().expn_info()`. + /// `ctxt.outer_expn_data()` is equivalent to but faster than + /// `ctxt.outer_expn().expn_data()`. #[inline] - pub fn outer_expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(data.outer_expn(self)).cloned()) + pub fn outer_expn_data(self) -> ExpnData { + HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone()) } - /// `ctxt.outer_expn_with_info()` is equivalent to but faster than - /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_info()) }`. #[inline] - pub fn outer_expn_with_info(self) -> (ExpnId, Option) { + pub fn outer_mark_with_data(self) -> (ExpnId, Transparency, ExpnData) { HygieneData::with(|data| { - let outer = data.outer_expn(self); - (outer, data.expn_info(outer).cloned()) + let (expn_id, transparency) = data.outer_mark(self); + (expn_id, transparency, data.expn_data(expn_id).clone()) }) } @@ -612,10 +581,16 @@ impl Span { /// other compiler-generated code to set per-span properties like allowed unstable features. /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. - pub fn fresh_expansion(self, parent: ExpnId, expn_info: ExpnInfo) -> Span { + pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { + self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent) + } + + pub fn fresh_expansion_with_transparency( + self, expn_data: ExpnData, transparency: Transparency + ) -> Span { HygieneData::with(|data| { - let expn_id = data.fresh_expn(parent, Some(expn_info)); - self.with_ctxt(data.apply_mark(SyntaxContext::empty(), expn_id)) + let expn_id = data.fresh_expn(Some(expn_data)); + self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency)) }) } } @@ -623,8 +598,12 @@ impl Span { /// A subset of properties from both macro definition and macro call available through global data. /// Avoid using this if you have access to the original definition or call structures. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub struct ExpnInfo { +pub struct ExpnData { // --- The part unique to each expansion. + /// The kind of this expansion - macro or compiler desugaring. + pub kind: ExpnKind, + /// The expansion that produced this expansion. + pub parent: ExpnId, /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` /// @@ -632,19 +611,17 @@ pub struct ExpnInfo { /// `foo!()` invoked `bar!()` internally, and there was an /// expression inside `bar!`; the call_site of the expression in /// the expansion would point to the `bar!` invocation; that - /// call_site span would have its own ExpnInfo, with the call_site + /// call_site span would have its own ExpnData, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, - /// The kind of this expansion - macro or compiler desugaring. - pub kind: ExpnKind, // --- The part specific to the macro/desugaring definition. - // --- FIXME: Share it between expansions with the same definition. + // --- It may be reasonable to share this part between expansions with the same definition, + // --- but such sharing is known to bring some minor inconveniences without also bringing + // --- noticeable perf improvements (PR #62898). /// The span of the macro definition (possibly dummy). /// This span serves only informational purpose and is not used for resolution. pub def_site: Span, - /// Transparency used by `apply_mark` for the expansion with this expansion info by default. - pub default_transparency: Transparency, /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. @@ -659,14 +636,14 @@ pub struct ExpnInfo { pub edition: Edition, } -impl ExpnInfo { - /// Constructs an expansion info with default properties. - pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnInfo { - ExpnInfo { - call_site, +impl ExpnData { + /// Constructs expansion data with default properties. + pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnData { + ExpnData { kind, + parent: ExpnId::root(), + call_site, def_site: DUMMY_SP, - default_transparency: Transparency::SemiTransparent, allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, @@ -675,12 +652,17 @@ impl ExpnInfo { } pub fn allow_unstable(kind: ExpnKind, call_site: Span, edition: Edition, - allow_internal_unstable: Lrc<[Symbol]>) -> ExpnInfo { - ExpnInfo { + allow_internal_unstable: Lrc<[Symbol]>) -> ExpnData { + ExpnData { allow_internal_unstable: Some(allow_internal_unstable), - ..ExpnInfo::default(kind, call_site, edition) + ..ExpnData::default(kind, call_site, edition) } } + + #[inline] + pub fn is_root(&self) -> bool { + if let ExpnKind::Root = self.kind { true } else { false } + } } /// Expansion kind. @@ -689,8 +671,9 @@ pub enum ExpnKind { /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind. Root, /// Expansion produced by a macro. - /// FIXME: Some code injected by the compiler before HIR lowering also gets this kind. Macro(MacroKind, Symbol), + /// Transform done by the compiler on the AST. + AstPass(AstPass), /// Desugaring done by the compiler during HIR lowering. Desugaring(DesugaringKind) } @@ -700,6 +683,7 @@ impl ExpnKind { match *self { ExpnKind::Root => kw::PathRoot, ExpnKind::Macro(_, descr) => descr, + ExpnKind::AstPass(kind) => Symbol::intern(kind.descr()), ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()), } } @@ -725,6 +709,13 @@ impl MacroKind { } } + pub fn descr_expected(self) -> &'static str { + match self { + MacroKind::Attr => "attribute", + _ => self.descr(), + } + } + pub fn article(self) -> &'static str { match self { MacroKind::Attr => "an", @@ -733,6 +724,26 @@ impl MacroKind { } } +/// The kind of AST transform. +#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] +pub enum AstPass { + StdImports, + TestHarness, + ProcMacroHarness, + PluginMacroDefs, +} + +impl AstPass { + fn descr(self) -> &'static str { + match self { + AstPass::StdImports => "standard library imports", + AstPass::TestHarness => "test harness", + AstPass::ProcMacroHarness => "proc macro harness", + AstPass::PluginMacroDefs => "plugin macro definitions", + } + } +} + /// The kind of compiler desugaring. #[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum DesugaringKind { @@ -767,14 +778,14 @@ impl DesugaringKind { } } -impl Encodable for SyntaxContext { +impl Encodable for ExpnId { fn encode(&self, _: &mut E) -> Result<(), E::Error> { Ok(()) // FIXME(jseyfried) intercrate hygiene } } -impl Decodable for SyntaxContext { - fn decode(_: &mut D) -> Result { - Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene +impl Decodable for ExpnId { + fn decode(_: &mut D) -> Result { + Ok(ExpnId::root()) // FIXME(jseyfried) intercrate hygiene } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 02a7433d94..e48637498f 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -21,7 +21,8 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; pub mod edition; use edition::Edition; pub mod hygiene; -pub use hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind, MacroKind, DesugaringKind}; +pub use hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind, MacroKind, DesugaringKind}; +use hygiene::Transparency; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -49,7 +50,6 @@ pub struct Globals { symbol_interner: Lock, span_interner: Lock, hygiene_data: Lock, - edition: Edition, } impl Globals { @@ -58,7 +58,6 @@ impl Globals { symbol_interner: Lock::new(symbol::Interner::fresh()), span_interner: Lock::new(span_encoding::SpanInterner::default()), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), - edition, } } } @@ -288,6 +287,17 @@ impl Span { span.lo.0 == 0 && span.hi.0 == 0 } + /// Returns `true` if this span comes from a macro or desugaring. + #[inline] + pub fn from_expansion(self) -> bool { + self.ctxt() != SyntaxContext::root() + } + + #[inline] + pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span { + Span::new(lo, hi, SyntaxContext::root()) + } + /// Returns a new span representing an empty span at the beginning of this span #[inline] pub fn shrink_to_lo(self) -> Span { @@ -344,20 +354,20 @@ impl Span { /// Returns the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { - self.ctxt().outer_expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { expn_data.call_site.source_callsite() } else { self } } /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any. pub fn parent(self) -> Option { - self.ctxt().outer_expn_info().map(|i| i.call_site) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { Some(expn_data.call_site) } else { None } } /// Edition of the crate from which this span came. pub fn edition(self) -> edition::Edition { - self.ctxt().outer_expn_info().map_or_else(|| { - Edition::from_session() - }, |einfo| einfo.edition) + self.ctxt().outer_expn_data().edition } #[inline] @@ -373,52 +383,42 @@ impl Span { /// Returns the source callee. /// /// Returns `None` if the supplied span has no expansion trace, - /// else returns the `ExpnInfo` for the macro definition + /// else returns the `ExpnData` for the macro definition /// corresponding to the source callsite. - pub fn source_callee(self) -> Option { - fn source_callee(info: ExpnInfo) -> ExpnInfo { - match info.call_site.ctxt().outer_expn_info() { - Some(info) => source_callee(info), - None => info, - } + pub fn source_callee(self) -> Option { + fn source_callee(expn_data: ExpnData) -> ExpnData { + let next_expn_data = expn_data.call_site.ctxt().outer_expn_data(); + if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data } } - self.ctxt().outer_expn_info().map(source_callee) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None } } /// Checks if a span is "internal" to a macro in which `#[unstable]` /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). pub fn allows_unstable(&self, feature: Symbol) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info - .allow_internal_unstable - .map_or(false, |features| features.iter().any(|&f| - f == feature || f == sym::allow_internal_unstable_backcompat_hack - )), - None => false, - } + self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| { + features.iter().any(|&f| { + f == feature || f == sym::allow_internal_unstable_backcompat_hack + }) + }) } /// Checks if this span arises from a compiler desugaring of kind `kind`. pub fn is_desugaring(&self, kind: DesugaringKind) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => match info.kind { - ExpnKind::Desugaring(k) => k == kind, - _ => false, - }, - None => false, + match self.ctxt().outer_expn_data().kind { + ExpnKind::Desugaring(k) => k == kind, + _ => false, } } /// Returns the compiler desugaring that created this span, or `None` /// if this span is not from a desugaring. pub fn desugaring_kind(&self) -> Option { - match self.ctxt().outer_expn_info() { - Some(info) => match info.kind { - ExpnKind::Desugaring(k) => Some(k), - _ => None - }, - None => None + match self.ctxt().outer_expn_data().kind { + ExpnKind::Desugaring(k) => Some(k), + _ => None } } @@ -426,21 +426,23 @@ impl Span { /// can be used without triggering the `unsafe_code` lint // (that is, a macro marked with `#[allow_internal_unsafe]`). pub fn allows_unsafe(&self) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info.allow_internal_unsafe, - None => false, - } + self.ctxt().outer_expn_data().allow_internal_unsafe } pub fn macro_backtrace(mut self) -> Vec { let mut prev_span = DUMMY_SP; let mut result = vec![]; - while let Some(info) = self.ctxt().outer_expn_info() { + loop { + let expn_data = self.ctxt().outer_expn_data(); + if expn_data.is_root() { + break; + } // Don't print recursive invocations. - if !info.call_site.source_equal(&prev_span) { - let (pre, post) = match info.kind { + if !expn_data.call_site.source_equal(&prev_span) { + let (pre, post) = match expn_data.kind { ExpnKind::Root => break, ExpnKind::Desugaring(..) => ("desugaring of ", ""), + ExpnKind::AstPass(..) => ("", ""), ExpnKind::Macro(macro_kind, _) => match macro_kind { MacroKind::Bang => ("", "!"), MacroKind::Attr => ("#[", "]"), @@ -448,14 +450,14 @@ impl Span { } }; result.push(MacroBacktrace { - call_site: info.call_site, - macro_decl_name: format!("{}{}{}", pre, info.kind.descr(), post), - def_site_span: info.def_site, + call_site: expn_data.call_site, + macro_decl_name: format!("{}{}{}", pre, expn_data.kind.descr(), post), + def_site_span: expn_data.def_site, }); } prev_span = self; - self = info.call_site; + self = expn_data.call_site; } result } @@ -468,9 +470,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::empty() { + if span_data.ctxt == SyntaxContext::root() { return end; - } else if end_data.ctxt == SyntaxContext::empty() { + } else if end_data.ctxt == SyntaxContext::root() { return self; } // Both spans fall within a macro. @@ -479,7 +481,7 @@ impl Span { Span::new( cmp::min(span_data.lo, end_data.lo), cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt }, + if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, ) } @@ -490,7 +492,7 @@ impl Span { Span::new( span.hi, end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, + if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, ) } @@ -501,7 +503,7 @@ impl Span { Span::new( span.lo, end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, + if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, ) } @@ -512,10 +514,29 @@ impl Span { span.ctxt) } + /// Equivalent of `Span::def_site` from the proc macro API, + /// except that the location is taken from the `self` span. + pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span { + self.with_ctxt_from_mark(expn_id, Transparency::Opaque) + } + + /// Equivalent of `Span::call_site` from the proc macro API, + /// except that the location is taken from the `self` span. + pub fn with_call_site_ctxt(&self, expn_id: ExpnId) -> Span { + self.with_ctxt_from_mark(expn_id, Transparency::Transparent) + } + + /// Produces a span with the same location as `self` and context produced by a macro with the + /// given ID and transparency, assuming that macro was defined directly and not produced by + /// some other macro (which is the case for built-in and procedural macros). + pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { + self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency)) + } + #[inline] - pub fn apply_mark(self, mark: ExpnId) -> Span { + pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.apply_mark(mark)) + span.with_ctxt(span.ctxt.apply_mark(expn_id, transparency)) } #[inline] @@ -611,7 +632,7 @@ impl rustc_serialize::UseSpecializedDecodable for Span { d.read_struct("Span", 2, |d| { let lo = d.read_struct_field("lo", 0, Decodable::decode)?; let hi = d.read_struct_field("hi", 1, Decodable::decode)?; - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::with_root_ctxt(lo, hi)) }) } } @@ -755,8 +776,6 @@ impl From> for MultiSpan { } } -pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty(); - /// Identifies an offset of a multi-byte character in a `SourceFile`. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] pub struct MultiByteChar { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e301a06997..189a08b5c1 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -8,13 +8,13 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::newtype_index; use rustc_macros::symbols; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable}; use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; use std::fmt; use std::hash::{Hash, Hasher}; use std::str; -use crate::hygiene::SyntaxContext; use crate::{Span, DUMMY_SP, GLOBALS}; #[cfg(test)] @@ -83,11 +83,11 @@ symbols! { Yield: "yield", // Edition-specific keywords that are used in stable Rust. + Async: "async", // >= 2018 Edition only + Await: "await", // >= 2018 Edition only Dyn: "dyn", // >= 2018 Edition only // Edition-specific keywords that are used in unstable Rust or reserved for future use. - Async: "async", // >= 2018 Edition only - Await: "await", // >= 2018 Edition only Try: "try", // >= 2018 Edition only // Special lifetime names @@ -225,9 +225,10 @@ symbols! { custom_inner_attributes, custom_test_frameworks, c_variadic, - Debug, + debug_trait, declare_lint_pass, decl_macro, + Debug, Decodable, Default, default_lib_allocator, @@ -238,6 +239,7 @@ symbols! { deref, deref_mut, derive, + diagnostic, direct, doc, doc_alias, @@ -470,6 +472,7 @@ symbols! { option_env, opt_out_copy, or, + or_patterns, Ord, Ordering, Output, @@ -568,6 +571,7 @@ symbols! { rustc_conversion_suggestion, rustc_def_path, rustc_deprecated, + rustc_diagnostic_item, rustc_diagnostic_macros, rustc_dirty, rustc_dummy, @@ -610,7 +614,6 @@ symbols! { rust_eh_personality, rust_eh_unwind_resume, rust_oom, - __rust_unstable_column, rvalue_static_promotion, sanitizer_runtime, _Self, @@ -746,25 +749,25 @@ impl Ident { Ident { name, span } } - /// Constructs a new identifier with an empty syntax context. + /// Constructs a new identifier with a dummy span. #[inline] - pub const fn with_empty_ctxt(name: Symbol) -> Ident { + pub const fn with_dummy_span(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) } #[inline] pub fn invalid() -> Ident { - Ident::with_empty_ctxt(kw::Invalid) + Ident::with_dummy_span(kw::Invalid) } /// Maps an interned string to an identifier with an empty syntax context. pub fn from_interned_str(string: InternedString) -> Ident { - Ident::with_empty_ctxt(string.as_symbol()) + Ident::with_dummy_span(string.as_symbol()) } - /// Maps a string to an identifier with an empty span. + /// Maps a string to an identifier with a dummy span. pub fn from_str(string: &str) -> Ident { - Ident::with_empty_ctxt(Symbol::intern(string)) + Ident::with_dummy_span(Symbol::intern(string)) } /// Maps a string and a span to an identifier. @@ -799,27 +802,25 @@ impl Ident { Ident::new(self.name, self.span.modern_and_legacy()) } - /// Transforms an identifier into one with the same name, but gensymed. - pub fn gensym(self) -> Ident { - let name = with_interner(|interner| interner.gensymed(self.name)); - Ident::new(name, self.span) - } - /// Transforms an underscore identifier into one with the same name, but /// gensymed. Leaves non-underscore identifiers unchanged. pub fn gensym_if_underscore(self) -> Ident { - if self.name == kw::Underscore { self.gensym() } else { self } - } - - // WARNING: this function is deprecated and will be removed in the future. - pub fn is_gensymed(self) -> bool { - with_interner(|interner| interner.is_gensymed(self.name)) + if self.name == kw::Underscore { + let name = with_interner(|interner| interner.gensymed(self.name)); + Ident::new(name, self.span) + } else { + self + } } + /// Convert the name to a `LocalInternedString`. This is a slowish + /// operation because it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { self.name.as_str() } + /// Convert the name to an `InternedString`. This is a slowish operation + /// because it requires locking the symbol interner. pub fn as_interned_str(self) -> InternedString { self.name.as_interned_str() } @@ -850,25 +851,26 @@ impl fmt::Display for Ident { } } -impl Encodable for Ident { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - if self.span.ctxt().modern() == SyntaxContext::empty() { - s.emit_str(&self.as_str()) - } else { // FIXME(jseyfried): intercrate hygiene - let mut string = "#".to_owned(); - string.push_str(&self.as_str()); - s.emit_str(&string) - } +impl UseSpecializedEncodable for Ident { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_struct("Ident", 2, |s| { + s.emit_struct_field("name", 0, |s| { + self.name.encode(s) + })?; + s.emit_struct_field("span", 1, |s| { + self.span.encode(s) + }) + }) } } -impl Decodable for Ident { - fn decode(d: &mut D) -> Result { - let string = d.read_str()?; - Ok(if !string.starts_with('#') { - Ident::from_str(&string) - } else { // FIXME(jseyfried): intercrate hygiene - Ident::from_str(&string[1..]).gensym() +impl UseSpecializedDecodable for Ident { + fn default_decode(d: &mut D) -> Result { + d.read_struct("Ident", 2, |d| { + Ok(Ident { + name: d.read_struct_field("name", 0, Decodable::decode)?, + span: d.read_struct_field("span", 1, Decodable::decode)?, + }) }) } } @@ -885,9 +887,12 @@ impl Decodable for Ident { /// /// Examples: /// ``` -/// assert_eq!(Ident::from_str("x"), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym()) +/// assert_eq!(Ident::from_str("_"), Ident::from_str("_")) +/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_")) +/// assert_ne!( +/// Ident::from_str("_").gensym_if_underscore(), +/// Ident::from_str("_").gensym_if_underscore(), +/// ) /// ``` /// Internally, a symbol is implemented as an index, and all operations /// (including hashing, equality, and ordering) operate on that index. The use @@ -913,6 +918,25 @@ impl Symbol { with_interner(|interner| interner.intern(string)) } + /// Access the symbol's chars. This is a slowish operation because it + /// requires locking the symbol interner. + pub fn with R, R>(self, f: F) -> R { + with_interner(|interner| { + f(interner.get(self)) + }) + } + + /// Access two symbols' chars. This is a slowish operation because it + /// requires locking the symbol interner, but it is faster than calling + /// `with()` twice. + fn with2 R, R>(self, other: Symbol, f: F) -> R { + with_interner(|interner| { + f(interner.get(self), interner.get(other)) + }) + } + + /// Convert to a `LocalInternedString`. This is a slowish operation because + /// it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { @@ -921,6 +945,8 @@ impl Symbol { }) } + /// Convert to an `InternedString`. This is a slowish operation because it + /// requires locking the symbol interner. pub fn as_interned_str(self) -> InternedString { with_interner(|interner| InternedString { symbol: interner.interned(self) @@ -1061,11 +1087,11 @@ pub mod sym { impl Symbol { fn is_used_keyword_2018(self) -> bool { - self == kw::Dyn + self >= kw::Async && self <= kw::Dyn } fn is_unused_keyword_2018(self) -> bool { - self >= kw::Async && self <= kw::Try + self == kw::Try } /// Used for sanity checking rustdoc keyword sections. @@ -1083,6 +1109,11 @@ impl Symbol { self == kw::DollarCrate } + /// Returns `true` if the symbol is `true` or `false`. + pub fn is_bool_lit(self) -> bool { + self == kw::True || self == kw::False + } + /// This symbol can be a raw identifier. pub fn can_be_raw(self) -> bool { self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword() @@ -1144,39 +1175,11 @@ fn with_interner T>(f: F) -> T { // FIXME: ensure that the interner outlives any thread which uses // `LocalInternedString`, by creating a new thread right after constructing the // interner. -#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] pub struct LocalInternedString { string: &'static str, } -impl LocalInternedString { - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - let string = with_interner(|interner| { - let symbol = interner.intern(string); - interner.strings[symbol.0.as_usize()] - }); - LocalInternedString { - string: unsafe { std::mem::transmute::<&str, &str>(string) } - } - } - - pub fn as_interned_str(self) -> InternedString { - InternedString { - symbol: Symbol::intern(self.string) - } - } - - #[inline] - pub fn get(&self) -> &str { - // This returns a valid string since we ensure that `self` outlives the interner - // by creating the interner on a thread which outlives threads which can access it. - // This type cannot move to a thread which outlives the interner since it does - // not implement Send. - self.string - } -} - impl std::convert::AsRef for LocalInternedString where str: std::convert::AsRef @@ -1238,18 +1241,6 @@ impl fmt::Display for LocalInternedString { } } -impl Decodable for LocalInternedString { - fn decode(d: &mut D) -> Result { - Ok(LocalInternedString::intern(&d.read_str()?)) - } -} - -impl Encodable for LocalInternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self.string) - } -} - /// An alternative to `Symbol` that is focused on string contents. It has two /// main differences to `Symbol`. /// @@ -1277,28 +1268,19 @@ impl InternedString { } pub fn with R, R>(self, f: F) -> R { - let str = with_interner(|interner| { - interner.get(self.symbol) as *const str - }); - // This is safe because the interner keeps string alive until it is dropped. - // We can access it because we know the interner is still alive since we use a - // scoped thread local to access it, and it was alive at the beginning of this scope - unsafe { f(&*str) } + self.symbol.with(f) } fn with2 R, R>(self, other: &InternedString, f: F) -> R { - let (self_str, other_str) = with_interner(|interner| { - (interner.get(self.symbol) as *const str, - interner.get(other.symbol) as *const str) - }); - // This is safe for the same reason that `with` is safe. - unsafe { f(&*self_str, &*other_str) } + self.symbol.with2(other.symbol, f) } pub fn as_symbol(self) -> Symbol { self.symbol } + /// Convert to a `LocalInternedString`. This is a slowish operation because it + /// requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { self.symbol.as_str() } diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml index 4eba9a9d79..2931e0bda9 100644 --- a/src/libterm/Cargo.toml +++ b/src/libterm/Cargo.toml @@ -5,6 +5,8 @@ version = "0.0.0" edition = "2018" [lib] -name = "term" path = "lib.rs" -crate-type = ["dylib", "rlib"] + +[dependencies] +core = { path = "../libcore" } +std = { path = "../libstd" } diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index a72e4c7050..170fbb984c 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -10,8 +10,22 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] -getopts = "0.2.19" +getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } term = { path = "../libterm" } +std = { path = "../libstd" } +core = { path = "../libcore" } +libc = { version = "0.2", default-features = false } +panic_unwind = { path = "../libpanic_unwind" } +panic_abort = { path = "../libpanic_abort" } # not actually used but needed to always have proc_macro in the sysroot proc_macro = { path = "../libproc_macro" } + +# Forward features to the `std` crate as necessary +[features] +backtrace = ["std/backtrace"] +compiler-builtins-c = ["std/compiler-builtins-c"] +llvm-libunwind = ["std/llvm-libunwind"] +panic-unwind = ["std/panic_unwind"] +panic_immediate_abort = ["std/panic_immediate_abort"] +profiler = ["std/profiler"] diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index a06497f986..e0bea4ce54 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -9,44 +9,57 @@ impl JsonFormatter { Self { out } } - fn write_message(&mut self, s: &str) -> io::Result<()> { + fn writeln_message(&mut self, s: &str) -> io::Result<()> { assert!(!s.contains('\n')); self.out.write_all(s.as_ref())?; self.out.write_all(b"\n") } + fn write_message(&mut self, s: &str) -> io::Result<()> { + assert!(!s.contains('\n')); + + self.out.write_all(s.as_ref()) + } + fn write_event( &mut self, ty: &str, name: &str, evt: &str, - extra: Option, + stdout: Option>, + extra: Option<&str>, ) -> io::Result<()> { - if let Some(extras) = extra { + self.write_message(&*format!( + r#"{{ "type": "{}", "name": "{}", "event": "{}""#, + ty, name, evt + ))?; + if let Some(stdout) = stdout { self.write_message(&*format!( - r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#, - ty, name, evt, extras - )) - } else { + r#", "stdout": "{}""#, + EscapedString(stdout) + ))?; + } + if let Some(extra) = extra { self.write_message(&*format!( - r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#, - ty, name, evt - )) + r#", {}"#, + extra + ))?; } + self.writeln_message(" }") } } impl OutputFormatter for JsonFormatter { fn write_run_start(&mut self, test_count: usize) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#, test_count )) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, desc.name )) @@ -57,34 +70,30 @@ impl OutputFormatter for JsonFormatter { desc: &TestDesc, result: &TestResult, stdout: &[u8], + state: &ConsoleTestState, ) -> io::Result<()> { + let stdout = if (state.options.display_output || *result != TrOk) && stdout.len() > 0 { + Some(String::from_utf8_lossy(stdout)) + } else { + None + }; match *result { - TrOk => self.write_event("test", desc.name.as_slice(), "ok", None), - - TrFailed => { - let extra_data = if stdout.len() > 0 { - Some(format!( - r#""stdout": "{}""#, - EscapedString(String::from_utf8_lossy(stdout)) - )) - } else { - None - }; + TrOk => self.write_event("test", desc.name.as_slice(), "ok", stdout, None), - self.write_event("test", desc.name.as_slice(), "failed", extra_data) - } + TrFailed => self.write_event("test", desc.name.as_slice(), "failed", stdout, None), TrFailedMsg(ref m) => self.write_event( "test", desc.name.as_slice(), "failed", - Some(format!(r#""message": "{}""#, EscapedString(m))), + stdout, + Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None), + TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", stdout, None), TrAllowedFail => { - self.write_event("test", desc.name.as_slice(), "allowed_failure", None) + self.write_event("test", desc.name.as_slice(), "allowed_failure", stdout, None) } TrBench(ref bs) => { @@ -105,20 +114,20 @@ impl OutputFormatter for JsonFormatter { desc.name, median, deviation, mbps ); - self.write_message(&*line) + self.writeln_message(&*line) } } } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, desc.name )) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { - self.write_message(&*format!( + self.writeln_message(&*format!( "{{ \"type\": \"suite\", \ \"event\": \"{}\", \ \"passed\": {}, \ diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index be5f6a6503..cc30b06e5e 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -17,6 +17,7 @@ pub(crate) trait OutputFormatter { desc: &TestDesc, result: &TestResult, stdout: &[u8], + state: &ConsoleTestState, ) -> io::Result<()>; fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result; } diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 4af00428ca..88331406a6 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -162,7 +162,13 @@ impl OutputFormatter for PrettyFormatter { Ok(()) } - fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> { + fn write_result( + &mut self, + desc: &TestDesc, + result: &TestResult, + _: &[u8], + _: &ConsoleTestState, + ) -> io::Result<()> { if self.is_multithreaded { self.write_test_name(desc)?; } diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 1400fba5d6..d10b0c5807 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -170,7 +170,13 @@ impl OutputFormatter for TerseFormatter { Ok(()) } - fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> { + fn write_result( + &mut self, + desc: &TestDesc, + result: &TestResult, + _: &[u8], + _: &ConsoleTestState, + ) -> io::Result<()> { match *result { TrOk => self.write_ok(), TrFailed | TrFailedMsg(_) => self.write_failed(), diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ef66c4df99..09d5fcc895 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -274,7 +274,7 @@ impl Options { // The default console test runner. It accepts the command line // arguments and a vector of test_descs. -pub fn test_main(args: &[String], tests: Vec, options: Options) { +pub fn test_main(args: &[String], tests: Vec, options: Option) { let mut opts = match parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { @@ -283,8 +283,9 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { } None => return, }; - - opts.options = options; + if let Some(options) = options { + opts.options = options; + } if opts.list { if let Err(e) = list_tests_console(&opts, tests) { eprintln!("error: io error when listing tests: {:?}", e); @@ -325,7 +326,7 @@ pub fn test_main_static(tests: &[&TestDescAndFn]) { _ => panic!("non-static tests passed to test::test_main_static"), }) .collect(); - test_main(&args, owned_tests, Options::new()) + test_main(&args, owned_tests, None) } /// Invoked when unit tests terminate. Should panic if the unit @@ -448,6 +449,11 @@ fn optgroups() -> getopts::Options { json = Output a json document", "pretty|terse|json", ) + .optflag( + "", + "show-output", + "Show captured stdout of successful tests" + ) .optopt( "Z", "", @@ -647,7 +653,7 @@ pub fn parse_opts(args: &[String]) -> Option { format, test_threads, skip: matches.opt_strs("skip"), - options: Options::new(), + options: Options::new().display_output(matches.opt_present("show-output")), }; Some(Ok(test_opts)) @@ -880,7 +886,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu TeTimeout(ref test) => out.write_timeout(test), TeResult(test, result, stdout) => { st.write_log_result(&test, &result)?; - out.write_result(&test, &result, &*stdout)?; + out.write_result(&test, &result, &*stdout, &st)?; match result { TrOk => { st.passed += 1; @@ -965,12 +971,11 @@ fn use_color(opts: &TestOpts) -> bool { #[cfg(any( target_os = "cloudabi", - target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx") ))] fn stdout_isatty() -> bool { - // FIXME: Implement isatty on Redox and SGX + // FIXME: Implement isatty on SGX false } #[cfg(unix)] @@ -1193,15 +1198,15 @@ fn get_concurrency() -> usize { } } - #[cfg(target_os = "redox")] + #[cfg(target_os = "vxworks")] fn num_cpus() -> usize { - // FIXME: Implement num_cpus on Redox + // FIXME: Implement num_cpus on vxWorks 1 } - #[cfg(target_os = "vxworks")] + #[cfg(target_os = "redox")] fn num_cpus() -> usize { - // FIXME: Implement num_cpus on vxWorks + // FIXME: Implement num_cpus on Redox 1 } @@ -1221,7 +1226,7 @@ fn get_concurrency() -> usize { target_os = "ios", target_os = "linux", target_os = "macos", - target_os = "solaris" + target_os = "solaris", ))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index f574743e4b..afc4217ec1 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -180,6 +180,17 @@ fn parse_ignored_flag() { assert_eq!(opts.run_ignored, RunIgnored::Only); } +#[test] +fn parse_show_output_flag() { + let args = vec![ + "progname".to_string(), + "filter".to_string(), + "--show-output".to_string(), + ]; + let opts = parse_opts(&args).unwrap().unwrap(); + assert!(opts.options.display_output); +} + #[test] fn parse_include_ignored_flag() { let args = vec![ diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index f0f1bab425..f10df8c85b 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -22,7 +22,7 @@ compiler_builtins = "0.1.0" cfg-if = "0.1.8" [build-dependencies] -cc = { optional = true, version = "1.0.1" } +cc = { version = "1.0.1" } [features] -llvm-libunwind = ["cc"] +llvm-libunwind = [] diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index da31a49ddf..f24d957d67 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -4,17 +4,15 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); let target = env::var("TARGET").expect("TARGET was not set"); - // FIXME: the not(bootstrap) part is needed because of the issue addressed by #62286, - // and could be removed once that change is in beta. - if cfg!(all(not(bootstrap), feature = "llvm-libunwind")) && - (target.contains("linux") || + if cfg!(feature = "llvm-libunwind") && + ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia")) { // Build the unwinding from libunwind C/C++ source code. - #[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] llvm_libunwind::compile(); } else if target.contains("linux") { if target.contains("musl") { - // musl is handled in lib.rs + // linking for musl is handled in lib.rs + llvm_libunwind::compile(); } else if !target.contains("android") { println!("cargo:rustc-link-lib=gcc_s"); } @@ -25,7 +23,11 @@ fn main() { } else if target.contains("netbsd") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("openbsd") { - println!("cargo:rustc-link-lib=c++abi"); + if target.contains("sparc64") { + println!("cargo:rustc-link-lib=gcc"); + } else { + println!("cargo:rustc-link-lib=c++abi"); + } } else if target.contains("solaris") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("dragonfly") { @@ -46,7 +48,6 @@ fn main() { } } -#[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] mod llvm_libunwind { use std::env; use std::path::Path; @@ -98,6 +99,15 @@ mod llvm_libunwind { cfg.file(root.join("src").join(src)); } + if target_env == "musl" { + // use the same C compiler command to compile C++ code so we do not need to setup the + // C++ compiler env variables on the builders + cfg.cpp(false); + // linking for musl is handled in lib.rs + cfg.cargo_metadata(false); + println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap()); + } + cfg.compile("unwind"); } } diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index aacbfc547d..7c9eaa51fd 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -70,7 +70,7 @@ pub enum _Unwind_Context {} pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); -#[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", +#[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -97,7 +97,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm } pub use _Unwind_Action::*; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -153,7 +153,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm pub const UNWIND_POINTER_REG: c_int = 12; pub const UNWIND_IP_REG: c_int = 15; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -218,7 +218,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm cfg_if::cfg_if! { if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { // Not 32-bit iOS - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -230,7 +230,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { } } else { // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { diff --git a/src/stage0.txt b/src/stage0.txt index 017ff4b277..20e87d435b 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,9 +12,9 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-08-15 -rustc: 1.37.0 -cargo: 0.38.0 +date: 2019-09-26 +rustc: 1.38.0 +cargo: 0.39.0 # When making a stable release the process currently looks like: # diff --git a/src/stdarch/.appveyor.yml b/src/stdarch/.appveyor.yml deleted file mode 100644 index f6016e68a0..0000000000 --- a/src/stdarch/.appveyor.yml +++ /dev/null @@ -1,30 +0,0 @@ -environment: - # We don't want to do identical comdat folding as it messes up the ability to - # generate lossless backtraces in some cases. This is enabled by rustc by - # default so pass a flag to disable it to ensure our tests work ok. - RUSTFLAGS: -Clink-args=/OPT:NOICF - - # VS2017 looks to be the first with avx-512 support, notably in dumpbin - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - matrix: - - TARGET: x86_64-pc-windows-msvc - -install: - # Install rust, x86_64-pc-windows-msvc host - - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - if NOT "%TARGET%" == "x86_64-pc-windows-msvc" rustup target add %TARGET% - - rustc -vV - - cargo -vV - -build: false - -test_script: - - set STDSIMD_DISABLE_ASSERT_INSTR=1 - - C:\msys64\usr\bin\sh ci\run.sh - -branches: - only: - - master diff --git a/src/stdarch/.cirrus.yml b/src/stdarch/.cirrus.yml new file mode 100644 index 0000000000..b5c1196c27 --- /dev/null +++ b/src/stdarch/.cirrus.yml @@ -0,0 +1,13 @@ +task: + name: x86_64-unknown-freebsd + freebsd_instance: + image: freebsd-12-0-release-amd64 + setup_script: + - pkg install -y curl + - curl https://sh.rustup.rs -sSf --output rustup.sh + - sh rustup.sh --default-toolchain nightly -y + - . $HOME/.cargo/env + - rustup default nightly + test_script: + - . $HOME/.cargo/env + - cargo build --all diff --git a/src/stdarch/README.md b/src/stdarch/README.md index 699d076a38..77079ac5ae 100644 --- a/src/stdarch/README.md +++ b/src/stdarch/README.md @@ -1,7 +1,7 @@ stdarch - Rust's standard library SIMD components ======= -[![Travis-CI Status]][travis] [![Appveyor Status]][appveyor] +[![Azure Pipelines Status]][azure] # Crates @@ -29,10 +29,8 @@ To do a release of the `core_arch` and `std_detect` crates, https://github.com/rust-lang/cargo/issues/4242), * publish the crates. -[travis]: https://travis-ci.com/rust-lang/stdarch -[Travis-CI Status]: https://travis-ci.com/rust-lang/stdarch.svg?branch=master -[appveyor]: https://ci.appveyor.com/project/rust-lang-libs/stdarch/branch/master -[Appveyor Status]: https://ci.appveyor.com/api/projects/status/ix74qhmilpibn00x/branch/master?svg=true +[azure]: https://dev.azure.com/rust-lang2/stdarch/_build/latest?definitionId=2&branchName=auto +[Azure Pipelines Status]: https://dev.azure.com/rust-lang2/stdarch/_apis/build/status/rust-lang.stdarch?branchName=auto [core_arch_crate_badge]: https://img.shields.io/crates/v/core_arch.svg [core_arch_crate_link]: https://crates.io/crates/core_arch [core_arch_docs_badge]: https://docs.rs/core_arch/badge.svg diff --git a/src/stdarch/azure-pipelines.yml b/src/stdarch/ci/azure.yml similarity index 78% rename from src/stdarch/azure-pipelines.yml rename to src/stdarch/ci/azure.yml index 212ec27def..bb8f220956 100644 --- a/src/stdarch/azure-pipelines.yml +++ b/src/stdarch/ci/azure.yml @@ -5,8 +5,8 @@ resources: - repository: rustinfra type: github name: rust-lang/simpleinfra - endpoint: rust-lang -trigger: ["master"] + endpoint: gnzlbg +trigger: ["auto", "try"] pr: ["master"] jobs: @@ -15,7 +15,7 @@ jobs: pool: vmImage: ubuntu-16.04 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - bash: | if [ "${NO_DOCKER}" = "1" ]; then ci/run.sh $TARGET @@ -62,7 +62,7 @@ jobs: pool: vmImage: ubuntu-16.04 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - bash: | if [ "${NO_DOCKER}" = "1" ]; then ci/run.sh $TARGET @@ -121,7 +121,7 @@ jobs: pool: vmImage: macos-10.14 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - bash: sh ./ci/run.sh $TARGET displayName: Execute run.sh strategy: @@ -134,7 +134,7 @@ jobs: pool: vmImage: macos-10.13 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - bash: sh ./ci/run.sh $TARGET displayName: Execute run.sh strategy: @@ -147,7 +147,7 @@ jobs: pool: vmImage: vs2017-win2016 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - bash: sh ./ci/run.sh $TARGET displayName: Execute run.sh strategy: @@ -168,7 +168,7 @@ jobs: pool: vmImage: ubuntu-16.04 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - script: sh ci/style.sh displayName: Check style - script: sh ci/dox.sh @@ -184,38 +184,38 @@ jobs: pool: vmImage: ubuntu-16.04 steps: - - template: ci/azure-install-rust.yml + - template: azure-install-rust.yml - script: cargo test --manifest-path crates/stdarch-verify/Cargo.toml displayName: Automatic verification - - job: GameBoyAdvance - dependsOn: StyleAndDocs - pool: - vmImage: ubuntu-16.04 - steps: - - template: ci/azure-install-rust.yml - - script: rustup component add rust-src - displayName: Add rust-src - - script: (test -x $HOME/.cargo/bin/cargo-xbuild || cargo install cargo-xbuild) - displayName: Add cargo-xbuild +# - job: GameBoyAdvance +# dependsOn: StyleAndDocs +# pool: +# vmImage: ubuntu-16.04 +# steps: +# - template: azure-install-rust.yml +# - script: rustup component add rust-src +# displayName: Add rust-src +# - script: (test -x $HOME/.cargo/bin/cargo-xbuild || cargo install cargo-xbuild) +# displayName: Add cargo-xbuild # Obtain the devkitPro tools, using `target/` as a temp directory. This # is required because we need to use their linker. `lld` uses the `BLX` # instruction, which was not available in thumb state code until ARMv5. - - script: | - mkdir -p target - cd target - wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb - sudo dpkg -i devkitpro-pacman.deb - sudo dkp-pacman -Sy - sudo dkp-pacman -Syu - sudo dkp-pacman -S -v --noconfirm gba-tools devkitARM - export PATH="$PATH:/opt/devkitpro/devkitARM/bin" - export PATH="$PATH:/opt/devkitpro/tools/bin" - cd .. - # Pull the target spec up into the current directory and then build - mv ci/gba.json gba.json - cargo xbuild -p core_arch --target gba.json - variables: - NORUN: 1 - NOSTD: 1 - NO_DOCKER: 1 +# - script: | +# mkdir -p target +# cd target +# wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb +# sudo dpkg -i devkitpro-pacman.deb +# sudo dkp-pacman -Sy +# sudo dkp-pacman -Syu +# sudo dkp-pacman -S -v --noconfirm gba-tools devkitARM +# export PATH="$PATH:/opt/devkitpro/devkitARM/bin" +# export PATH="$PATH:/opt/devkitpro/tools/bin" +# cd .. +# # Pull the target spec up into the current directory and then build +# mv ci/gba.json gba.json +# cargo xbuild -p core_arch --target gba.json +# variables: +# NORUN: 1 +# NOSTD: 1 +# NO_DOCKER: 1 diff --git a/src/stdarch/crates/core_arch/Cargo.toml b/src/stdarch/crates/core_arch/Cargo.toml index c67e3e15c9..77c988e480 100644 --- a/src/stdarch/crates/core_arch/Cargo.toml +++ b/src/stdarch/crates/core_arch/Cargo.toml @@ -18,8 +18,7 @@ build = "build.rs" edition = "2018" [badges] -travis-ci = { repository = "rust-lang/stdarch" } -appveyor = { repository = "rust-lang/stdarch" } +azure-devops = { project = "stdarch", pipeline = "rust-lang2.stdarch" } is-it-maintained-issue-resolution = { repository = "rust-lang/stdarch" } is-it-maintained-open-issues = { repository = "rust-lang/stdarch" } maintenance = { status = "experimental" } diff --git a/src/stdarch/crates/core_arch/README.md b/src/stdarch/crates/core_arch/README.md index 89f03b7527..52eb80955b 100644 --- a/src/stdarch/crates/core_arch/README.md +++ b/src/stdarch/crates/core_arch/README.md @@ -1,7 +1,7 @@ `core::arch` - Rust's core library architecture-specific intrinsics ======= -[![Travis-CI Status]][travis] [![Appveyor Status]][appveyor] [![core_arch_crate_badge]][core_arch_crate_link] [![core_arch_docs_badge]][core_arch_docs_link] +[![Azure Pipelines Status]][azure] [![core_arch_crate_badge]][core_arch_crate_link] [![core_arch_docs_badge]][core_arch_docs_link] The `core::arch` module implements architecture-dependent intrinsics (e.g. SIMD). @@ -62,10 +62,8 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `core_arch` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -[travis]: https://travis-ci.com/rust-lang/stdarch -[Travis-CI Status]: https://travis-ci.com/rust-lang/stdarch.svg?branch=master -[appveyor]: https://ci.appveyor.com/project/rust-lang-libs/stdarch/branch/master -[Appveyor Status]: https://ci.appveyor.com/api/projects/status/ix74qhmilpibn00x/branch/master?svg=true +[azure]: https://dev.azure.com/rust-lang2/stdarch/_build/latest?definitionId=2&branchName=auto +[Azure Pipelines Status]: https://dev.azure.com/rust-lang2/stdarch/_apis/build/status/rust-lang.stdarch?branchName=auto [core_arch_crate_badge]: https://img.shields.io/crates/v/core_arch.svg [core_arch_crate_link]: https://crates.io/crates/core_arch [core_arch_docs_badge]: https://docs.rs/core_arch/badge.svg diff --git a/src/stdarch/crates/core_arch/src/aarch64/crc.rs b/src/stdarch/crates/core_arch/src/aarch64/crc.rs index 278a785627..32dddab811 100644 --- a/src/stdarch/crates/core_arch/src/aarch64/crc.rs +++ b/src/stdarch/crates/core_arch/src/aarch64/crc.rs @@ -138,5 +138,4 @@ mod tests { assert_eq!(__crc32cd(0, 0), 0); assert_eq!(__crc32cd(0, 18446744073709551615), 3293575501); } - } diff --git a/src/stdarch/crates/core_arch/src/aarch64/neon.rs b/src/stdarch/crates/core_arch/src/aarch64/neon.rs index 46af4567b3..2ddd97273c 100644 --- a/src/stdarch/crates/core_arch/src/aarch64/neon.rs +++ b/src/stdarch/crates/core_arch/src/aarch64/neon.rs @@ -1980,7 +1980,6 @@ mod tests { test_vcombine!(test_vcombine_u64 => vcombine_u64([3_u64], [13_u64])); test_vcombine!(test_vcombine_p64 => vcombine_p64([3_u64], [13_u64])); test_vcombine!(test_vcombine_f64 => vcombine_f64([-3_f64], [13_f64])); - } #[cfg(test)] diff --git a/src/stdarch/crates/core_arch/src/acle/dsp.rs b/src/stdarch/crates/core_arch/src/acle/dsp.rs index 03cc082697..49986fa6ef 100644 --- a/src/stdarch/crates/core_arch/src/acle/dsp.rs +++ b/src/stdarch/crates/core_arch/src/acle/dsp.rs @@ -381,5 +381,4 @@ mod tests { assert_eq!(super::__smlawt(a, transmute(b), c), r); } } - } diff --git a/src/stdarch/crates/core_arch/src/mips/msa.rs b/src/stdarch/crates/core_arch/src/mips/msa.rs index 46c9bd089a..f93bcdbae7 100644 --- a/src/stdarch/crates/core_arch/src/mips/msa.rs +++ b/src/stdarch/crates/core_arch/src/mips/msa.rs @@ -1137,7 +1137,7 @@ extern "C" { /// Vector Add Absolute Values. /// /// The absolute values of the elements in vector in `a` (sixteen signed 8-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -1150,7 +1150,7 @@ pub unsafe fn __msa_add_a_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Add Absolute Values /// /// The absolute values of the elements in vector in `a` (eight signed 16-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (eight signed 16-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -1163,7 +1163,7 @@ pub unsafe fn __msa_add_a_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Add Absolute Values /// /// The absolute values of the elements in vector in `a` (four signed 32-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (four signed 32-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -1176,8 +1176,8 @@ pub unsafe fn __msa_add_a_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Add Absolute Values /// /// The absolute values of the elements in vector in `a` (two signed 64-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (two signed 64-bit integer numbers) -// The result is written to vector (two signed 64-bit integer numbers). +/// are added to the absolute values of the elements in vector `b` (two signed 64-bit integer numbers). +/// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1189,7 +1189,7 @@ pub unsafe fn __msa_add_a_d(a: v2i64, b: v2i64) -> v2i64 { /// Signed Saturated Vector Saturated Add of Absolute Values /// /// The absolute values of the elements in vector in `a` (sixteen signed 8-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (sixteen signed 8-bit integer numbers). /// The saturated signed result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -1202,7 +1202,7 @@ pub unsafe fn __msa_adds_a_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Saturated Add of Absolute Values /// /// The absolute values of the elements in vector in `a` (eight signed 16-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (eight signed 16-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (eight signed 16-bit integer numbers). /// The saturated signed result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -1215,7 +1215,7 @@ pub unsafe fn __msa_adds_a_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Saturated Add of Absolute Values /// /// The absolute values of the elements in vector in `a` (four signed 32-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (four signed 32-bit integer numbers) +/// are added to the absolute values of the elements in vector `b` (four signed 32-bit integer numbers). /// The saturated signed result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -1228,8 +1228,8 @@ pub unsafe fn __msa_adds_a_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Saturated Add of Absolute Values /// /// The absolute values of the elements in vector in `a` (two signed 64-bit integer numbers) -/// are added to the absolute values of the elements in vector `b` (two signed 64-bit integer numbers) -// The saturated signed result is written to vector (two signed 64-bit integer numbers). +/// are added to the absolute values of the elements in vector `b` (two signed 64-bit integer numbers). +/// The saturated signed result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1240,10 +1240,10 @@ pub unsafe fn __msa_adds_a_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Signed Saturated Add of Signed Values /// -/// The elements in vector in `a` (sixteen signed 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers) +/// The elements in vector in `a` (sixteen signed 8-bit integer numbers) +/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest -/// representable signed values before writing the result to vector (sixteen signed 8-bit integer numbers). +/// representable signed values before writing the result to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1255,7 +1255,7 @@ pub unsafe fn __msa_adds_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Saturated Add of Signed Values /// /// The elements in vector in `a` (eight signed 16-bit integer numbers) -/// are added to the elements in vector `b` (eight signed 16-bit integer numbers) +/// are added to the elements in vector `b` (eight signed 16-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (eight signed 16-bit integer numbers). /// @@ -1269,7 +1269,7 @@ pub unsafe fn __msa_adds_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Saturated Add of Signed Values /// /// The elements in vector in `a` (four signed 32-bit integer numbers) -/// are added to the elements in vector `b` (four signed 32-bit integer numbers) +/// are added to the elements in vector `b` (four signed 32-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (four signed 32-bit integer numbers). /// @@ -1283,7 +1283,7 @@ pub unsafe fn __msa_adds_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Saturated Add of Signed Values /// /// The elements in vector in `a` (two signed 64-bit integer numbers) -/// are added to the elements in vector `b` (two signed 64-bit integer numbers) +/// are added to the elements in vector `b` (two signed 64-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (two signed 64-bit integer numbers). /// @@ -1297,7 +1297,7 @@ pub unsafe fn __msa_adds_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Saturated Add of Unsigned Values /// /// The elements in vector in `a` (sixteen unsigned 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (sixteen unsigned 8-bit integer numbers). /// @@ -1311,7 +1311,7 @@ pub unsafe fn __msa_adds_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Saturated Add of Unsigned Values /// /// The elements in vector in `a` (eight unsigned 16-bit integer numbers) -/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers) +/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (eight unsigned 16-bit integer numbers). /// @@ -1325,7 +1325,7 @@ pub unsafe fn __msa_adds_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Saturated Add of Unsigned Values /// /// The elements in vector in `a` (four unsigned 32-bit integer numbers) -/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers) +/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (four unsigned 32-bit integer numbers). /// @@ -1339,7 +1339,7 @@ pub unsafe fn __msa_adds_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Saturated Add of Unsigned Values /// /// The elements in vector in `a` (two unsigned 64-bit integer numbers) -/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers) +/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (two unsigned 64-bit integer numbers). /// @@ -1353,7 +1353,7 @@ pub unsafe fn __msa_adds_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Add /// /// The elements in vector in `a` (sixteen signed 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -1366,7 +1366,7 @@ pub unsafe fn __msa_addv_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Add /// /// The elements in vector in `a` (eight signed 16-bit integer numbers) -/// are added to the elements in vector `b` (eight signed 16-bit integer numbers) +/// are added to the elements in vector `b` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -1379,7 +1379,7 @@ pub unsafe fn __msa_addv_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Add /// /// The elements in vector in `a` (four signed 32-bit integer numbers) -/// are added to the elements in vector `b` (four signed 32-bit integer numbers) +/// are added to the elements in vector `b` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -1392,7 +1392,7 @@ pub unsafe fn __msa_addv_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Add /// /// The elements in vector in `a` (two signed 64-bit integer numbers) -/// are added to the elements in vector `b` (two signed 64-bit integer numbers) +/// are added to the elements in vector `b` (two signed 64-bit integer numbers). /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -1404,8 +1404,8 @@ pub unsafe fn __msa_addv_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Add /// -/// The 5-bit immediate unsigned value u5 is added to the elements -/// vector in `a` (sixteen signed 8-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` is added to the elements +/// vector in `a` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -1423,8 +1423,8 @@ pub unsafe fn __msa_addvi_b(a: v16i8, imm5: i32) -> v16i8 { /// Immediate Add /// -/// The 5-bit immediate unsigned value u5 is added to the elements -/// vector in `a` (eight signed 16-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` is added to the elements +/// vector in `a` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -1442,8 +1442,8 @@ pub unsafe fn __msa_addvi_h(a: v8i16, imm5: i32) -> v8i16 { /// Immediate Add /// -/// The 5-bit immediate unsigned value u5 is added to the elements -/// vector in `a` (four signed 32-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` is added to the elements +/// vector in `a` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -1461,8 +1461,8 @@ pub unsafe fn __msa_addvi_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Add /// -/// The 5-bit immediate unsigned value u5 is added to the elements -/// vector in `a` (two signed 64-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` is added to the elements +/// vector in `a` (two signed 64-bit integer numbers). /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -1481,7 +1481,7 @@ pub unsafe fn __msa_addvi_d(a: v2i64, imm5: i32) -> v2i64 { /// Vector Logical And /// /// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) -/// is combined with the corresponding bit of vector 'b' (sixteen unsigned 8-bit integer numbers). +/// is combined with the corresponding bit of vector `b` (sixteen unsigned 8-bit integer numbers) /// in a bitwise logical AND operation. /// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// @@ -1494,7 +1494,7 @@ pub unsafe fn __msa_and_v(a: v16u8, b: v16u8) -> v16u8 { /// Immediate Logical And /// -/// Each byte element of vector `a` (sixteen unsigned 8-bit integer numbers) +/// Each byte element of vector `a` (sixteen unsigned 8-bit integer numbers) /// is combined with the 8-bit immediate i8 (signed 8-bit integer number) in a bitwise logical AND operation. /// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// @@ -1514,8 +1514,8 @@ pub unsafe fn __msa_andi_b(a: v16u8, imm8: i32) -> v16u8 { /// Vector Absolute Values of Signed Subtract /// /// The signed elements in vector `a` (sixteen signed 8-bit integer numbers) -/// are subtracted from the signed elements in vector `b` (sixteen signed 8-bit integer numbers) -/// The absolute value of the signed result is written to vector (sixteen signed 8-bit integer numbers). +/// are subtracted from the signed elements in vector `b` (sixteen signed 8-bit integer numbers). +/// The absolute value of the signed result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1527,8 +1527,8 @@ pub unsafe fn __msa_asub_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Absolute Values of Signed Subtract /// /// The signed elements in vector `a` (eight signed 16-bit integer numbers) -/// are subtracted from the signed elements in vector `b` (eight signed 16-bit integer numbers) -/// The absolute value of the signed result is written to vector (eight signed 16-bit integer numbers). +/// are subtracted from the signed elements in vector `b` (eight signed 16-bit integer numbers). +/// The absolute value of the signed result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1540,8 +1540,8 @@ pub unsafe fn __msa_asub_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Absolute Values of Signed Subtract /// /// The signed elements in vector `a` (four signed 32-bit integer numbers) -/// are subtracted from the signed elements in vector `b` (four signed 32-bit integer numbers) -/// The absolute value of the signed result is written to vector (four signed 32-bit integer numbers). +/// are subtracted from the signed elements in vector `b` (four signed 32-bit integer numbers). +/// The absolute value of the signed result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1553,8 +1553,8 @@ pub unsafe fn __msa_asub_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Absolute Values of Signed Subtract /// /// The signed elements in vector `a` (two signed 64-bit integer numbers) -/// are subtracted from the signed elements in vector `b` (two signed 64-bit integer numbers) -/// The absolute value of the signed result is written to vector (two signed 64-bit integer numbers). +/// are subtracted from the signed elements in vector `b` (two signed 64-bit integer numbers). +/// The absolute value of the signed result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1566,8 +1566,8 @@ pub unsafe fn __msa_asub_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Absolute Values of Unsigned Subtract /// /// The unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) -/// are subtracted from the unsigned elements in vector `b` (sixteen unsigned 8-bit integer numbers) -/// The absolute value of the unsigned result is written to vector (sixteen unsigned 8-bit integer numbers). +/// are subtracted from the unsigned elements in vector `b` (sixteen unsigned 8-bit integer numbers). +/// The absolute value of the unsigned result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1579,8 +1579,8 @@ pub unsafe fn __msa_asub_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Absolute Values of Unsigned Subtract /// /// The unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) -/// are subtracted from the unsigned elements in vector `b` (eight unsigned 16-bit integer numbers) -/// The absolute value of the unsigned result is written to vector (eight unsigned 16-bit integer numbers). +/// are subtracted from the unsigned elements in vector `b` (eight unsigned 16-bit integer numbers). +/// The absolute value of the unsigned result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1592,8 +1592,8 @@ pub unsafe fn __msa_asub_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Absolute Values of Unsigned Subtract /// /// The unsigned elements in vector `a` (four unsigned 32-bit integer numbers) -/// are subtracted from the unsigned elements in vector `b` (four unsigned 32-bit integer numbers) -/// The absolute value of the unsigned result is written to vector (four unsigned 32-bit integer numbers). +/// are subtracted from the unsigned elements in vector `b` (four unsigned 32-bit integer numbers). +/// The absolute value of the unsigned result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1605,8 +1605,8 @@ pub unsafe fn __msa_asub_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Absolute Values of Unsigned Subtract /// /// The unsigned elements in vector `a` (two unsigned 64-bit integer numbers) -/// are subtracted from the unsigned elements in vector `b` (two unsigned 64-bit integer numbers) -/// The absolute value of the unsigned result is written to vector (two unsigned 64-bit integer numbers). +/// are subtracted from the unsigned elements in vector `b` (two unsigned 64-bit integer numbers). +/// The absolute value of the unsigned result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -1618,8 +1618,8 @@ pub unsafe fn __msa_asub_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Signed Average /// /// The elements in vector `a` (sixteen signed 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers) -/// The addition is done signed with full precision, i.e.the result has one extra bit +/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers). +/// The addition is done signed with full precision, i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before /// writing the result to vector (sixteen signed 8-bit integer numbers). /// @@ -1633,8 +1633,8 @@ pub unsafe fn __msa_ave_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Average /// /// The elements in vector `a` (eight signed 16-bit integer numbers) -/// are added to the elements in vector `b` (eight signed 16-bit integer numbers) -/// The addition is done signed with full precision, i.e.the result has one extra bit +/// are added to the elements in vector `b` (eight signed 16-bit integer numbers). +/// The addition is done signed with full precision, i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before /// writing the result to vector (eight signed 16-bit integer numbers). /// @@ -1648,8 +1648,8 @@ pub unsafe fn __msa_ave_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Average /// /// The elements in vector `a` (four signed 32-bit integer numbers) -/// are added to the elements in vector `b` (four signed 32-bit integer numbers) -/// The addition is done signed with full precision, i.e.the result has one extra bit +/// are added to the elements in vector `b` (four signed 32-bit integer numbers). +/// The addition is done signed with full precision, i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before /// writing the result to vector (four signed 32-bit integer numbers). /// @@ -1663,8 +1663,8 @@ pub unsafe fn __msa_ave_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Average /// /// The elements in vector `a` (two signed 64-bit integer numbers) -/// are added to the elements in vector `b` (two signed 64-bit integer numbers) -/// The addition is done signed with full precision, i.e.the result has one extra bit +/// are added to the elements in vector `b` (two signed 64-bit integer numbers). +/// The addition is done signed with full precision, i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before /// writing the result to vector (two signed 64-bit integer numbers). /// @@ -1678,9 +1678,9 @@ pub unsafe fn __msa_ave_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Average /// /// The elements in vector `a` (sixteen unsigned 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers) -/// The addition is done unsigned with full precision, i.e.the result has one extra bit -/// Unsigned division by 2 (or logical shift right by one bit) is performed before +/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers). +/// The addition is done unsigned with full precision, i.e. the result has one extra bit. +/// Unsigned division by 2 (or logical shift right by one bit) is performed before /// writing the result to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] @@ -1693,9 +1693,9 @@ pub unsafe fn __msa_ave_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Average /// /// The elements in vector `a` (eight unsigned 16-bit integer numbers) -/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers) -/// The addition is done unsigned with full precision, i.e.the result has one extra bit -/// Unsigned division by 2 (or logical shift right by one bit) is performed before +/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers). +/// The addition is done unsigned with full precision, i.e. the result has one extra bit. +/// Unsigned division by 2 (or logical shift right by one bit) is performed before /// writing the result to vector (eight unsigned 16-bit integer numbers). /// #[inline] @@ -1708,9 +1708,9 @@ pub unsafe fn __msa_ave_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Average /// /// The elements in vector `a` (four unsigned 32-bit integer numbers) -/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers) -/// The addition is done unsigned with full precision, i.e.the result has one extra bit -/// Unsigned division by 2 (or logical shift right by one bit) is performed before +/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers). +/// The addition is done unsigned with full precision, i.e. the result has one extra bit. +/// Unsigned division by 2 (or logical shift right by one bit) is performed before /// writing the result to vector (four unsigned 32-bit integer numbers). /// #[inline] @@ -1723,9 +1723,9 @@ pub unsafe fn __msa_ave_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Average /// /// The elements in vector `a` (two unsigned 64-bit integer numbers) -/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers) -/// The addition is done unsigned with full precision, i.e.the result has one extra bit -/// Unsigned division by 2 (or logical shift right by one bit) is performed before +/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers). +/// The addition is done unsigned with full precision, i.e. the result has one extra bit. +/// Unsigned division by 2 (or logical shift right by one bit) is performed before /// writing the result to vector (two unsigned 64-bit integer numbers). /// #[inline] @@ -1738,7 +1738,7 @@ pub unsafe fn __msa_ave_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Signed Average Rounded /// /// The elements in vector `a` (sixteen signed 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are added to the elements in vector `b` (sixteen signed 8-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done signed with full precision, /// i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before @@ -1754,7 +1754,7 @@ pub unsafe fn __msa_aver_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Average Rounded /// /// The elements in vector `a` (eight signed 16-bit integer numbers) -/// are added to the elements in vector `b` (eight signed 16-bit integer numbers) +/// are added to the elements in vector `b` (eight signed 16-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done signed with full precision, /// i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before @@ -1770,7 +1770,7 @@ pub unsafe fn __msa_aver_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Average Rounded /// /// The elements in vector `a` (four signed 32-bit integer numbers) -/// are added to the elements in vector `b` (four signed 32-bit integer numbers) +/// are added to the elements in vector `b` (four signed 32-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done signed with full precision, /// i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before @@ -1786,7 +1786,7 @@ pub unsafe fn __msa_aver_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Average Rounded /// /// The elements in vector `a` (two signed 64-bit integer numbers) -/// are added to the elements in vector `b` (two signed 64-bit integer numbers) +/// are added to the elements in vector `b` (two signed 64-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done signed with full precision, /// i.e. the result has one extra bit. /// Signed division by 2 (or arithmetic shift right by one bit) is performed before @@ -1802,7 +1802,7 @@ pub unsafe fn __msa_aver_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Average Rounded /// /// The elements in vector `a` (sixteen unsigned 8-bit integer numbers) -/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// are added to the elements in vector `b` (sixteen unsigned 8-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done unsigned with full precision, /// i.e. the result has one extra bit. /// Unsigned division by 2 (or logical shift right by one bit) is performed before @@ -1818,7 +1818,7 @@ pub unsafe fn __msa_aver_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Average Rounded /// /// The elements in vector `a` (eight unsigned 16-bit integer numbers) -/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers) +/// are added to the elements in vector `b` (eight unsigned 16-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done unsigned with full precision, /// i.e. the result has one extra bit. /// Unsigned division by 2 (or logical shift right by one bit) is performed before @@ -1834,7 +1834,7 @@ pub unsafe fn __msa_aver_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Average Rounded /// /// The elements in vector `a` (four unsigned 32-bit integer numbers) -/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers) +/// are added to the elements in vector `b` (four unsigned 32-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done unsigned with full precision, /// i.e. the result has one extra bit. /// Unsigned division by 2 (or logical shift right by one bit) is performed before @@ -1850,7 +1850,7 @@ pub unsafe fn __msa_aver_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Average Rounded /// /// The elements in vector `a` (two unsigned 64-bit integer numbers) -/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers) +/// are added to the elements in vector `b` (two unsigned 64-bit integer numbers). /// The addition of the elements plus 1 (for rounding) is done unsigned with full precision, /// i.e. the result has one extra bit. /// Unsigned division by 2 (or logical shift right by one bit) is performed before @@ -1865,7 +1865,7 @@ pub unsafe fn __msa_aver_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) +/// Clear (set to 0) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). /// The bit position is given by the elements in `b` (sixteen unsigned 8-bit integer numbers) /// modulo the size of the element in bits. /// The result is written to vector (sixteen unsigned 8-bit integer numbers). @@ -1879,7 +1879,7 @@ pub unsafe fn __msa_bclr_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) +/// Clear (set to 0) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). /// The bit position is given by the elements in `b` (eight unsigned 16-bit integer numbers) /// modulo the size of the element in bits. /// The result is written to vector (eight unsigned 16-bit integer numbers). @@ -1893,7 +1893,7 @@ pub unsafe fn __msa_bclr_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (four unsigned 32-bit integer numbers) +/// Clear (set to 0) one bit in each element of vector `a` (four unsigned 32-bit integer numbers). /// The bit position is given by the elements in `b` (four unsigned 32-bit integer numbers) /// modulo the size of the element in bits. /// The result is written to vector (four unsigned 32-bit integer numbers). @@ -1907,7 +1907,7 @@ pub unsafe fn __msa_bclr_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (two unsigned 64-bit integer numbers) +/// Clear (set to 0) one bit in each element of vector `a` (two unsigned 64-bit integer numbers). /// The bit position is given by the elements in `b` (two unsigned 64-bit integer numbers) /// modulo the size of the element in bits. /// The result is written to vector (two unsigned 64-bit integer numbers). @@ -1921,8 +1921,8 @@ pub unsafe fn __msa_bclr_d(a: v2u64, b: v2u64) -> v2u64 { /// Immediate Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) -/// The bit position is given by the immediate 'm' modulo the size of the element in bits. +/// Clear (set to 0) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). +/// The bit position is given by the immediate `m` modulo the size of the element in bits. /// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] @@ -1940,8 +1940,8 @@ pub unsafe fn __msa_bclri_b(a: v16u8, imm3: i32) -> v16u8 { /// Immediate Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) -/// The bit position is given by the immediate 'm' modulo the size of the element in bits. +/// Clear (set to 0) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). +/// The bit position is given by the immediate `m` modulo the size of the element in bits. /// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] @@ -1959,8 +1959,8 @@ pub unsafe fn __msa_bclri_h(a: v8u16, imm4: i32) -> v8u16 { /// Immediate Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (four unsigned 32-bit integer numbers) -/// The bit position is given by the immediate 'm' modulo the size of the element in bits. +/// Clear (set to 0) one bit in each element of vector `a` (four unsigned 32-bit integer numbers). +/// The bit position is given by the immediate `m` modulo the size of the element in bits. /// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] @@ -1978,8 +1978,8 @@ pub unsafe fn __msa_bclri_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Bit Clear /// -/// Clear (set to 0) one bit in each element of vector `a` (two unsigned 64-bit integer numbers) -/// The bit position is given by the immediate 'm' modulo the size of the element in bits. +/// Clear (set to 0) one bit in each element of vector `a` (two unsigned 64-bit integer numbers). +/// The bit position is given by the immediate `m` modulo the size of the element in bits. /// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] @@ -1998,9 +1998,9 @@ pub unsafe fn __msa_bclri_d(a: v2u64, imm6: i32) -> v2u64 { /// Vector Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (sixteen unsigned 8-bit integer numbers) -/// to elements in vector 'a' (sixteen unsigned 8-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the elements in vector 'c' (sixteen unsigned 8-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (sixteen unsigned 8-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the elements in vector `c` (sixteen unsigned 8-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2012,9 +2012,9 @@ pub unsafe fn __msa_binsl_b(a: v16u8, b: v16u8, c: v16u8) -> v16u8 { /// Vector Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (eight unsigned 16-bit integer numbers) -/// to elements in vector 'a' (eight unsigned 16-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the elements in vector 'c' (eight unsigned 16-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (eight unsigned 16-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the elements in vector `c` (eight unsigned 16-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2026,9 +2026,9 @@ pub unsafe fn __msa_binsl_h(a: v8u16, b: v8u16, c: v8u16) -> v8u16 { /// Vector Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (four unsigned 32-bit integer numbers) -/// to elements in vector 'a' (four unsigned 32-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the elements in vector 'c' (four unsigned 32-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (four unsigned 32-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the elements in vector `c` (four unsigned 32-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2040,9 +2040,9 @@ pub unsafe fn __msa_binsl_w(a: v4u32, b: v4u32, c: v4u32) -> v4u32 { /// Vector Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (two unsigned 64-bit integer numbers) -/// to elements in vector 'a' (two unsigned 64-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the elements in vector 'c' (two unsigned 64-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (two unsigned 64-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the elements in vector `c` (two unsigned 64-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2054,8 +2054,8 @@ pub unsafe fn __msa_binsl_d(a: v2u64, b: v2u64, c: v2u64) -> v2u64 { /// Immediate Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (sixteen unsigned 8-bit integer numbers) -/// to elements in vector 'a' (sixteen unsigned 8-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the immediate imm3 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (sixteen unsigned 8-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the immediate `imm3` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2073,8 +2073,8 @@ pub unsafe fn __msa_binsli_b(a: v16u8, b: v16u8, imm3: i32) -> v16u8 { /// Immediate Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (eight unsigned 16-bit integer numbers) -/// to elements in vector 'a' (eight unsigned 16-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the immediate imm4 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (eight unsigned 16-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the immediate `imm4` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2092,8 +2092,8 @@ pub unsafe fn __msa_binsli_h(a: v8u16, b: v8u16, imm4: i32) -> v8u16 { /// Immediate Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (four unsigned 32-bit integer numbers) -/// to elements in vector 'a' (four unsigned 32-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the immediate imm5 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (four unsigned 32-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the immediate `imm5` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2111,8 +2111,8 @@ pub unsafe fn __msa_binsli_w(a: v4u32, b: v4u32, imm5: i32) -> v4u32 { /// Immediate Bit Insert Left /// /// Copy most significant (left) bits in each element of vector `b` (two unsigned 64-bit integer numbers) -/// to elements in vector 'a' (two unsigned 64-bit integer numbers) while preserving the least sig-nificant (right) bits. -/// The number of bits to copy is given by the immediate imm6 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (two unsigned 64-bit integer numbers) while preserving the least significant (right) bits. +/// The number of bits to copy is given by the immediate `imm6` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2130,9 +2130,9 @@ pub unsafe fn __msa_binsli_d(a: v2u64, b: v2u64, imm6: i32) -> v2u64 { /// Vector Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (sixteen unsigned 8-bit integer numbers) -/// to elements in vector 'a' (sixteen unsigned 8-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the elements in vector 'c' (sixteen unsigned 8-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (sixteen unsigned 8-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the elements in vector `c` (sixteen unsigned 8-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2144,9 +2144,9 @@ pub unsafe fn __msa_binsr_b(a: v16u8, b: v16u8, c: v16u8) -> v16u8 { /// Vector Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (eight unsigned 16-bit integer numbers) -/// to elements in vector 'a' (eight unsigned 16-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the elements in vector 'c' (eight unsigned 16-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (eight unsigned 16-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the elements in vector `c` (eight unsigned 16-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2158,9 +2158,9 @@ pub unsafe fn __msa_binsr_h(a: v8u16, b: v8u16, c: v8u16) -> v8u16 { /// Vector Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (four unsigned 32-bit integer numbers) -/// to elements in vector 'a' (four unsigned 32-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the elements in vector 'c' (four unsigned 32-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (four unsigned 32-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the elements in vector `c` (four unsigned 32-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2172,9 +2172,9 @@ pub unsafe fn __msa_binsr_w(a: v4u32, b: v4u32, c: v4u32) -> v4u32 { /// Vector Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (two unsigned 64-bit integer numbers) -/// to elements in vector 'a' (two unsigned 64-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the elements in vector 'c' (two unsigned 64-bit integer numbers) -/// modulo the size of the element inbits plus 1. +/// to elements in vector `a` (two unsigned 64-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the elements in vector `c` (two unsigned 64-bit integer numbers) +/// modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2186,8 +2186,8 @@ pub unsafe fn __msa_binsr_d(a: v2u64, b: v2u64, c: v2u64) -> v2u64 { /// Immediate Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (sixteen unsigned 8-bit integer numbers) -/// to elements in vector 'a' (sixteen unsigned 8-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the immediate imm3 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (sixteen unsigned 8-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the immediate `imm3` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2205,8 +2205,8 @@ pub unsafe fn __msa_binsri_b(a: v16u8, b: v16u8, imm3: i32) -> v16u8 { /// Immediate Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (eight unsigned 16-bit integer numbers) -/// to elements in vector 'a' (eight unsigned 16-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the immediate imm4 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (eight unsigned 16-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the immediate `imm4` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2224,8 +2224,8 @@ pub unsafe fn __msa_binsri_h(a: v8u16, b: v8u16, imm4: i32) -> v8u16 { /// Immediate Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (four unsigned 32-bit integer numbers) -/// to elements in vector 'a' (four unsigned 32-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the immediate imm5 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (four unsigned 32-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the immediate `imm5` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2243,8 +2243,8 @@ pub unsafe fn __msa_binsri_w(a: v4u32, b: v4u32, imm5: i32) -> v4u32 { /// Immediate Bit Insert Right /// /// Copy most significant (right) bits in each element of vector `b` (two unsigned 64-bit integer numbers) -/// to elements in vector 'a' (two unsigned 64-bit integer numbers) while preserving the least sig-nificant (left) bits. -/// The number of bits to copy is given by the immediate imm6 modulo the size of the element in bitsplus 1. +/// to elements in vector `a` (two unsigned 64-bit integer numbers) while preserving the least significant (left) bits. +/// The number of bits to copy is given by the immediate `imm6` modulo the size of the element in bits plus 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2261,9 +2261,9 @@ pub unsafe fn __msa_binsri_d(a: v2u64, b: v2u64, imm6: i32) -> v2u64 { /// Vector Bit Move If Not Zero /// -/// Copy to destination vector 'a' (sixteen unsigned 8-bit integer numbers) all bits from source vector -/// 'b' (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from target vector 'c' -/// (sixteen unsigned 8-bit integer numbers) are 1 and leaves unchanged all destination bits +/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector +/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from target vector `c` +/// (sixteen unsigned 8-bit integer numbers) are 1 and leaves unchanged all destination bits /// for which the corresponding target bits are 0. /// #[inline] @@ -2275,8 +2275,8 @@ pub unsafe fn __msa_bmnz_v(a: v16u8, b: v16u8, c: v16u8) -> v16u8 { /// Immediate Bit Move If Not Zero /// -/// Copy to destination vector 'a' (sixteen unsigned 8-bit integer numbers) all bits from source vector -/// 'b' (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate imm8 +/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector +/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate `imm8` /// are 1 and leaves unchanged all destination bits for which the corresponding target bits are 0. /// #[inline] @@ -2294,10 +2294,10 @@ pub unsafe fn __msa_bmnzi_b(a: v16u8, b: v16u8, imm8: i32) -> v16u8 { /// Vector Bit Move If Zero /// -/// Copy to destination vector 'a' (sixteen unsigned 8-bit integer numbers) all bits from source vector -/// 'b' (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from target vector 'c' -/// (sixteen unsigned 8-bit integer numbers) are 0 and leaves unchanged all destination bits -/// for which the corresponding target bits are 1 +/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector +/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from target vector `c` +/// (sixteen unsigned 8-bit integer numbers) are 0 and leaves unchanged all destination bits +/// for which the corresponding target bits are 1. /// #[inline] #[target_feature(enable = "msa")] @@ -2308,8 +2308,8 @@ pub unsafe fn __msa_bmz_v(a: v16u8, b: v16u8, c: v16u8) -> v16u8 { /// Immediate Bit Move If Zero /// -/// Copy to destination vector 'a' (sixteen unsigned 8-bit integer numbers) all bits from source vector -/// 'b' (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate imm8 +/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector +/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate `imm8` /// are 0 and leaves unchanged all destination bits for which the corresponding immediate bits are 1. /// #[inline] @@ -2327,10 +2327,10 @@ pub unsafe fn __msa_bmzi_b(a: v16u8, b: v16u8, imm8: i32) -> v16u8 { /// Vector Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (sixteen unsigned 8-bit integer numbers) -/// modulo thesize of the element in bits. -/// The result is written to vector (sixteen unsigned 8-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). +/// The bit position is given by the elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// modulo the size of the element in bits. +/// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2341,10 +2341,10 @@ pub unsafe fn __msa_bneg_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (eight unsigned 16-bit integer numbers) -/// modulo thesize of the element in bits. -/// The result is written to vector (eight unsigned 16-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). +/// The bit position is given by the elements in vector `b` (eight unsigned 16-bit integer numbers) +/// modulo the size of the element in bits. +/// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2355,10 +2355,10 @@ pub unsafe fn __msa_bneg_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (four unsigned 32-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (four unsigned 32-bit integer numbers) -/// modulo thesize of the element in bits. -/// The result is written to vector (four unsigned 32-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (four unsigned 32-bit integer numbers). +/// The bit position is given by the elements in vector `b` (four unsigned 32-bit integer numbers) +/// modulo the size of the element in bits. +/// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2369,10 +2369,10 @@ pub unsafe fn __msa_bneg_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (two unsigned 64-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (two unsigned 64-bit integer numbers) -/// modulo thesize of the element in bits. -/// The result is written to vector (two unsigned 64-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (two unsigned 64-bit integer numbers). +/// The bit position is given by the elements in vector `b` (two unsigned 64-bit integer numbers) +/// modulo the size of the element in bits. +/// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2383,9 +2383,9 @@ pub unsafe fn __msa_bneg_d(a: v2u64, b: v2u64) -> v2u64 { /// Immediate Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) -/// The bit position is given by immediate imm3 modulo thesize of the element in bits. -/// The result is written to vector (sixteen unsigned 8-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). +/// The bit position is given by immediate `imm3` modulo the size of the element in bits. +/// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2402,9 +2402,9 @@ pub unsafe fn __msa_bnegi_b(a: v16u8, imm3: i32) -> v16u8 { /// Immediate Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) -/// The bit position is given by immediate imm4 modulo thesize of the element in bits. -/// The result is written to vector (eight unsigned 16-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). +/// The bit position is given by immediate `imm4` modulo the size of the element in bits. +/// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2421,9 +2421,9 @@ pub unsafe fn __msa_bnegi_h(a: v8u16, imm4: i32) -> v8u16 { /// Immediate Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (four unsigned 32-bit integer numbers) -/// The bit position is given by immediate imm5 modulo thesize of the element in bits. -/// The result is written to vector (four unsigned 32-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (four unsigned 32-bit integer numbers). +/// The bit position is given by immediate `imm5` modulo the size of the element in bits. +/// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2440,9 +2440,9 @@ pub unsafe fn __msa_bnegi_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Bit Negate /// -/// Negate (complement) one bit in each element of vector `a` (two unsigned 64-bit integer numbers) -/// The bit position is given by immediate imm6 modulo thesize of the element in bits. -/// The result is written to vector (two unsigned 64-bit integer numbers) +/// Negate (complement) one bit in each element of vector `a` (two unsigned 64-bit integer numbers). +/// The bit position is given by immediate `imm6` modulo the size of the element in bits. +/// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2459,7 +2459,7 @@ pub unsafe fn __msa_bnegi_d(a: v2u64, imm6: i32) -> v2u64 { /// Immediate Branch If All Elements Are Not Zero /// -/// PC-relative branch if all elements in 'a' (sixteen unsigned 8-bit integer numbers) are not zero. +/// PC-relative branch if all elements in `a` (sixteen unsigned 8-bit integer numbers) are not zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2470,7 +2470,7 @@ pub unsafe fn __msa_bnz_b(a: v16u8) -> i32 { /// Immediate Branch If All Elements Are Not Zero /// -/// PC-relative branch if all elements in 'a' (eight unsigned 16-bit integer numbers) are not zero. +/// PC-relative branch if all elements in `a` (eight unsigned 16-bit integer numbers) are not zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2481,7 +2481,7 @@ pub unsafe fn __msa_bnz_h(a: v8u16) -> i32 { /// Immediate Branch If All Elements Are Not Zero /// -/// PC-relative branch if all elements in 'a' (four unsigned 32-bit integer numbers) are not zero. +/// PC-relative branch if all elements in `a` (four unsigned 32-bit integer numbers) are not zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2492,7 +2492,7 @@ pub unsafe fn __msa_bnz_w(a: v4u32) -> i32 { /// Immediate Branch If All Elements Are Not Zero /// -/// PC-relative branch if all elements in 'a' (two unsigned 64-bit integer numbers) are not zero. +/// PC-relative branch if all elements in `a` (two unsigned 64-bit integer numbers) are not zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2503,7 +2503,7 @@ pub unsafe fn __msa_bnz_d(a: v2u64) -> i32 { /// Immediate Branch If Not Zero (At Least One Element of Any Format Is Not Zero) /// -/// PC-relative branch if at least one bit in 'a' (four unsigned 32-bit integer numbers) are not zero. +/// PC-relative branch if at least one bit in `a` (four unsigned 32-bit integer numbers) are not zero. /// i.e at least one element is not zero regardless of the data format. /// #[inline] @@ -2515,10 +2515,10 @@ pub unsafe fn __msa_bnz_v(a: v16u8) -> i32 { /// Vector Bit Select /// -/// Selectively copy bits from the source vectors 'b' (eight unsigned 16-bit integer numbers) -/// and 'c' (eight unsigned 16-bit integer numbers) -/// into destination vector 'a' (eight unsigned 16-bit integer numbers) based on the corresponding bit in a: -/// if 0 copies the bit from 'b', if 1 copies the bit from 'c'. +/// Selectively copy bits from the source vectors `b` (eight unsigned 16-bit integer numbers) +/// and `c` (eight unsigned 16-bit integer numbers) +/// into destination vector `a` (eight unsigned 16-bit integer numbers) based on the corresponding bit in `a`: +/// if 0 copies the bit from `b`, if 1 copies the bit from `c`. /// #[inline] #[target_feature(enable = "msa")] @@ -2529,9 +2529,9 @@ pub unsafe fn __msa_bsel_v(a: v16u8, b: v16u8, c: v16u8) -> v16u8 { /// Immediate Bit Select /// -/// Selectively copy bits from the 8-bit immediate imm8 and 'c' (eight unsigned 16-bit integer numbers) -/// into destination vector 'a' (eight unsigned 16-bit integer numbers) based on the corresponding bit in a: -/// if 0 copies the bit from 'b', if 1 copies the bit from 'c'. +/// Selectively copy bits from the 8-bit immediate `imm8` and `c` (eight unsigned 16-bit integer numbers) +/// into destination vector `a` (eight unsigned 16-bit integer numbers) based on the corresponding bit in `a`: +/// if 0 copies the bit from `b`, if 1 copies the bit from `c`. /// #[inline] #[target_feature(enable = "msa")] @@ -2548,10 +2548,10 @@ pub unsafe fn __msa_bseli_b(a: v16u8, b: v16u8, imm8: i32) -> v16u8 { /// Vector Bit Set /// -/// Set to 1 one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (sixteen unsigned 8-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). +/// The bit position is given by the elements in vector `b` (sixteen unsigned 8-bit integer numbers) /// modulo the size of the element in bits. -/// The result is written to vector (sixteen unsigned 8-bit integer numbers) +/// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2562,10 +2562,10 @@ pub unsafe fn __msa_bset_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Bit Set /// -/// Set to 1 one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (eight unsigned 16-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). +/// The bit position is given by the elements in vector `b` (eight unsigned 16-bit integer numbers) /// modulo the size of the element in bits. -/// The result is written to vector (eight unsigned 16-bit integer numbers) +/// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2576,10 +2576,10 @@ pub unsafe fn __msa_bset_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Bit Set /// -/// Set to 1 one bit in each element of vector `a` (four unsigned 32-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (four unsigned 32-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (four unsigned 32-bit integer numbers). +/// The bit position is given by the elements in vector `b` (four unsigned 32-bit integer numbers) /// modulo the size of the element in bits. -/// The result is written to vector (four unsigned 32-bit integer numbers) +/// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2590,10 +2590,10 @@ pub unsafe fn __msa_bset_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Bit Set /// -/// Set to 1 one bit in each element of vector `a` (two unsigned 64-bit integer numbers) -/// The bit position is given by the elements in vector 'b' (two unsigned 64-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (two unsigned 64-bit integer numbers). +/// The bit position is given by the elements in vector `b` (two unsigned 64-bit integer numbers) /// modulo the size of the element in bits. -/// The result is written to vector (two unsigned 64-bit integer numbers) +/// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2604,9 +2604,9 @@ pub unsafe fn __msa_bset_d(a: v2u64, b: v2u64) -> v2u64 { /// Immediate Bit Set /// -/// Set to 1 one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers) -/// The bit position is given by immediate imm3. -/// The result is written to vector 'a'(sixteen unsigned 8-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (sixteen unsigned 8-bit integer numbers). +/// The bit position is given by immediate `imm3`. +/// The result is written to vector `a` (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2623,9 +2623,9 @@ pub unsafe fn __msa_bseti_b(a: v16u8, imm3: i32) -> v16u8 { /// Immediate Bit Set /// -/// Set to 1 one bit in each element of vector `a` (eight unsigned 16-bit integer numbers) -/// The bit position is given by immediate imm4. -/// The result is written to vector 'a'(eight unsigned 16-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (eight unsigned 16-bit integer numbers). +/// The bit position is given by immediate `imm4`. +/// The result is written to vector `a` (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2642,9 +2642,9 @@ pub unsafe fn __msa_bseti_h(a: v8u16, imm4: i32) -> v8u16 { /// Immediate Bit Set /// -/// Set to 1 one bit in each element of vector `a` (four unsigned 32-bit integer numbers) -/// The bit position is given by immediate imm5. -/// The result is written to vector 'a'(four unsigned 32-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (four unsigned 32-bit integer numbers). +/// The bit position is given by immediate `imm5`. +/// The result is written to vector `a` (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2661,9 +2661,9 @@ pub unsafe fn __msa_bseti_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Bit Set /// -/// Set to 1 one bit in each element of vector `a` (two unsigned 64-bit integer numbers) -/// The bit position is given by immediate imm6. -/// The result is written to vector 'a'(two unsigned 64-bit integer numbers) +/// Set to 1 one bit in each element of vector `a` (two unsigned 64-bit integer numbers). +/// The bit position is given by immediate `imm6`. +/// The result is written to vector `a` (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -2680,7 +2680,7 @@ pub unsafe fn __msa_bseti_d(a: v2u64, imm6: i32) -> v2u64 { /// Immediate Branch If At Least One Element Is Zero /// -/// PC-relative branch if at least one element in 'a' (sixteen unsigned 8-bit integer numbers) is zero. +/// PC-relative branch if at least one element in `a` (sixteen unsigned 8-bit integer numbers) is zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2691,7 +2691,7 @@ pub unsafe fn __msa_bz_b(a: v16u8) -> i32 { /// Immediate Branch If At Least One Element Is Zero /// -/// PC-relative branch if at least one element in 'a' (eight unsigned 16-bit integer numbers) is zero. +/// PC-relative branch if at least one element in `a` (eight unsigned 16-bit integer numbers) is zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2702,7 +2702,7 @@ pub unsafe fn __msa_bz_h(a: v8u16) -> i32 { /// Immediate Branch If At Least One Element Is Zero /// -/// PC-relative branch if at least one element in 'a' (four unsigned 32-bit integer numbers) is zero. +/// PC-relative branch if at least one element in `a` (four unsigned 32-bit integer numbers) is zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2713,7 +2713,7 @@ pub unsafe fn __msa_bz_w(a: v4u32) -> i32 { /// Immediate Branch If At Least One Element Is Zero /// -/// PC-relative branch if at least one element in 'a' (two unsigned 64-bit integer numbers) is zero. +/// PC-relative branch if at least one element in `a` (two unsigned 64-bit integer numbers) is zero. /// #[inline] #[target_feature(enable = "msa")] @@ -2724,8 +2724,8 @@ pub unsafe fn __msa_bz_d(a: v2u64) -> i32 { /// Immediate Branch If Zero (All Elements of Any Format Are Zero) /// -/// PC-relative branch if all elements in 'a' (sixteen unsigned 8-bit integer numbers) bits are zero, -/// i.e. all elements are zero regardless of the data format +/// PC-relative branch if all elements in `a` (sixteen unsigned 8-bit integer numbers) bits are zero, +/// i.e. all elements are zero regardless of the data format. /// #[inline] #[target_feature(enable = "msa")] @@ -2737,7 +2737,7 @@ pub unsafe fn __msa_bz_v(a: v16u8) -> i32 { /// Vector Compare Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) and 'b' (sixteen signed 8-bit integer numbers) +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) and `b` (sixteen signed 8-bit integer numbers) /// elements are equal, otherwise set all bits to 0. /// #[inline] @@ -2750,7 +2750,7 @@ pub unsafe fn __msa_ceq_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Compare Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) and 'b' (eight signed 16-bit integer numbers) +/// if the corresponding `a` (eight signed 16-bit integer numbers) and `b` (eight signed 16-bit integer numbers) /// elements are equal, otherwise set all bits to 0. /// #[inline] @@ -2763,7 +2763,7 @@ pub unsafe fn __msa_ceq_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Compare Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) and 'b' (four signed 32-bit integer numbers) +/// if the corresponding `a` (four signed 32-bit integer numbers) and `b` (four signed 32-bit integer numbers) /// elements are equal, otherwise set all bits to 0. /// #[inline] @@ -2776,7 +2776,7 @@ pub unsafe fn __msa_ceq_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Compare Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) and 'b' (two signed 64-bit integer numbers) +/// if the corresponding `a` (two signed 64-bit integer numbers) and `b` (two signed 64-bit integer numbers) /// elements are equal, otherwise set all bits to 0. /// #[inline] @@ -2789,7 +2789,7 @@ pub unsafe fn __msa_ceq_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Compare Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) the 5-bit signed immediate imm_s5 +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) the 5-bit signed immediate imm_s5 /// are equal, otherwise set all bits to 0. /// #[inline] @@ -2808,7 +2808,7 @@ pub unsafe fn __msa_ceqi_b(a: v16i8, imm_s5: i32) -> v16i8 { /// Immediate Compare Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) the 5-bit signed immediate imm_s5 +/// if the corresponding `a` (eight signed 16-bit integer numbers) the 5-bit signed immediate imm_s5 /// are equal, otherwise set all bits to 0. /// #[inline] @@ -2827,7 +2827,7 @@ pub unsafe fn __msa_ceqi_h(a: v8i16, imm_s5: i32) -> v8i16 { /// Immediate Compare Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) the 5-bit signed immediate imm_s5 +/// if the corresponding `a` (four signed 32-bit integer numbers) the 5-bit signed immediate imm_s5 /// are equal, otherwise set all bits to 0. /// #[inline] @@ -2846,7 +2846,7 @@ pub unsafe fn __msa_ceqi_w(a: v4i32, imm_s5: i32) -> v4i32 { /// Immediate Compare Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) the 5-bit signed immediate imm_s5 +/// if the corresponding `a` (two signed 64-bit integer numbers) the 5-bit signed immediate imm_s5 /// are equal, otherwise set all bits to 0. /// #[inline] @@ -2864,7 +2864,7 @@ pub unsafe fn __msa_ceqi_d(a: v2i64, imm_s5: i32) -> v2i64 { /// GPR Copy from MSA Control Register /// -/// The sign extended content of MSA control register cs is copied to GPRrd. +/// The sign extended content of MSA control register cs is copied to GPR rd. /// /// Can not be tested in user mode #[inline] @@ -2883,9 +2883,9 @@ pub unsafe fn __msa_cfcmsa(imm5: i32) -> i32 { /// Vector Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) element -/// are signed less than or equal to 'b' (sixteen signed 8-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) element +/// are signed less than or equal to `b` (sixteen signed 8-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2897,9 +2897,9 @@ pub unsafe fn __msa_cle_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) element -/// are signed less than or equal to 'b' (eight signed 16-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (eight signed 16-bit integer numbers) element +/// are signed less than or equal to `b` (eight signed 16-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2911,9 +2911,9 @@ pub unsafe fn __msa_cle_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) element -/// are signed less than or equal to 'b' (four signed 32-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (four signed 32-bit integer numbers) element +/// are signed less than or equal to `b` (four signed 32-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2925,9 +2925,9 @@ pub unsafe fn __msa_cle_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) element -/// are signed less than or equal to 'b' (two signed 64-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (two signed 64-bit integer numbers) element +/// are signed less than or equal to `b` (two signed 64-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2939,9 +2939,9 @@ pub unsafe fn __msa_cle_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen unsigned 8-bit integer numbers) element -/// are unsigned less than or equal to 'b' (sixteen unsigned 8-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (sixteen unsigned 8-bit integer numbers) element +/// are unsigned less than or equal to `b` (sixteen unsigned 8-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2953,9 +2953,9 @@ pub unsafe fn __msa_cle_u_b(a: v16u8, b: v16u8) -> v16i8 { /// Vector Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight unsigned 16-bit integer numbers) element -/// are unsigned less than or equal to 'b' (eight unsigned 16-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (eight unsigned 16-bit integer numbers) element +/// are unsigned less than or equal to `b` (eight unsigned 16-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2967,9 +2967,9 @@ pub unsafe fn __msa_cle_u_h(a: v8u16, b: v8u16) -> v8i16 { /// Vector Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four unsigned 32-bit integer numbers) element -/// are unsigned less than or equal to 'b' (four unsigned 32-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (four unsigned 32-bit integer numbers) element +/// are unsigned less than or equal to `b` (four unsigned 32-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2981,9 +2981,9 @@ pub unsafe fn __msa_cle_u_w(a: v4u32, b: v4u32) -> v4i32 { /// Vector Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two unsigned 64-bit integer numbers) element -/// are unsigned less than or equal to 'b' (two unsigned 64-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (two unsigned 64-bit integer numbers) element +/// are unsigned less than or equal to `b` (two unsigned 64-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -2995,7 +2995,7 @@ pub unsafe fn __msa_cle_u_d(a: v2u64, b: v2u64) -> v2i64 { /// Immediate Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) element +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) element /// is less than or equal to the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3015,7 +3015,7 @@ pub unsafe fn __msa_clei_s_b(a: v16i8, imm_s5: i32) -> v16i8 { /// Immediate Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) element +/// if the corresponding `a` (eight signed 16-bit integer numbers) element /// is less than or equal to the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3035,7 +3035,7 @@ pub unsafe fn __msa_clei_s_h(a: v8i16, imm_s5: i32) -> v8i16 { /// Immediate Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) element +/// if the corresponding `a` (four signed 32-bit integer numbers) element /// is less than or equal to the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3055,7 +3055,7 @@ pub unsafe fn __msa_clei_s_w(a: v4i32, imm_s5: i32) -> v4i32 { /// Immediate Compare Signed Less Than or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) element +/// if the corresponding `a` (two signed 64-bit integer numbers) element /// is less than or equal to the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3075,8 +3075,8 @@ pub unsafe fn __msa_clei_s_d(a: v2i64, imm_s5: i32) -> v2i64 { /// Immediate Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen unsigned 8-bit integer numbers) element -/// is unsigned less than or equal to the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (sixteen unsigned 8-bit integer numbers) element +/// is unsigned less than or equal to the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3095,8 +3095,8 @@ pub unsafe fn __msa_clei_u_b(a: v16u8, imm5: i32) -> v16i8 { /// Immediate Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight unsigned 16-bit integer numbers) element -/// is unsigned less than or equal to the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (eight unsigned 16-bit integer numbers) element +/// is unsigned less than or equal to the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3115,8 +3115,8 @@ pub unsafe fn __msa_clei_u_h(a: v8u16, imm5: i32) -> v8i16 { /// Immediate Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four unsigned 32-bit integer numbers) element -/// is unsigned less than or equal to the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (four unsigned 32-bit integer numbers) element +/// is unsigned less than or equal to the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3135,8 +3135,8 @@ pub unsafe fn __msa_clei_u_w(a: v4u32, imm5: i32) -> v4i32 { /// Immediate Compare Unsigned Less Than or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two unsigned 64-bit integer numbers) element -/// is unsigned less than or equal to the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (two unsigned 64-bit integer numbers) element +/// is unsigned less than or equal to the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3155,9 +3155,9 @@ pub unsafe fn __msa_clei_u_d(a: v2u64, imm5: i32) -> v2i64 { /// Vector Compare Signed Less Than /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) element -/// are signed less than 'b' (sixteen signed 8-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) element +/// are signed less than `b` (sixteen signed 8-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3169,9 +3169,9 @@ pub unsafe fn __msa_clt_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Compare Signed Less Than /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) element -/// are signed less than 'b' (eight signed 16-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (eight signed 16-bit integer numbers) element +/// are signed less than `b` (eight signed 16-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3183,9 +3183,9 @@ pub unsafe fn __msa_clt_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Compare Signed Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) element -/// are signed less than 'b' (four signed 32-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (four signed 32-bit integer numbers) element +/// are signed less than `b` (four signed 32-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3197,9 +3197,9 @@ pub unsafe fn __msa_clt_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Compare Signed Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) element -/// are signed less than 'b' (two signed 64-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (two signed 64-bit integer numbers) element +/// are signed less than `b` (two signed 64-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3211,9 +3211,9 @@ pub unsafe fn __msa_clt_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Compare Unsigned Less Than /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen unsigned 8-bit integer numbers) element -/// are unsigned less than 'b' (sixteen unsigned 8-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (sixteen unsigned 8-bit integer numbers) element +/// are unsigned less than `b` (sixteen unsigned 8-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3225,9 +3225,9 @@ pub unsafe fn __msa_clt_u_b(a: v16u8, b: v16u8) -> v16i8 { /// Vector Compare Unsigned Less Than /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight unsigned 16-bit integer numbers) element -/// are unsigned less than 'b' (eight unsigned 16-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (eight unsigned 16-bit integer numbers) element +/// are unsigned less than `b` (eight unsigned 16-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3239,9 +3239,9 @@ pub unsafe fn __msa_clt_u_h(a: v8u16, b: v8u16) -> v8i16 { /// Vector Compare Unsigned Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four unsigned 32-bit integer numbers) element -/// are unsigned less than 'b' (four unsigned 32-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (four unsigned 32-bit integer numbers) element +/// are unsigned less than `b` (four unsigned 32-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3253,9 +3253,9 @@ pub unsafe fn __msa_clt_u_w(a: v4u32, b: v4u32) -> v4i32 { /// Vector Compare Unsigned Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two unsigned 64-bit integer numbers) element -/// are unsigned less than 'b' (two unsigned 64-bit integer numbers) element. -/// otherwise set all bits to 0. +/// if the corresponding `a` (two unsigned 64-bit integer numbers) element +/// are unsigned less than `b` (two unsigned 64-bit integer numbers) element. +/// Otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -3267,7 +3267,7 @@ pub unsafe fn __msa_clt_u_d(a: v2u64, b: v2u64) -> v2i64 { /// Immediate Compare Signed Less Than /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen signed 8-bit integer numbers) element +/// if the corresponding `a` (sixteen signed 8-bit integer numbers) element /// is less than the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3287,7 +3287,7 @@ pub unsafe fn __msa_clti_s_b(a: v16i8, imm_s5: i32) -> v16i8 { /// Immediate Compare Signed Less Than /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight signed 16-bit integer numbers) element +/// if the corresponding `a` (eight signed 16-bit integer numbers) element /// is less than the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3307,7 +3307,7 @@ pub unsafe fn __msa_clti_s_h(a: v8i16, imm_s5: i32) -> v8i16 { /// Immediate Compare Signed Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four signed 32-bit integer numbers) element +/// if the corresponding `a` (four signed 32-bit integer numbers) element /// is less than the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3327,7 +3327,7 @@ pub unsafe fn __msa_clti_s_w(a: v4i32, imm_s5: i32) -> v4i32 { /// Immediate Compare Signed Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two signed 64-bit integer numbers) element +/// if the corresponding `a` (two signed 64-bit integer numbers) element /// is less than the 5-bit signed immediate imm_s5, /// otherwise set all bits to 0. /// @@ -3347,8 +3347,8 @@ pub unsafe fn __msa_clti_s_d(a: v2i64, imm_s5: i32) -> v2i64 { /// Immediate Compare Unsigned Less Than /// /// Set all bits to 1 in vector (sixteen signed 8-bit integer numbers) elements -/// if the corresponding 'a' (sixteen unsigned 8-bit integer numbers) element -/// is unsigned less than the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (sixteen unsigned 8-bit integer numbers) element +/// is unsigned less than the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3367,8 +3367,8 @@ pub unsafe fn __msa_clti_u_b(a: v16u8, imm5: i32) -> v16i8 { /// Immediate Compare Unsigned Less Than /// /// Set all bits to 1 in vector (eight signed 16-bit integer numbers) elements -/// if the corresponding 'a' (eight unsigned 16-bit integer numbers) element -/// is unsigned less than the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (eight unsigned 16-bit integer numbers) element +/// is unsigned less than the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3387,8 +3387,8 @@ pub unsafe fn __msa_clti_u_h(a: v8u16, imm5: i32) -> v8i16 { /// Immediate Compare Unsigned Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four unsigned 32-bit integer numbers) element -/// is unsigned less than the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (four unsigned 32-bit integer numbers) element +/// is unsigned less than the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3407,8 +3407,8 @@ pub unsafe fn __msa_clti_u_w(a: v4u32, imm5: i32) -> v4i32 { /// Immediate Compare Unsigned Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two unsigned 64-bit integer numbers) element -/// is unsigned less than the 5-bit unsigned immediate imm5, +/// if the corresponding `a` (two unsigned 64-bit integer numbers) element +/// is unsigned less than the 5-bit unsigned immediate `imm5`, /// otherwise set all bits to 0. /// #[inline] @@ -3426,8 +3426,8 @@ pub unsafe fn __msa_clti_u_d(a: v2u64, imm5: i32) -> v2i64 { /// Element Copy to GPR Signed /// -/// Sign-extend element imm4 of vector 'a' (sixteen signed 8-bit integer numbers) -/// and copy the result to GPR rd +/// Sign-extend element `imm4` of vector `a` (sixteen signed 8-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3444,8 +3444,8 @@ pub unsafe fn __msa_copy_s_b(a: v16i8, imm4: i32) -> i32 { /// Element Copy to GPR Signed /// -/// Sign-extend element imm3 of vector 'a' (eight signed 16-bit integer numbers) -/// and copy the result to GPR rd +/// Sign-extend element `imm3` of vector `a` (eight signed 16-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3462,8 +3462,8 @@ pub unsafe fn __msa_copy_s_h(a: v8i16, imm3: i32) -> i32 { /// Element Copy to GPR Signed /// -/// Sign-extend element imm2 of vector 'a' (four signed 32-bit integer numbers) -/// and copy the result to GPR rd +/// Sign-extend element `imm2` of vector `a` (four signed 32-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3480,8 +3480,8 @@ pub unsafe fn __msa_copy_s_w(a: v4i32, imm2: i32) -> i32 { /// Element Copy to GPR Signed /// -/// Sign-extend element imm1 of vector 'a' (two signed 64-bit integer numbers) -/// and copy the result to GPR rd +/// Sign-extend element `imm1` of vector `a` (two signed 64-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3498,8 +3498,8 @@ pub unsafe fn __msa_copy_s_d(a: v2i64, imm1: i32) -> i64 { /// Element Copy to GPR Unsigned /// -/// Zero-extend element imm4 of vector 'a' (sixteen signed 8-bit integer numbers) -/// and copy the result to GPR rd +/// Zero-extend element `imm4` of vector `a` (sixteen signed 8-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3516,8 +3516,8 @@ pub unsafe fn __msa_copy_u_b(a: v16i8, imm4: i32) -> u32 { /// Element Copy to GPR Unsigned /// -/// Zero-extend element imm3 of vector 'a' (eight signed 16-bit integer numbers) -/// and copy the result to GPR rd +/// Zero-extend element `imm3` of vector `a` (eight signed 16-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3534,8 +3534,8 @@ pub unsafe fn __msa_copy_u_h(a: v8i16, imm3: i32) -> u32 { /// Element Copy to GPR Unsigned /// -/// Zero-extend element imm2 of vector 'a' (four signed 32-bit integer numbers) -/// and copy the result to GPR rd +/// Zero-extend element `imm2` of vector `a` (four signed 32-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3552,8 +3552,8 @@ pub unsafe fn __msa_copy_u_w(a: v4i32, imm2: i32) -> u32 { /// Element Copy to GPR Unsigned /// -/// Zero-extend element imm1 of vector 'a' (two signed 64-bit integer numbers) -/// and copy the result to GPR rd +/// Zero-extend element `imm1` of vector `a` (two signed 64-bit integer numbers) +/// and copy the result to GPR rd. /// #[inline] #[target_feature(enable = "msa")] @@ -3569,9 +3569,12 @@ pub unsafe fn __msa_copy_u_d(a: v2i64, imm1: i32) -> u64 { } /// GPR Copy to MSA Control Register -/// The content of the least significant 31 bits of GPR imm1 is copied to -/// MSA control register cd +/// +/// The content of the least significant 31 bits of GPR `imm1` is copied to +/// MSA control register cd. +/// /// Can not be tested in user mode +/// #[inline] #[target_feature(enable = "msa")] #[cfg_attr(test, assert_instr(ctcmsa, imm1 = 0b1))] @@ -3587,8 +3590,8 @@ pub unsafe fn __msa_ctcmsa(imm5: i32, a: i32) -> () { /// Vector Signed Divide /// -/// The signed integer elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// are divided by signed integer elements in vector 'b' (sixteen signed 8-bit integer numbers). +/// The signed integer elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are divided by signed integer elements in vector `b` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -3600,8 +3603,8 @@ pub unsafe fn __msa_div_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Divide /// -/// The signed integer elements in vector 'a' (eight signed 16-bit integer numbers) -/// are divided by signed integer elements in vector 'b' (eight signed 16-bit integer numbers). +/// The signed integer elements in vector `a` (eight signed 16-bit integer numbers) +/// are divided by signed integer elements in vector `b` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -3613,8 +3616,8 @@ pub unsafe fn __msa_div_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Divide /// -/// The signed integer elements in vector 'a' (four signed 32-bit integer numbers) -/// are divided by signed integer elements in vector 'b' (four signed 32-bit integer numbers). +/// The signed integer elements in vector `a` (four signed 32-bit integer numbers) +/// are divided by signed integer elements in vector `b` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -3626,8 +3629,8 @@ pub unsafe fn __msa_div_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Divide /// -/// The signed integer elements in vector 'a' (two signed 64-bit integer numbers) -/// are divided by signed integer elements in vector 'b' (two signed 64-bit integer numbers). +/// The signed integer elements in vector `a` (two signed 64-bit integer numbers) +/// are divided by signed integer elements in vector `b` (two signed 64-bit integer numbers). /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -3639,8 +3642,8 @@ pub unsafe fn __msa_div_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Divide /// -/// The unsigned integer elements in vector 'a' (sixteen unsigned 8-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b' (sixteen unsigned 8-bit integer numbers). +/// The unsigned integer elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (sixteen unsigned 8-bit integer numbers). /// The result is written to vector (sixteen unsigned 8-bit integer numbers). /// #[inline] @@ -3652,8 +3655,8 @@ pub unsafe fn __msa_div_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Divide /// -/// The unsigned integer elements in vector 'a' (eight unsigned 16-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b' (eight unsigned 16-bit integer numbers). +/// The unsigned integer elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (eight unsigned 16-bit integer numbers). /// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] @@ -3665,8 +3668,8 @@ pub unsafe fn __msa_div_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Divide /// -/// The unsigned integer elements in vector 'a' (four unsigned 32-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b' (four unsigned 32-bit integer numbers). +/// The unsigned integer elements in vector `a` (four unsigned 32-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (four unsigned 32-bit integer numbers). /// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] @@ -3678,8 +3681,8 @@ pub unsafe fn __msa_div_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Divide /// -/// The unsigned integer elements in vector 'a' (two unsigned 64-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b' (two unsigned 64-bit integer numbers). +/// The unsigned integer elements in vector `a` (two unsigned 64-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (two unsigned 64-bit integer numbers). /// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] @@ -3691,9 +3694,9 @@ pub unsafe fn __msa_div_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Signed Dot Product /// -/// The signed integer elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// are multiplied by signed integer elements in vector 'b' (sixteen signed 8-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The signed integer elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are multiplied by signed integer elements in vector `b` (sixteen signed 8-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (eight signed 16-bit integer numbers). /// @@ -3706,9 +3709,9 @@ pub unsafe fn __msa_dotp_s_h(a: v16i8, b: v16i8) -> v8i16 { /// Vector Signed Dot Product /// -/// The signed integer elements in vector 'a' (eight signed 16-bit integer numbers) -/// are multiplied by signed integer elements in vector 'b' (eight signed 16-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The signed integer elements in vector `a` (eight signed 16-bit integer numbers) +/// are multiplied by signed integer elements in vector `b` (eight signed 16-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (four signed 32-bit integer numbers). /// @@ -3721,9 +3724,9 @@ pub unsafe fn __msa_dotp_s_w(a: v8i16, b: v8i16) -> v4i32 { /// Vector Signed Dot Product /// -/// The signed integer elements in vector 'a' (four signed 32-bit integer numbers) -/// are multiplied by signed integer elements in vector 'b' (four signed 32-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The signed integer elements in vector `a` (four signed 32-bit integer numbers) +/// are multiplied by signed integer elements in vector `b` (four signed 32-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (two signed 64-bit integer numbers). /// @@ -3736,9 +3739,9 @@ pub unsafe fn __msa_dotp_s_d(a: v4i32, b: v4i32) -> v2i64 { /// Vector Unsigned Dot Product /// -/// The unsigned integer elements in vector 'a' (sixteen unsigned 8-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'b' (sixteen unsigned 8-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The unsigned integer elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (eight unsigned 16-bit integer numbers). /// @@ -3751,9 +3754,9 @@ pub unsafe fn __msa_dotp_u_h(a: v16u8, b: v16u8) -> v8u16 { /// Vector Unsigned Dot Product /// -/// The unsigned integer elements in vector 'a' (eight unsigned 16-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'b' (eight unsigned 16-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The unsigned integer elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `b` (eight unsigned 16-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (four unsigned 32-bit integer numbers). /// @@ -3766,9 +3769,9 @@ pub unsafe fn __msa_dotp_u_w(a: v8u16, b: v8u16) -> v4u32 { /// Vector Unsigned Dot Product /// -/// The unsigned integer elements in vector 'a' (four unsigned 32-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'b' (four unsigned 32-bit integer numbers). -/// producing a result the size of the input operands. The multiplication resultsof +/// The unsigned integer elements in vector `a` (four unsigned 32-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `b` (four unsigned 32-bit integer numbers) +/// producing a result the size of the input operands. The multiplication results of /// adjacent odd/even elements are added and stored to the destination /// vector (two unsigned 64-bit integer numbers). /// @@ -3781,10 +3784,10 @@ pub unsafe fn __msa_dotp_u_d(a: v4u32, b: v4u32) -> v2u64 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (sixteen signed 8-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (sixteen signed 8-bit integer numbers). +/// The signed integer elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (sixteen signed 8-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (eight signed 16-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3795,10 +3798,10 @@ pub unsafe fn __msa_dpadd_s_h(a: v8i16, b: v16i8, c: v16i8) -> v8i16 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (eight signed 16-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (eight signed 16-bit integer numbers). +/// The signed integer elements in vector `b` (eight signed 16-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (eight signed 16-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (four signed 32-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3809,10 +3812,10 @@ pub unsafe fn __msa_dpadd_s_w(a: v4i32, b: v8i16, c: v8i16) -> v4i32 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (four signed 32-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (four signed 32-bit integer numbers). +/// The signed integer elements in vector `b` (four signed 32-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (four signed 32-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (two signed 64-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3823,10 +3826,10 @@ pub unsafe fn __msa_dpadd_s_d(a: v2i64, b: v4i32, c: v4i32) -> v2i64 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (sixteen unsigned 8-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (sixteen unsigned 8-bit integer numbers). +/// The unsigned integer elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (sixteen unsigned 8-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (eight unsigned 16-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3837,10 +3840,10 @@ pub unsafe fn __msa_dpadd_u_h(a: v8u16, b: v16u8, c: v16u8) -> v8u16 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (eight unsigned 16-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (eight unsigned 16-bit integer numbers). +/// The unsigned integer elements in vector `b` (eight unsigned 16-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (eight unsigned 16-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (four unsigned 32-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3851,10 +3854,10 @@ pub unsafe fn __msa_dpadd_u_w(a: v4u32, b: v8u16, c: v8u16) -> v4u32 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (four unsigned 32-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (four unsigned 32-bit integer numbers). +/// The unsigned integer elements in vector `b` (four unsigned 32-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (four unsigned 32-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are added to the vector 'a' (two unsigned 64-bit integer numbers). +/// of adjacent odd/even elements are added to the vector `a` (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3865,10 +3868,10 @@ pub unsafe fn __msa_dpadd_u_d(a: v2u64, b: v4u32, c: v4u32) -> v2u64 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (sixteen signed 8-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (sixteen signed 8-bit integer numbers). +/// The signed integer elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (sixteen signed 8-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (eight signed 16-bit integer numbers). /// #[inline] @@ -3880,10 +3883,10 @@ pub unsafe fn __msa_dpsub_s_h(a: v8i16, b: v16i8, c: v16i8) -> v8i16 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (eight signed 16-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (eight signed 16-bit integer numbers). +/// The signed integer elements in vector `b` (eight signed 16-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (eight signed 16-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (four signed 32-bit integer numbers). /// #[inline] @@ -3895,10 +3898,10 @@ pub unsafe fn __msa_dpsub_s_w(a: v4i32, b: v8i16, c: v8i16) -> v4i32 { /// Vector Signed Dot Product and Add /// -/// The signed integer elements in vector 'b' (four signed 32-bit integer numbers) -/// are multiplied by signed integer elements in vector 'c' (four signed 32-bit integer numbers). +/// The signed integer elements in vector `b` (four signed 32-bit integer numbers) +/// are multiplied by signed integer elements in vector `c` (four signed 32-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (two signed 64-bit integer numbers). /// #[inline] @@ -3910,10 +3913,10 @@ pub unsafe fn __msa_dpsub_s_d(a: v2i64, b: v4i32, c: v4i32) -> v2i64 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (sixteen unsigned 8-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (sixteen unsigned 8-bit integer numbers). +/// The unsigned integer elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (sixteen unsigned 8-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (eight signed 16-bit integer numbers). /// #[inline] @@ -3925,10 +3928,10 @@ pub unsafe fn __msa_dpsub_u_h(a: v8i16, b: v16u8, c: v16u8) -> v8i16 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (eight unsigned 16-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (eight unsigned 16-bit integer numbers). +/// The unsigned integer elements in vector `b` (eight unsigned 16-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (eight unsigned 16-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (four signed 32-bit integer numbers). /// #[inline] @@ -3940,10 +3943,10 @@ pub unsafe fn __msa_dpsub_u_w(a: v4i32, b: v8u16, c: v8u16) -> v4i32 { /// Vector Unsigned Dot Product and Add /// -/// The unsigned integer elements in vector 'b' (four unsigned 32-bit integer numbers) -/// are multiplied by unsigned integer elements in vector 'c' (four unsigned 32-bit integer numbers). +/// The unsigned integer elements in vector `b` (four unsigned 32-bit integer numbers) +/// are multiplied by unsigned integer elements in vector `c` (four unsigned 32-bit integer numbers) /// producing a result twice the size of the input operands. The multiplication results -/// of adjacent odd/even elements are sub-tracted from the integer elements in vector 'a' +/// of adjacent odd/even elements are subtracted from the integer elements in vector `a` /// (two signed 64-bit integer numbers). /// #[inline] @@ -3955,9 +3958,9 @@ pub unsafe fn __msa_dpsub_u_d(a: v2i64, b: v4u32, c: v4u32) -> v2i64 { /// Vector Floating-Point Addition /// -/// The floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// are added to the floating-point elements in 'bc' (four 32-bit floating point numbers). -/// The result is written to vector (four 32-bit floating point numbers) +/// The floating-point elements in vector `a` (four 32-bit floating point numbers) +/// are added to the floating-point elements in `bc` (four 32-bit floating point numbers). +/// The result is written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3968,9 +3971,9 @@ pub unsafe fn __msa_fadd_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Addition /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// are added to the floating-point elements in 'bc' (two 64-bit floating point numbers). -/// The result is written to vector (two 64-bit floating point numbers) +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) +/// are added to the floating-point elements in `bc` (two 64-bit floating point numbers). +/// The result is written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -3981,9 +3984,9 @@ pub unsafe fn __msa_fadd_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Quiet Compare Always False /// -/// Set all bits to 0 in vector (four signed 32-bit integer numbers) -/// Signaling NaN elements in 'a' (four 32-bit floating point numbers) -/// or 'b' (four 32-bit floating point numbers)signal Invalid Operation exception. +/// Set all bits to 0 in vector (four signed 32-bit integer numbers). +/// Signaling NaN elements in `a` (four 32-bit floating point numbers) +/// or `b` (four 32-bit floating point numbers) signal Invalid Operation exception. /// #[inline] #[target_feature(enable = "msa")] @@ -3994,9 +3997,9 @@ pub unsafe fn __msa_fcaf_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Always False /// -/// Set all bits to 0 in vector (two signed 64-bit integer numbers) -/// Signaling NaN elements in 'a' (two 64-bit floating point numbers) -/// or 'b' (two 64-bit floating point numbers) signal Invalid Operation exception. +/// Set all bits to 0 in vector (two signed 64-bit integer numbers). +/// Signaling NaN elements in `a` (two 64-bit floating point numbers) +/// or `b` (two 64-bit floating point numbers) signal Invalid Operation exception. /// #[inline] #[target_feature(enable = "msa")] @@ -4008,8 +4011,8 @@ pub unsafe fn __msa_fcaf_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding in 'a' (four 32-bit floating point numbers) -/// and 'b' (four 32-bit floating point numbers)elements are ordered and equal, +/// elements if the corresponding in `a` (four 32-bit floating point numbers) +/// and `b` (four 32-bit floating point numbers) elements are ordered and equal, /// otherwise set all bits to 0. /// #[inline] @@ -4022,8 +4025,8 @@ pub unsafe fn __msa_fceq_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding in 'a' (two 64-bit floating point numbers) -/// and 'b' (two 64-bit floating point numbers) elementsare ordered and equal, +/// elements if the corresponding in `a` (two 64-bit floating point numbers) +/// and `b` (two 64-bit floating point numbers) elements are ordered and equal, /// otherwise set all bits to 0. /// #[inline] @@ -4037,10 +4040,10 @@ pub unsafe fn __msa_fceq_d(a: v2f64, b: v2f64) -> v2i64 { /// /// Store in each element of vector (four signed 32-bit integer numbers) /// a bit mask reflecting the floating-point class of the corresponding element of vector -/// 'a' (four 32-bit floating point numbers). +/// `a` (four 32-bit floating point numbers). /// The mask has 10 bits as follows. Bits 0 and 1 indicate NaN values: signaling NaN (bit 0) and quiet NaN (bit 1). -/// Bits 2, 3, 4, 5 classify negative values: infinity (bit 2), normal (bit 3), subnormal (bit 4), and zero (bit 5). -/// Bits 6, 7, 8, 9classify positive values:infinity (bit 6), normal (bit 7), subnormal (bit 8), and zero (bit 9). +/// Bits 2, 3, 4, 5 classify negative values: infinity (bit 2), normal (bit 3), subnormal (bit 4), and zero (bit 5). +/// Bits 6, 7, 8, 9 classify positive values: infinity (bit 6), normal (bit 7), subnormal (bit 8), and zero (bit 9). /// #[inline] #[target_feature(enable = "msa")] @@ -4051,12 +4054,12 @@ pub unsafe fn __msa_fclass_w(a: v4f32) -> v4i32 { /// Vector Floating-Point Class Mask /// -/// Store in each element of vector (wto signed 64-bit integer numbers) +/// Store in each element of vector (two signed 64-bit integer numbers) /// a bit mask reflecting the floating-point class of the corresponding element of vector -/// 'a' (wto 64-bit floating point numbers). +/// `a` (two 64-bit floating point numbers). /// The mask has 10 bits as follows. Bits 0 and 1 indicate NaN values: signaling NaN (bit 0) and quiet NaN (bit 1). -/// Bits 2, 3, 4, 5 classify negative values: infinity (bit 2), normal (bit 3), subnormal (bit 4), and zero (bit 5). -/// Bits 6, 7, 8, 9classify positive values:infinity (bit 6), normal (bit 7), subnormal (bit 8), and zero (bit 9). +/// Bits 2, 3, 4, 5 classify negative values: infinity (bit 2), normal (bit 3), subnormal (bit 4), and zero (bit 5). +/// Bits 6, 7, 8, 9 classify positive values: infinity (bit 6), normal (bit 7), subnormal (bit 8), and zero (bit 9). /// #[inline] #[target_feature(enable = "msa")] @@ -4068,8 +4071,8 @@ pub unsafe fn __msa_fclass_d(a: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Less or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers)elements are ordered -/// and either less than or equal to 'b' (four 32-bit floating point numbers)elements +/// elements if the corresponding `a` (four 32-bit floating point numbers) elements are ordered +/// and either less than or equal to `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4082,8 +4085,8 @@ pub unsafe fn __msa_fcle_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Less or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) elementsare ordered -/// and either less than or equal to 'b' (two 64-bit floating point numbers) elements +/// elements if the corresponding `a` (two 64-bit floating point numbers) elements are ordered +/// and either less than or equal to `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4096,8 +4099,8 @@ pub unsafe fn __msa_fcle_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers)elements are ordered -/// and less than 'b' (four 32-bit floating point numbers)elements +/// elements if the corresponding `a` (four 32-bit floating point numbers) elements are ordered +/// and less than `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4110,8 +4113,8 @@ pub unsafe fn __msa_fclt_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) elementsare ordered -/// and less than 'b' (two 64-bit floating point numbers) elements +/// elements if the corresponding `a` (two 64-bit floating point numbers) elements are ordered +/// and less than `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4124,8 +4127,8 @@ pub unsafe fn __msa_fclt_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Not Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are ordered and not equal +/// elements if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are ordered and not equal, /// otherwise set all bits to 0. /// #[inline] @@ -4138,8 +4141,8 @@ pub unsafe fn __msa_fcne_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Not Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare ordered and not equal +/// elements if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are ordered and not equal, /// otherwise set all bits to 0. /// #[inline] @@ -4152,8 +4155,8 @@ pub unsafe fn __msa_fcne_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Ordered /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are ordered, i.e. both elementsare not NaN values, +/// elements if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are ordered, i.e. both elements are not NaN values, /// otherwise set all bits to 0. /// #[inline] @@ -4166,8 +4169,8 @@ pub unsafe fn __msa_fcor_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Ordered /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare ordered, i.e. both elementsare not NaN values, +/// elements if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are ordered, i.e. both elements are not NaN values, /// otherwise set all bits to 0. /// #[inline] @@ -4180,8 +4183,8 @@ pub unsafe fn __msa_fcor_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Unordered or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are unordered or equal, +/// elements if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are unordered or equal, /// otherwise set all bits to 0. /// #[inline] @@ -4194,8 +4197,8 @@ pub unsafe fn __msa_fcueq_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Unordered or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare unordered or equal, +/// elements if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are unordered or equal, /// otherwise set all bits to 0. /// #[inline] @@ -4208,8 +4211,8 @@ pub unsafe fn __msa_fcueq_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Unordered or Less or Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding elements in 'a' (four 32-bit floating point numbers) -/// are unordered or less than or equal to 'b' (four 32-bit floating point numbers)elements, +/// elements if the corresponding elements in `a` (four 32-bit floating point numbers) +/// are unordered or less than or equal to `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4222,8 +4225,8 @@ pub unsafe fn __msa_fcule_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Unordered or Less or Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding elements in 'a' (two 64-bit floating point numbers) -/// are unordered or less than or equal to 'b' (two 64-bit floating point numbers) elements, +/// elements if the corresponding elements in `a` (two 64-bit floating point numbers) +/// are unordered or less than or equal to `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4236,8 +4239,8 @@ pub unsafe fn __msa_fcule_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Unordered or Less Than /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding elements in 'a' (four 32-bit floating point numbers) -/// are unordered or less than 'b' (four 32-bit floating point numbers)elements, +/// elements if the corresponding elements in `a` (four 32-bit floating point numbers) +/// are unordered or less than `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4250,8 +4253,8 @@ pub unsafe fn __msa_fcult_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Unordered or Less Than /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding elements in 'a' (two 64-bit floating point numbers) -/// are unordered or less than 'b' (two 64-bit floating point numbers) elements, +/// elements if the corresponding elements in `a` (two 64-bit floating point numbers) +/// are unordered or less than `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -4264,9 +4267,9 @@ pub unsafe fn __msa_fcult_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Unordered /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers) -/// and 'b' (four 32-bit floating point numbers)elements are unordered, -/// i.e. at least oneelement is a NaN value, otherwise set all bits to 0. +/// elements if the corresponding `a` (four 32-bit floating point numbers) +/// and `b` (four 32-bit floating point numbers) elements are unordered, +/// i.e. at least one element is a NaN value, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4278,9 +4281,9 @@ pub unsafe fn __msa_fcun_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Unordered /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) -/// and 'b' (two 64-bit floating point numbers) elementsare unordered, -/// i.e. at least oneelement is a NaN value, otherwise set all bits to 0. +/// elements if the corresponding `a` (two 64-bit floating point numbers) +/// and `b` (two 64-bit floating point numbers) elements are unordered, +/// i.e. at least one element is a NaN value, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4292,8 +4295,8 @@ pub unsafe fn __msa_fcun_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Quiet Compare Unordered or Not Equal /// /// Set all bits to 1 in vector (four signed 32-bit integer numbers) -/// elements if the corresponding 'a' (four 32-bit floating point numbers) -/// and 'b' (four 32-bit floating point numbers)elements are unordered or not equal, +/// elements if the corresponding `a` (four 32-bit floating point numbers) +/// and `b` (four 32-bit floating point numbers) elements are unordered or not equal, /// otherwise set all bits to 0. /// #[inline] @@ -4306,8 +4309,8 @@ pub unsafe fn __msa_fcune_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Quiet Compare Unordered or Not Equal /// /// Set all bits to 1 in vector (two signed 64-bit integer numbers) -/// elements if the corresponding 'a' (two 64-bit floating point numbers) -/// and 'b' (two 64-bit floating point numbers) elementsare unordered or not equal, +/// elements if the corresponding `a` (two 64-bit floating point numbers) +/// and `b` (two 64-bit floating point numbers) elements are unordered or not equal, /// otherwise set all bits to 0. /// #[inline] @@ -4319,8 +4322,8 @@ pub unsafe fn __msa_fcune_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Division /// -/// The floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// are divided by the floating-point elements in vector 'b' (four 32-bit floating point numbers) +/// The floating-point elements in vector `a` (four 32-bit floating point numbers) +/// are divided by the floating-point elements in vector `b` (four 32-bit floating point numbers). /// The result is written to vector (four 32-bit floating point numbers). /// #[inline] @@ -4332,8 +4335,8 @@ pub unsafe fn __msa_fdiv_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Division /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// are divided by the floating-point elements in vector 'b' (two 64-bit floating point numbers) +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) +/// are divided by the floating-point elements in vector `b` (two 64-bit floating point numbers). /// The result is written to vector (two 64-bit floating point numbers). /// #[inline] @@ -4346,9 +4349,9 @@ pub unsafe fn __msa_fdiv_d(a: v2f64, b: v2f64) -> v2f64 { /* FIXME: 16-bit float /// Vector Floating-Point Down-Convert Interchange Format /// -/// The floating-point elements in vector 'a' (four 64-bit floating point numbers) -/// and vector 'b' (four 64-bit floating point numbers) are down-converted -/// to a smaller interchange format, i.e. from 64-bitto 32-bit, or from 32-bit to 16-bit. +/// The floating-point elements in vector `a` (four 64-bit floating point numbers) +/// and vector `b` (four 64-bit floating point numbers) are down-converted +/// to a smaller interchange format, i.e. from 64-bit to 32-bit, or from 32-bit to 16-bit. /// The result is written to vector (8 16-bit floating point numbers). /// #[inline] @@ -4360,9 +4363,9 @@ pub unsafe fn __msa_fexdo_h(a: v4f32, b: v4f32) -> f16x8 { /// Vector Floating-Point Down-Convert Interchange Format /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// and vector 'b' (two 64-bit floating point numbers) are down-converted -/// to a smaller interchange format, i.e. from 64-bitto 32-bit, or from 32-bit to 16-bit. +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) +/// and vector `b` (two 64-bit floating point numbers) are down-converted +/// to a smaller interchange format, i.e. from 64-bit to 32-bit, or from 32-bit to 16-bit. /// The result is written to vector (four 32-bit floating point numbers). /// #[inline] @@ -4374,8 +4377,8 @@ pub unsafe fn __msa_fexdo_w(a: v2f64, b: v2f64) -> v4f32 { /// Vector Floating-Point Down-Convert Interchange Format /// -/// The floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// are scaled, i.e. multiplied, by 2 to the power of integer elements in vector 'b' +/// The floating-point elements in vector `a` (four 32-bit floating point numbers) +/// are scaled, i.e. multiplied, by 2 to the power of integer elements in vector `b` /// (four signed 32-bit integer numbers). /// The result is written to vector (four 32-bit floating point numbers). /// @@ -4388,8 +4391,8 @@ pub unsafe fn __msa_fexp2_w(a: v4f32, b: v4i32) -> v4f32 { /// Vector Floating-Point Down-Convert Interchange Format /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// are scaled, i.e. multiplied, by 2 to the power of integer elements in vector 'b' +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) +/// are scaled, i.e. multiplied, by 2 to the power of integer elements in vector `b` /// (two signed 64-bit integer numbers). /// The result is written to vector (two 64-bit floating point numbers). /// @@ -4403,7 +4406,7 @@ pub unsafe fn __msa_fexp2_d(a: v2f64, b: v2i64) -> v2f64 { /* FIXME: 16-bit float /// Vector Floating-Point Up-Convert Interchange Format Left /// -/// The left half floating-point elements in vector 'a' (two 16-bit floating point numbers) +/// The left half floating-point elements in vector `a` (two 16-bit floating point numbers) /// are up-converted to a larger interchange format, /// i.e. from 16-bit to 32-bit, or from 32-bit to 64-bit. /// The result is written to vector (four 32-bit floating point numbers). @@ -4417,7 +4420,7 @@ pub unsafe fn __msa_fexupl_w(a: f16x8) -> v4f32 { /// Vector Floating-Point Up-Convert Interchange Format Left /// -/// The left half floating-point elements in vector 'a' (four 32-bit floating point numbers) +/// The left half floating-point elements in vector `a` (four 32-bit floating point numbers) /// are up-converted to a larger interchange format, /// i.e. from 16-bit to 32-bit, or from 32-bit to 64-bit. /// The result is written to vector (two 64-bit floating point numbers). @@ -4432,7 +4435,7 @@ pub unsafe fn __msa_fexupl_d(a: v4f32) -> v2f64 { /* FIXME: 16-bit float /// Vector Floating-Point Up-Convert Interchange Format Left /// -/// The right half floating-point elements in vector 'a' (two 16-bit floating point numbers) +/// The right half floating-point elements in vector `a` (two 16-bit floating point numbers) /// are up-converted to a larger interchange format, /// i.e. from 16-bit to 32-bit, or from 32-bit to 64-bit. /// The result is written to vector (four 32-bit floating point numbers). @@ -4446,7 +4449,7 @@ pub unsafe fn __msa_fexupr_w(a: f16x8) -> v4f32 { /// Vector Floating-Point Up-Convert Interchange Format Left /// -/// The right half floating-point elements in vector 'a' (four 32-bit floating point numbers) +/// The right half floating-point elements in vector `a` (four 32-bit floating point numbers) /// are up-converted to a larger interchange format, /// i.e. from 16-bit to 32-bit, or from 32-bit to 64-bit. /// The result is written to vector (two 64-bit floating point numbers). @@ -4460,7 +4463,7 @@ pub unsafe fn __msa_fexupr_d(a: v4f32) -> v2f64 { /// Vector Floating-Point Round and Convert from Signed Integer /// -/// The signed integer elements in vector 'a' (four signed 32-bit integer numbers) +/// The signed integer elements in vector `a` (four signed 32-bit integer numbers) /// are converted to floating-point values. /// The result is written to vector (four 32-bit floating point numbers). /// @@ -4473,7 +4476,7 @@ pub unsafe fn __msa_ffint_s_w(a: v4i32) -> v4f32 { /// Vector Floating-Point Round and Convert from Signed Integer /// -/// The signed integer elements in vector 'a' (two signed 64-bit integer numbers) +/// The signed integer elements in vector `a` (two signed 64-bit integer numbers) /// are converted to floating-point values. /// The result is written to vector (two 64-bit floating point numbers). /// @@ -4486,7 +4489,7 @@ pub unsafe fn __msa_ffint_s_d(a: v2i64) -> v2f64 { /// Vector Floating-Point Round and Convert from Unsigned Integer /// -/// The unsigned integer elements in vector 'a' (four unsigned 32-bit integer numbers) +/// The unsigned integer elements in vector `a` (four unsigned 32-bit integer numbers) /// are converted to floating-point values. /// The result is written to vector (four 32-bit floating point numbers). /// @@ -4499,7 +4502,7 @@ pub unsafe fn __msa_ffint_u_w(a: v4u32) -> v4f32 { /// Vector Floating-Point Round and Convert from Unsigned Integer /// -/// The unsigned integer elements in vector 'a' (two unsigned 64-bit integer numbers) +/// The unsigned integer elements in vector `a` (two unsigned 64-bit integer numbers) /// are converted to floating-point values. /// The result is written to vector (two 64-bit floating point numbers). /// @@ -4512,7 +4515,7 @@ pub unsafe fn __msa_ffint_u_d(a: v2u64) -> v2f64 { /// Vector Floating-Point Convert from Fixed-Point Left /// -/// The left half fixed-point elements in vector 'a' (eight signed 16-bit integer numbers) +/// The left half fixed-point elements in vector `a` (eight signed 16-bit integer numbers) /// are up-converted to floating-point data format. /// i.e. from 16-bit Q15 to 32-bit floating-point, or from 32-bit Q31 to 64-bit floating-point. /// The result is written to vector (four 32-bit floating point numbers). @@ -4526,7 +4529,7 @@ pub unsafe fn __msa_ffql_w(a: v8i16) -> v4f32 { /// Vector Floating-Point Convert from Fixed-Point Left /// -/// The left half fixed-point elements in vector 'a' (four signed 32-bit integer numbers) +/// The left half fixed-point elements in vector `a` (four signed 32-bit integer numbers) /// are up-converted to floating-point data format. /// i.e. from 16-bit Q15 to 32-bit floating-point, or from 32-bit Q31 to 64-bit floating-point. /// The result is written to vector (two 64-bit floating point numbers). @@ -4540,7 +4543,7 @@ pub unsafe fn __msa_ffql_d(a: v4i32) -> v2f64 { /// Vector Floating-Point Convert from Fixed-Point Left /// -/// The right half fixed-point elements in vector 'a' (eight signed 16-bit integer numbers) +/// The right half fixed-point elements in vector `a` (eight signed 16-bit integer numbers) /// are up-converted to floating-point data format. /// i.e. from 16-bit Q15 to 32-bit floating-point, or from 32-bit Q31 to 64-bit floating-point. /// The result is written to vector (four 32-bit floating point numbers). @@ -4554,7 +4557,7 @@ pub unsafe fn __msa_ffqr_w(a: v8i16) -> v4f32 { /// Vector Floating-Point Convert from Fixed-Point Left /// -/// The right half fixed-point elements in vector 'a' (four signed 32-bit integer numbers) +/// The right half fixed-point elements in vector `a` (four signed 32-bit integer numbers) /// are up-converted to floating-point data format. /// i.e. from 16-bit Q15 to 32-bit floating-point, or from 32-bit Q31 to 64-bit floating-point. /// The result is written to vector (two 64-bit floating point numbers). @@ -4570,7 +4573,7 @@ pub unsafe fn __msa_ffqr_d(a: v4i32) -> v2f64 { /// /// Replicate GPR rs value to all elements in vector (sixteen signed 8-bit integer numbers). /// If the source GPR is wider than the destination data format, the destination's elements -/// will be set to the least significant bits of the GPR +/// will be set to the least significant bits of the GPR. /// #[inline] #[target_feature(enable = "msa")] @@ -4583,7 +4586,7 @@ pub unsafe fn __msa_fill_b(a: i32) -> v16i8 { /// /// Replicate GPR rs value to all elements in vector (eight signed 16-bit integer numbers). /// If the source GPR is wider than the destination data format, the destination's elements -/// will be set to the least significant bits of the GPR +/// will be set to the least significant bits of the GPR. /// #[inline] #[target_feature(enable = "msa")] @@ -4596,7 +4599,7 @@ pub unsafe fn __msa_fill_h(a: i32) -> v8i16 { /// /// Replicate GPR rs value to all elements in vector (four signed 32-bit integer numbers). /// If the source GPR is wider than the destination data format, the destination's elements -/// will be set to the least significant bits of the GPR +/// will be set to the least significant bits of the GPR. /// #[inline] #[target_feature(enable = "msa")] @@ -4609,7 +4612,7 @@ pub unsafe fn __msa_fill_w(a: i32) -> v4i32 { /// /// Replicate GPR rs value to all elements in vector (two signed 64-bit integer numbers). /// If the source GPR is wider than the destination data format, the destination's elements -/// will be set to the least significant bits of the GPR +/// will be set to the least significant bits of the GPR. /// #[inline] #[target_feature(enable = "msa")] @@ -4620,8 +4623,8 @@ pub unsafe fn __msa_fill_d(a: i64) -> v2i64 { /// Vector Floating-Point Base 2 Logarithm /// -/// The signed integral base 2 exponents of floating-point elements in vector 'a' -/// (four 32-bit floating point numbers)are written as floating-point values to vector elements +/// The signed integral base 2 exponents of floating-point elements in vector `a` +/// (four 32-bit floating point numbers) are written as floating-point values to vector elements /// (four 32-bit floating point numbers). /// #[inline] @@ -4633,7 +4636,7 @@ pub unsafe fn __msa_flog2_w(a: v4f32) -> v4f32 { /// Vector Floating-Point Base 2 Logarithm /// -/// The signed integral base 2 exponents of floating-point elements in vector 'a' +/// The signed integral base 2 exponents of floating-point elements in vector `a` /// (two 64-bit floating point numbers) are written as floating-point values to vector elements /// (two 64-bit floating point numbers). /// @@ -4646,9 +4649,9 @@ pub unsafe fn __msa_flog2_d(a: v2f64) -> v2f64 { /// Vector Floating-Point Multiply-Add /// -/// The floating-point elements in vector 'b' (four 32-bit floating point numbers) -/// multiplied by floating-point elements in vector 'c' (four 32-bit floating point numbers) -/// are added to the floating-point elements in vector 'a' (four 32-bit floating point numbers) +/// The floating-point elements in vector `b` (four 32-bit floating point numbers) +/// multiplied by floating-point elements in vector `c` (four 32-bit floating point numbers) +/// are added to the floating-point elements in vector `a` (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4659,9 +4662,9 @@ pub unsafe fn __msa_fmadd_w(a: v4f32, b: v4f32, c: v4f32) -> v4f32 { /// Vector Floating-Point Multiply-Add /// -/// The floating-point elements in vector 'b' (two 64-bit floating point numbers) -/// multiplied by floating-point elements in vector 'c' (two 64-bit floating point numbers) -/// are added to the floating-point elements in vector 'a' (two 64-bit floating point numbers) +/// The floating-point elements in vector `b` (two 64-bit floating point numbers) +/// multiplied by floating-point elements in vector `c` (two 64-bit floating point numbers) +/// are added to the floating-point elements in vector `a` (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4672,9 +4675,9 @@ pub unsafe fn __msa_fmadd_d(a: v2f64, b: v2f64, c: v2f64) -> v2f64 { /// Vector Floating-Point Maximum /// -/// The largest values between corresponding floating-point elements in vector 'a' -/// (four 32-bit floating point numbers)andvector 'b' (four 32-bit floating point numbers) -/// are written to vector (four 32-bit floating point numbers) +/// The largest values between corresponding floating-point elements in vector `a` +/// (four 32-bit floating point numbers) and vector `b` (four 32-bit floating point numbers) +/// are written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4685,9 +4688,9 @@ pub unsafe fn __msa_fmax_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Maximum /// -/// The largest values between corresponding floating-point elements in vector 'a' -/// (two 64-bit floating point numbers) and vector 'b' (two 64-bit floating point numbers) -/// are written to vector (two 64-bit floating point numbers) +/// The largest values between corresponding floating-point elements in vector `a` +/// (two 64-bit floating point numbers) and vector `b` (two 64-bit floating point numbers) +/// are written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4699,9 +4702,9 @@ pub unsafe fn __msa_fmax_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// and vector 'b' (four 32-bit floating point numbers) -/// are written to vector (four 32-bit floating point numbers) +/// floating-point elements in vector `a` (four 32-bit floating point numbers) +/// and vector `b` (four 32-bit floating point numbers) +/// are written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4713,9 +4716,9 @@ pub unsafe fn __msa_fmax_a_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// and vector 'b' (two 64-bit floating point numbers) -/// are written to vector (two 64-bit floating point numbers) +/// floating-point elements in vector `a` (two 64-bit floating point numbers) +/// and vector `b` (two 64-bit floating point numbers) +/// are written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4726,9 +4729,9 @@ pub unsafe fn __msa_fmax_a_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Minimum /// -/// The smallest values between corresponding floating-point elements in vector 'a' -/// (four 32-bit floating point numbers)andvector 'b' (four 32-bit floating point numbers) -/// are written to vector (four 32-bit floating point numbers) +/// The smallest values between corresponding floating-point elements in vector `a` +/// (four 32-bit floating point numbers) and vector `b` (four 32-bit floating point numbers) +/// are written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4739,9 +4742,9 @@ pub unsafe fn __msa_fmin_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Minimum /// -/// The smallest values between corresponding floating-point elements in vector 'a' -/// (two 64-bit floating point numbers) and vector 'b' (two 64-bit floating point numbers) -/// are written to vector (two 64-bit floating point numbers) +/// The smallest values between corresponding floating-point elements in vector `a` +/// (two 64-bit floating point numbers) and vector `b` (two 64-bit floating point numbers) +/// are written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4753,9 +4756,9 @@ pub unsafe fn __msa_fmin_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Minimum Based on Absolute Values /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// and vector 'b' (four 32-bit floating point numbers) -/// are written to vector (four 32-bit floating point numbers) +/// floating-point elements in vector `a` (four 32-bit floating point numbers) +/// and vector `b` (four 32-bit floating point numbers) +/// are written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4767,9 +4770,9 @@ pub unsafe fn __msa_fmin_a_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Minimum Based on Absolute Values /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// and vector 'b' (two 64-bit floating point numbers) -/// are written to vector (two 64-bit floating point numbers) +/// floating-point elements in vector `a` (two 64-bit floating point numbers) +/// and vector `b` (two 64-bit floating point numbers) +/// are written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4780,9 +4783,9 @@ pub unsafe fn __msa_fmin_a_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Multiply-Sub /// -/// The floating-point elements in vector 'b' (four 32-bit floating point numbers) -/// multiplied by floating-point elements in vector 'c' (four 32-bit floating point numbers) -/// are subtracted from the floating-point elements in vector 'a' (four 32-bit floating point numbers) +/// The floating-point elements in vector `b` (four 32-bit floating point numbers) +/// multiplied by floating-point elements in vector `c` (four 32-bit floating point numbers) +/// are subtracted from the floating-point elements in vector `a` (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4793,9 +4796,9 @@ pub unsafe fn __msa_fmsub_w(a: v4f32, b: v4f32, c: v4f32) -> v4f32 { /// Vector Floating-Point Multiply-Sub /// -/// The floating-point elements in vector 'b' (two 64-bit floating point numbers) -/// multiplied by floating-point elements in vector 'c' (two 64-bit floating point numbers) -/// are subtracted from the floating-point elements in vector 'a' (two 64-bit floating point numbers) +/// The floating-point elements in vector `b` (two 64-bit floating point numbers) +/// multiplied by floating-point elements in vector `c` (two 64-bit floating point numbers) +/// are subtracted from the floating-point elements in vector `a` (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4806,8 +4809,8 @@ pub unsafe fn __msa_fmsub_d(a: v2f64, b: v2f64, c: v2f64) -> v2f64 { /// Vector Floating-Point Multiplication /// -/// The floating-point elements in vector 'a' (four 32-bit floating point numbers)are -/// multiplied by floating-point elements in vector 'b' (four 32-bit floating point numbers) +/// The floating-point elements in vector `a` (four 32-bit floating point numbers) are +/// multiplied by floating-point elements in vector `b` (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4818,8 +4821,8 @@ pub unsafe fn __msa_fmul_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Multiplication /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) are -/// multiplied by floating-point elements in vector 'b' (two 64-bit floating point numbers) +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) are +/// multiplied by floating-point elements in vector `b` (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4830,9 +4833,9 @@ pub unsafe fn __msa_fmul_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Round to Integer /// -/// The floating-point elements in vector 'a' (four 32-bit floating point numbers) +/// The floating-point elements in vector `a` (four 32-bit floating point numbers) /// are rounded to an integral valued floating-point number in the same format based -/// on the rounding mode bits RM in MSA Control and Status Register MSACSR. +/// on the rounding mode bits RM in MSA Control and Status Register MSACSR. /// #[inline] #[target_feature(enable = "msa")] @@ -4843,9 +4846,9 @@ pub unsafe fn __msa_frint_w(a: v4f32) -> v4f32 { /// Vector Floating-Point Round to Integer /// -/// The floating-point elements in vector 'a' (two 64-bit floating point numbers) +/// The floating-point elements in vector `a` (two 64-bit floating point numbers) /// are rounded to an integral valued floating-point number in the same format based -/// on the rounding mode bits RM in MSA Control and Status Register MSACSR. +/// on the rounding mode bits RM in MSA Control and Status Register MSACSR. /// #[inline] #[target_feature(enable = "msa")] @@ -4854,10 +4857,10 @@ pub unsafe fn __msa_frint_d(a: v2f64) -> v2f64 { msa_frint_d(a) } -/// Vector Approximate Floating-Point Reciprocal +/// Vector Approximate Floating-Point Reciprocal /// -/// The reciprocals of floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// are calculated and the result is written to vector (four 32-bit floating point numbers) +/// The reciprocals of floating-point elements in vector `a` (four 32-bit floating point numbers) +/// are calculated and the result is written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4866,10 +4869,10 @@ pub unsafe fn __msa_frcp_w(a: v4f32) -> v4f32 { msa_frcp_w(a) } -/// Vector Approximate Floating-Point Reciprocal +/// Vector Approximate Floating-Point Reciprocal /// -/// The reciprocals of floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// are calculated and the result is written to vector (two 64-bit floating point numbers) +/// The reciprocals of floating-point elements in vector `a` (two 64-bit floating point numbers) +/// are calculated and the result is written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4880,8 +4883,8 @@ pub unsafe fn __msa_frcp_d(a: v2f64) -> v2f64 { /// Vector Approximate Floating-Point Reciprocal of Square Root /// -/// The reciprocals of the square roots of floating-point elements in vector 'a' (four 32-bit floating point numbers) -/// are calculated and the result is written to vector (four 32-bit floating point numbers) +/// The reciprocals of the square roots of floating-point elements in vector `a` (four 32-bit floating point numbers) +/// are calculated and the result is written to vector (four 32-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4892,8 +4895,8 @@ pub unsafe fn __msa_frsqrt_w(a: v4f32) -> v4f32 { /// Vector Approximate Floating-Point Reciprocal of Square Root /// -/// The reciprocals of the square roots of floating-point elements in vector 'a' (two 64-bit floating point numbers) -/// are calculated and the result is written to vector (two 64-bit floating point numbers) +/// The reciprocals of the square roots of floating-point elements in vector `a` (two 64-bit floating point numbers) +/// are calculated and the result is written to vector (two 64-bit floating point numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -4904,10 +4907,10 @@ pub unsafe fn __msa_frsqrt_d(a: v2f64) -> v2f64 { /// Vector Floating-Point Signaling Compare Always False /// -/// Set all bits to 0 in vector (four signed 32-bit integer numbers) elements. -/// Signaling and quiet NaN elements in vector 'a' (four 32-bit floating point numbers) -/// or 'b' (four 32-bit floating point numbers)signal Invalid Operation exception. -/// In case of a floating-point exception, the default result has all bits set to 0 +/// Set all bits to 0 in vector (four signed 32-bit integer numbers) elements. +/// Signaling and quiet NaN elements in vector `a` (four 32-bit floating point numbers) +/// or `b` (four 32-bit floating point numbers) signal Invalid Operation exception. +/// In case of a floating-point exception, the default result has all bits set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4918,10 +4921,10 @@ pub unsafe fn __msa_fsaf_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Always False /// -/// Set all bits to 0 in vector (two signed 64-bit integer numbers) elements. -/// Signaling and quiet NaN elements in vector 'a' (two 64-bit floating point numbers) -/// or 'b' (two 64-bit floating point numbers) signal Invalid Operation exception. -/// In case of a floating-point exception, the default result has all bits set to 0 +/// Set all bits to 0 in vector (two signed 64-bit integer numbers) elements. +/// Signaling and quiet NaN elements in vector `a` (two 64-bit floating point numbers) +/// or `b` (two 64-bit floating point numbers) signal Invalid Operation exception. +/// In case of a floating-point exception, the default result has all bits set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4932,9 +4935,9 @@ pub unsafe fn __msa_fsaf_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Equal /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers) -/// and 'b' (four 32-bit floating point numbers)elements are equal, otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) +/// and `b` (four 32-bit floating point numbers) elements are equal, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4945,9 +4948,9 @@ pub unsafe fn __msa_fseq_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Equal /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) -/// and 'b' (two 64-bit floating point numbers) elementsare equal, otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) +/// and `b` (two 64-bit floating point numbers) elements are equal, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4958,9 +4961,9 @@ pub unsafe fn __msa_fseq_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Less or Equal /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)elements -/// are less than or equal to 'b' (four 32-bit floating point numbers)elements, otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) elements +/// are less than or equal to `b` (four 32-bit floating point numbers) elements, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4971,9 +4974,9 @@ pub unsafe fn __msa_fsle_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Less or Equal /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) elements -/// are less than or equal to 'b' (two 64-bit floating point numbers) elements, otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) elements +/// are less than or equal to `b` (two 64-bit floating point numbers) elements, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4984,9 +4987,9 @@ pub unsafe fn __msa_fsle_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Less Than /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)elements -/// are less than 'b' (four 32-bit floating point numbers)elements, otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) elements +/// are less than `b` (four 32-bit floating point numbers) elements, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -4997,9 +5000,9 @@ pub unsafe fn __msa_fslt_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Less Than /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) elements -/// are less than 'b' (two 64-bit floating point numbers) elements, otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) elements +/// are less than `b` (two 64-bit floating point numbers) elements, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5010,9 +5013,9 @@ pub unsafe fn __msa_fslt_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Not Equal /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are not equal, otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are not equal, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5023,9 +5026,9 @@ pub unsafe fn __msa_fsne_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Not Equal /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare not equal, otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are not equal, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5036,10 +5039,10 @@ pub unsafe fn __msa_fsne_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Ordered /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are ordered, -/// i.e. both elementsare not NaN values, otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are ordered, +/// i.e. both elements are not NaN values, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5050,10 +5053,10 @@ pub unsafe fn __msa_fsor_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Ordered /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare ordered, -/// i.e. both elementsare not NaN values, otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are ordered, +/// i.e. both elements are not NaN values, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5062,11 +5065,11 @@ pub unsafe fn __msa_fsor_d(a: v2f64, b: v2f64) -> v2i64 { msa_fsor_d(a, mem::transmute(b)) } -/// Vector Floating-Point Square Root +/// Vector Floating-Point Square Root /// -/// The square roots of floating-point elements in vector 'a' -/// (four 32-bit floating point numbers)are written to vector -/// (four 32-bit floating point numbers)elements are ordered, +/// The square roots of floating-point elements in vector `a` +/// (four 32-bit floating point numbers) are written to vector +/// (four 32-bit floating point numbers) elements are ordered,. /// #[inline] #[target_feature(enable = "msa")] @@ -5075,11 +5078,11 @@ pub unsafe fn __msa_fsqrt_w(a: v4f32) -> v4f32 { msa_fsqrt_w(a) } -/// Vector Floating-Point Square Root +/// Vector Floating-Point Square Root /// -/// The square roots of floating-point elements in vector 'a' +/// The square roots of floating-point elements in vector `a` /// (two 64-bit floating point numbers) are written to vector -/// (two 64-bit floating point numbers) elementsare ordered, +/// (two 64-bit floating point numbers) elements are ordered,. /// #[inline] #[target_feature(enable = "msa")] @@ -5090,8 +5093,8 @@ pub unsafe fn __msa_fsqrt_d(a: v2f64) -> v2f64 { /// Vector Floating-Point Subtraction /// -/// The floating-point elements in vector 'b' (four 32-bit floating point numbers) -/// are subtracted from the floating-point elements in vector 'a' +/// The floating-point elements in vector `b` (four 32-bit floating point numbers) +/// are subtracted from the floating-point elements in vector `a` /// (four 32-bit floating point numbers). /// The result is written to vector (four 32-bit floating point numbers). /// @@ -5104,8 +5107,8 @@ pub unsafe fn __msa_fsub_w(a: v4f32, b: v4f32) -> v4f32 { /// Vector Floating-Point Subtraction /// -/// The floating-point elements in vector 'b' (two 64-bit floating point numbers) -/// are subtracted from the floating-point elements in vector 'a' +/// The floating-point elements in vector `b` (two 64-bit floating point numbers) +/// are subtracted from the floating-point elements in vector `a` /// (two 64-bit floating point numbers). /// The result is written to vector (two 64-bit floating point numbers). /// @@ -5118,9 +5121,9 @@ pub unsafe fn __msa_fsub_d(a: v2f64, b: v2f64) -> v2f64 { /// Vector Floating-Point Signaling Compare Ordered /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are unordered or equal, +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are unordered or equal, /// otherwise set all bits to 0. /// #[inline] @@ -5132,9 +5135,9 @@ pub unsafe fn __msa_fsueq_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Ordered /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare unordered or equal, +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are unordered or equal, /// otherwise set all bits to 0. /// #[inline] @@ -5146,9 +5149,9 @@ pub unsafe fn __msa_fsueq_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Unordered or Less or Equal /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)elements are -/// unordered or less than or equal to 'b' (four 32-bit floating point numbers)elements +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) elements are +/// unordered or less than or equal to `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -5160,9 +5163,9 @@ pub unsafe fn __msa_fsule_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Unordered or Less or Equal /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) elementsare -/// unordered or less than or equal to 'b' (two 64-bit floating point numbers) elements +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) elements are +/// unordered or less than or equal to `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -5174,9 +5177,9 @@ pub unsafe fn __msa_fsule_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Unordered or Less Than /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)elements -/// are unordered or less than 'b' (four 32-bit floating point numbers)elements +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) elements +/// are unordered or less than `b` (four 32-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -5188,9 +5191,9 @@ pub unsafe fn __msa_fsult_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Unordered or Less Than /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) elements -/// are unordered or less than 'b' (two 64-bit floating point numbers) elements +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) elements +/// are unordered or less than `b` (two 64-bit floating point numbers) elements, /// otherwise set all bits to 0. /// #[inline] @@ -5202,10 +5205,10 @@ pub unsafe fn __msa_fsult_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Unordered /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are unordered, -/// i.e. at least one element is a NaN value otherwise set all bits to 0. +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are unordered, +/// i.e. at least one element is a NaN value, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5216,10 +5219,10 @@ pub unsafe fn __msa_fsun_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Unordered /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare unordered, -/// i.e. at least one element is a NaN value otherwise set all bits to 0. +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are unordered, +/// i.e. at least one element is a NaN value, otherwise set all bits to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -5230,9 +5233,9 @@ pub unsafe fn __msa_fsun_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Signaling Compare Unordered or Not Equal /// -/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements -/// if the corresponding 'a' (four 32-bit floating point numbers)and -/// 'b' (four 32-bit floating point numbers)elements are unordered or not equal, +/// Set all bits to 1 in vector (four signed 32-bit integer numbers) elements +/// if the corresponding `a` (four 32-bit floating point numbers) and +/// `b` (four 32-bit floating point numbers) elements are unordered or not equal, /// otherwise set all bits to 0. /// #[inline] @@ -5244,9 +5247,9 @@ pub unsafe fn __msa_fsune_w(a: v4f32, b: v4f32) -> v4i32 { /// Vector Floating-Point Signaling Compare Unordered or Not Equal /// -/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements -/// if the corresponding 'a' (two 64-bit floating point numbers) and -/// 'b' (two 64-bit floating point numbers) elementsare unordered or not equal, +/// Set all bits to 1 in vector (two signed 64-bit integer numbers) elements +/// if the corresponding `a` (two 64-bit floating point numbers) and +/// `b` (two 64-bit floating point numbers) elements are unordered or not equal, /// otherwise set all bits to 0. /// #[inline] @@ -5258,7 +5261,7 @@ pub unsafe fn __msa_fsune_d(a: v2f64, b: v2f64) -> v2i64 { /// Vector Floating-Point Convert to Signed Integer /// -///The elements in vector 'a' (four 32-bit floating point numbers) +///The elements in vector `a` (four 32-bit floating point numbers) /// are rounded and converted to signed integer values based on the /// rounding mode bits RM in MSA Control and Status Register MSACSR. /// The result is written to vector (four signed 32-bit integer numbers). @@ -5272,7 +5275,7 @@ pub unsafe fn __msa_ftint_s_w(a: v4f32) -> v4i32 { /// Vector Floating-Point Convert to Signed Integer /// -///The elements in vector 'a' (two 64-bit floating point numbers) +///The elements in vector `a` (two 64-bit floating point numbers) /// are rounded and converted to signed integer values based on the /// rounding mode bits RM in MSA Control and Status Register MSACSR. /// The result is written to vector (two signed 64-bit integer numbers). @@ -5286,7 +5289,7 @@ pub unsafe fn __msa_ftint_s_d(a: v2f64) -> v2i64 { /// Vector Floating-Point Convert to Unsigned Integer /// -/// The elements in vector 'a' (four 32-bit floating point numbers) +/// The elements in vector `a` (four 32-bit floating point numbers) /// are rounded and converted to signed integer values based on the /// rounding mode bits RM in MSA Control and Status Register MSACSR. /// The result is written to vector (four unsigned 32-bit integer numbers). @@ -5300,7 +5303,7 @@ pub unsafe fn __msa_ftint_u_w(a: v4f32) -> v4u32 { /// Vector Floating-Point Convert to Unsigned Integer /// -/// The elements in vector 'a' (two 64-bit floating point numbers) +/// The elements in vector `a` (two 64-bit floating point numbers) /// are rounded and converted to signed integer values based on the /// rounding mode bits RM in MSA Control and Status Register MSACSR. /// The result is written to vector (two unsigned 64-bit integer numbers). @@ -5314,9 +5317,9 @@ pub unsafe fn __msa_ftint_u_d(a: v2f64) -> v2u64 { /// Vector Floating-Point Convert to Fixed-Point /// -/// The elements in vector 'a' (four 32-bit floating point numbers) -/// and 'b' (four 32-bit floating point numbers)are down-converted to a fixed-point -/// representation, i.e. from 64-bit floating-point to 32-bit Q31 fixed-point +/// The elements in vector `a` (four 32-bit floating point numbers) +/// and `b` (four 32-bit floating point numbers) are down-converted to a fixed-point +/// representation, i.e. from 64-bit floating-point to 32-bit Q31 fixed-point /// representation, or from 32-bit floating-point to 16-bit Q15 fixed-point representation. /// The result is written to vector (eight signed 16-bit integer numbers). /// @@ -5329,9 +5332,9 @@ pub unsafe fn __msa_ftq_h(a: v4f32, b: v4f32) -> v8i16 { /// Vector Floating-Point Convert to Fixed-Point /// -/// The elements in vector 'a' (two 64-bit floating point numbers) -/// and 'b' (two 64-bit floating point numbers) are down-converted to a fixed-point -/// representation, i.e. from 64-bit floating-point to 32-bit Q31 fixed-point +/// The elements in vector `a` (two 64-bit floating point numbers) +/// and `b` (two 64-bit floating point numbers) are down-converted to a fixed-point +/// representation, i.e. from 64-bit floating-point to 32-bit Q31 fixed-point /// representation, or from 32-bit floating-point to 16-bit Q15 fixed-point representation. /// The result is written to vector (four signed 32-bit integer numbers). /// @@ -5344,7 +5347,7 @@ pub unsafe fn __msa_ftq_w(a: v2f64, b: v2f64) -> v4i32 { /// Vector Floating-Point Truncate and Convert to Signed Integer /// -/// The elements in vector 'a' (four 32-bit floating point numbers) +/// The elements in vector `a` (four 32-bit floating point numbers) /// are truncated, i.e. rounded toward zero, to signed integer values. /// The result is written to vector (four signed 32-bit integer numbers). /// @@ -5357,7 +5360,7 @@ pub unsafe fn __msa_ftrunc_s_w(a: v4f32) -> v4i32 { /// Vector Floating-Point Truncate and Convert to Signed Integer /// -/// The elements in vector 'a' (two 64-bit floating point numbers) +/// The elements in vector `a` (two 64-bit floating point numbers) /// are truncated, i.e. rounded toward zero, to signed integer values. /// The result is written to vector (two signed 64-bit integer numbers). /// @@ -5370,7 +5373,7 @@ pub unsafe fn __msa_ftrunc_s_d(a: v2f64) -> v2i64 { /// Vector Floating-Point Truncate and Convert to Unsigned Integer /// -/// The elements in vector 'a' (four 32-bit floating point numbers) +/// The elements in vector `a` (four 32-bit floating point numbers) /// are truncated, i.e. rounded toward zero, to unsigned integer values. /// The result is written to vector (four unsigned 32-bit integer numbers). /// @@ -5383,7 +5386,7 @@ pub unsafe fn __msa_ftrunc_u_w(a: v4f32) -> v4u32 { /// Vector Floating-Point Truncate and Convert to Unsigned Integer /// -/// The elements in vector 'a' (two 64-bit floating point numbers) +/// The elements in vector `a` (two 64-bit floating point numbers) /// are truncated, i.e. rounded toward zero, to unsigned integer values. /// The result is written to vector (two unsigned 64-bit integer numbers). /// @@ -5396,9 +5399,9 @@ pub unsafe fn __msa_ftrunc_u_d(a: v2f64) -> v2u64 { /// Vector Signed Horizontal Add /// -/// The sign-extended odd elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// are added to the sign-extended even elements in vector 'b' (sixteen signed 8-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are added to the sign-extended even elements in vector `b` (sixteen signed 8-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -5410,9 +5413,9 @@ pub unsafe fn __msa_hadd_s_h(a: v16i8, b: v16i8) -> v8i16 { /// Vector Signed Horizontal Add /// -/// The sign-extended odd elements in vector 'a' (eight signed 16-bit integer numbers) -/// are added to the sign-extended even elements in vector 'b' (eight signed 16-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `a` (eight signed 16-bit integer numbers) +/// are added to the sign-extended even elements in vector `b` (eight signed 16-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -5424,9 +5427,9 @@ pub unsafe fn __msa_hadd_s_w(a: v8i16, b: v8i16) -> v4i32 { /// Vector Signed Horizontal Add /// -/// The sign-extended odd elements in vector 'a' (four signed 32-bit integer numbers) -/// are added to the sign-extended even elements in vector 'b' (four signed 32-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `a` (four signed 32-bit integer numbers) +/// are added to the sign-extended even elements in vector `b` (four signed 32-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -5438,9 +5441,9 @@ pub unsafe fn __msa_hadd_s_d(a: v4i32, b: v4i32) -> v2i64 { /// Vector Unsigned Horizontal Add /// -/// The zero-extended odd elements in vector 'a' (sixteen unsigned 8-bit integer numbers) -/// are added to the zero-extended even elements in vector 'b' (sixteen unsigned 8-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are added to the zero-extended even elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (eight unsigned 16-bit integer numbers). /// #[inline] @@ -5452,9 +5455,9 @@ pub unsafe fn __msa_hadd_u_h(a: v16u8, b: v16u8) -> v8u16 { /// Vector Unsigned Horizontal Add /// -/// The zero-extended odd elements in vector 'a' (eight unsigned 16-bit integer numbers) -/// are added to the zero-extended even elements in vector 'b' (eight unsigned 16-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are added to the zero-extended even elements in vector `b` (eight unsigned 16-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (four unsigned 32-bit integer numbers). /// #[inline] @@ -5466,9 +5469,9 @@ pub unsafe fn __msa_hadd_u_w(a: v8u16, b: v8u16) -> v4u32 { /// Vector Unsigned Horizontal Add /// -/// The zero-extended odd elements in vector 'a' (four unsigned 32-bit integer numbers) -/// are added to the zero-extended even elements in vector 'b' (four unsigned 32-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `a` (four unsigned 32-bit integer numbers) +/// are added to the zero-extended even elements in vector `b` (four unsigned 32-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (two unsigned 64-bit integer numbers). /// #[inline] @@ -5480,9 +5483,9 @@ pub unsafe fn __msa_hadd_u_d(a: v4u32, b: v4u32) -> v2u64 { /// Vector Signed Horizontal Subtract /// -/// The sign-extended odd elements in vector 'b' (sixteen signed 8-bit integer numbers) -/// are subtracted from the sign-extended elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are subtracted from the sign-extended elements in vector `a` (sixteen signed 8-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -5494,9 +5497,9 @@ pub unsafe fn __msa_hsub_s_h(a: v16i8, b: v16i8) -> v8i16 { /// Vector Signed Horizontal Subtract /// -/// The sign-extended odd elements in vector 'b' (eight signed 16-bit integer numbers) -/// are subtracted from the sign-extended elements in vector 'a' (eight signed 16-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `b` (eight signed 16-bit integer numbers) +/// are subtracted from the sign-extended elements in vector `a` (eight signed 16-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -5508,9 +5511,9 @@ pub unsafe fn __msa_hsub_s_w(a: v8i16, b: v8i16) -> v4i32 { /// Vector Signed Horizontal Subtract /// -/// The sign-extended odd elements in vector 'b' (four signed 32-bit integer numbers) -/// are subtracted from the sign-extended elements in vector 'a' (four signed 32-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The sign-extended odd elements in vector `b` (four signed 32-bit integer numbers) +/// are subtracted from the sign-extended elements in vector `a` (four signed 32-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -5522,9 +5525,9 @@ pub unsafe fn __msa_hsub_s_d(a: v4i32, b: v4i32) -> v2i64 { /// Vector Unsigned Horizontal Subtract /// -/// The zero-extended odd elements in vector 'b' (sixteen unsigned 8-bit integer numbers) -/// are subtracted from the zero-extended elements in vector 'a' (sixteen unsigned 8-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `b` (sixteen unsigned 8-bit integer numbers) +/// are subtracted from the zero-extended elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -5536,9 +5539,9 @@ pub unsafe fn __msa_hsub_u_h(a: v16u8, b: v16u8) -> v8i16 { /// Vector Unsigned Horizontal Subtract /// -/// The zero-extended odd elements in vector 'b' (eight unsigned 16-bit integer numbers) -/// are subtracted from the zero-extended elements in vector 'a' (eight unsigned 16-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `b` (eight unsigned 16-bit integer numbers) +/// are subtracted from the zero-extended elements in vector `a` (eight unsigned 16-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -5550,9 +5553,9 @@ pub unsafe fn __msa_hsub_u_w(a: v8u16, b: v8u16) -> v4i32 { /// Vector Unsigned Horizontal Subtract /// -/// The zero-extended odd elements in vector 'b' (four unsigned 32-bit integer numbers) -/// are subtracted from the zero-extended elements in vector 'a' (four unsigned 32-bit integer numbers) -/// producing aresult twice the size of the input operands. +/// The zero-extended odd elements in vector `b` (four unsigned 32-bit integer numbers) +/// are subtracted from the zero-extended elements in vector `a` (four unsigned 32-bit integer numbers) +/// producing a result twice the size of the input operands. /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -5564,10 +5567,10 @@ pub unsafe fn __msa_hsub_u_d(a: v4u32, b: v4u32) -> v2i64 { /// Vector Interleave Even /// -/// Even elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// and vector 'b' (sixteen signed 8-bit integer numbers) are copied to the result +/// Even elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// and vector `b` (sixteen signed 8-bit integer numbers) are copied to the result /// (sixteen signed 8-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5578,10 +5581,10 @@ pub unsafe fn __msa_ilvev_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Interleave Even /// -/// Even elements in vectors 'a' (eight signed 16-bit integer numbers) -/// and vector 'b' (eight signed 16-bit integer numbers) are copied to the result +/// Even elements in vectors `a` (eight signed 16-bit integer numbers) +/// and vector `b` (eight signed 16-bit integer numbers) are copied to the result /// (eight signed 16-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5592,10 +5595,10 @@ pub unsafe fn __msa_ilvev_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Interleave Even /// -/// Even elements in vectors 'a' (four signed 32-bit integer numbers) -/// and vector 'b' (four signed 32-bit integer numbers) are copied to the result +/// Even elements in vectors `a` (four signed 32-bit integer numbers) +/// and vector `b` (four signed 32-bit integer numbers) are copied to the result /// (four signed 32-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5606,10 +5609,10 @@ pub unsafe fn __msa_ilvev_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Interleave Even /// -/// Even elements in vectors 'a' (two signed 64-bit integer numbers) -/// and vector 'b' (two signed 64-bit integer numbers) are copied to the result +/// Even elements in vectors `a` (two signed 64-bit integer numbers) +/// and vector `b` (two signed 64-bit integer numbers) are copied to the result /// (two signed 64-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5620,10 +5623,10 @@ pub unsafe fn __msa_ilvev_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Interleave Left /// -/// The left half elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// and vector 'b' (sixteen signed 8-bit integer numbers) are copied to the result +/// The left half elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// and vector `b` (sixteen signed 8-bit integer numbers) are copied to the result /// (sixteen signed 8-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5634,10 +5637,10 @@ pub unsafe fn __msa_ilvl_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Interleave Left /// -/// The left half elements in vectors 'a' (eight signed 16-bit integer numbers) -/// and vector 'b' (eight signed 16-bit integer numbers) are copied to the result +/// The left half elements in vectors `a` (eight signed 16-bit integer numbers) +/// and vector `b` (eight signed 16-bit integer numbers) are copied to the result /// (eight signed 16-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5648,10 +5651,10 @@ pub unsafe fn __msa_ilvl_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Interleave Left /// -/// The left half elements in vectors 'a' (four signed 32-bit integer numbers) -/// and vector 'b' (four signed 32-bit integer numbers) are copied to the result +/// The left half elements in vectors `a` (four signed 32-bit integer numbers) +/// and vector `b` (four signed 32-bit integer numbers) are copied to the result /// (four signed 32-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5662,10 +5665,10 @@ pub unsafe fn __msa_ilvl_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Interleave Left /// -/// The left half elements in vectors 'a' (two signed 64-bit integer numbers) -/// and vector 'b' (two signed 64-bit integer numbers) are copied to the result +/// The left half elements in vectors `a` (two signed 64-bit integer numbers) +/// and vector `b` (two signed 64-bit integer numbers) are copied to the result /// (two signed 64-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5676,10 +5679,10 @@ pub unsafe fn __msa_ilvl_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Interleave Odd /// -/// Odd elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// and vector 'b' (sixteen signed 8-bit integer numbers) are copied to the result +/// Odd elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// and vector `b` (sixteen signed 8-bit integer numbers) are copied to the result /// (sixteen signed 8-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5690,10 +5693,10 @@ pub unsafe fn __msa_ilvod_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Interleave Odd /// -/// Odd elements in vectors 'a' (eight signed 16-bit integer numbers) -/// and vector 'b' (eight signed 16-bit integer numbers) are copied to the result +/// Odd elements in vectors `a` (eight signed 16-bit integer numbers) +/// and vector `b` (eight signed 16-bit integer numbers) are copied to the result /// (eight signed 16-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5704,10 +5707,10 @@ pub unsafe fn __msa_ilvod_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Interleave Odd /// -/// Odd elements in vectors 'a' (four signed 32-bit integer numbers) -/// and vector 'b' (four signed 32-bit integer numbers) are copied to the result +/// Odd elements in vectors `a` (four signed 32-bit integer numbers) +/// and vector `b` (four signed 32-bit integer numbers) are copied to the result /// (four signed 32-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5718,10 +5721,10 @@ pub unsafe fn __msa_ilvod_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Interleave Odd /// -/// Odd elements in vectors 'a' (two signed 64-bit integer numbers) -/// and vector 'b' (two signed 64-bit integer numbers) are copied to the result +/// Odd elements in vectors `a` (two signed 64-bit integer numbers) +/// and vector `b` (two signed 64-bit integer numbers) are copied to the result /// (two signed 64-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5732,10 +5735,10 @@ pub unsafe fn __msa_ilvod_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Interleave Right /// -/// The right half elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// and vector 'b' (sixteen signed 8-bit integer numbers) are copied to the result +/// The right half elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// and vector `b` (sixteen signed 8-bit integer numbers) are copied to the result /// (sixteen signed 8-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5746,10 +5749,10 @@ pub unsafe fn __msa_ilvr_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Interleave Right /// -/// The right half elements in vectors 'a' (eight signed 16-bit integer numbers) -/// and vector 'b' (eight signed 16-bit integer numbers) are copied to the result +/// The right half elements in vectors `a` (eight signed 16-bit integer numbers) +/// and vector `b` (eight signed 16-bit integer numbers) are copied to the result /// (eight signed 16-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5760,10 +5763,10 @@ pub unsafe fn __msa_ilvr_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Interleave Right /// -/// The right half elements in vectors 'a' (four signed 32-bit integer numbers) -/// and vector 'b' (four signed 32-bit integer numbers) are copied to the result +/// The right half elements in vectors `a` (four signed 32-bit integer numbers) +/// and vector `b` (four signed 32-bit integer numbers) are copied to the result /// (four signed 32-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5774,10 +5777,10 @@ pub unsafe fn __msa_ilvr_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Interleave Right /// -/// The right half elements in vectors 'a' (two signed 64-bit integer numbers) -/// and vector 'b' (two signed 64-bit integer numbers) are copied to the result +/// The right half elements in vectors `a` (two signed 64-bit integer numbers) +/// and vector `b` (two signed 64-bit integer numbers) are copied to the result /// (two signed 64-bit integer numbers) -/// alternating one element from 'a' with one element from 'b'. +/// alternating one element from `a` with one element from `b`. /// #[inline] #[target_feature(enable = "msa")] @@ -5788,8 +5791,8 @@ pub unsafe fn __msa_ilvr_d(a: v2i64, b: v2i64) -> v2i64 { /// GPR Insert Element /// -/// Set element imm4 in vector 'a' (sixteen signed 8-bit integer numbers) to GPR 'c' value. -/// All other elements in vector 'a' are unchanged. If the source GPR is wider than the +/// Set element `imm4` in vector `a` (sixteen signed 8-bit integer numbers) to GPR `c` value. +/// All other elements in vector `a` are unchanged. If the source GPR is wider than the /// destination data format, the destination's elements will be set to the least significant bits of the GPR. /// #[inline] @@ -5807,8 +5810,8 @@ pub unsafe fn __msa_insert_b(a: v16i8, imm4: i32, c: i32) -> v16i8 { /// GPR Insert Element /// -/// Set element imm3 in vector 'a' (eight signed 16-bit integer numbers) to GPR 'c' value. -/// All other elements in vector 'a' are unchanged. If the source GPR is wider than the +/// Set element `imm3` in vector `a` (eight signed 16-bit integer numbers) to GPR `c` value. +/// All other elements in vector `a` are unchanged. If the source GPR is wider than the /// destination data format, the destination's elements will be set to the least significant bits of the GPR. /// #[inline] @@ -5826,8 +5829,8 @@ pub unsafe fn __msa_insert_h(a: v8i16, imm3: i32, c: i32) -> v8i16 { /// GPR Insert Element /// -/// Set element imm2 in vector 'a' (four signed 32-bit integer numbers) to GPR 'c' value. -/// All other elements in vector 'a' are unchanged. If the source GPR is wider than the +/// Set element `imm2` in vector `a` (four signed 32-bit integer numbers) to GPR `c` value. +/// All other elements in vector `a` are unchanged. If the source GPR is wider than the /// destination data format, the destination's elements will be set to the least significant bits of the GPR. /// #[inline] @@ -5845,8 +5848,8 @@ pub unsafe fn __msa_insert_w(a: v4i32, imm2: i32, c: i32) -> v4i32 { /// GPR Insert Element /// -/// Set element imm1 in vector 'a' (two signed 64-bit integer numbers) to GPR 'c' value. -/// All other elements in vector 'a' are unchanged. If the source GPR is wider than the +/// Set element `imm1` in vector `a` (two signed 64-bit integer numbers) to GPR `c` value. +/// All other elements in vector `a` are unchanged. If the source GPR is wider than the /// destination data format, the destination's elements will be set to the least significant bits of the GPR. /// #[inline] @@ -5864,9 +5867,9 @@ pub unsafe fn __msa_insert_d(a: v2i64, imm1: i32, c: i64) -> v2i64 { /// Element Insert Element /// -/// Set element imm1 in the result vector 'a' (sixteen signed 8-bit integer numbers) to element 0 -/// in vector 'c' (sixteen signed 8-bit integer numbers) value. -/// All other elements in vector 'a' are unchanged. +/// Set element `imm1` in the result vector `a` (sixteen signed 8-bit integer numbers) to element 0 +/// in vector `c` (sixteen signed 8-bit integer numbers) value. +/// All other elements in vector `a` are unchanged. /// #[inline] #[target_feature(enable = "msa")] @@ -5883,9 +5886,9 @@ pub unsafe fn __msa_insve_b(a: v16i8, imm4: i32, c: v16i8) -> v16i8 { /// Element Insert Element /// -/// Set element imm1 in the result vector 'a' (eight signed 16-bit integer numbers) to element 0 -/// in vector 'c' (eight signed 16-bit integer numbers) value. -/// All other elements in vector 'a' are unchanged. +/// Set element `imm1` in the result vector `a` (eight signed 16-bit integer numbers) to element 0 +/// in vector `c` (eight signed 16-bit integer numbers) value. +/// All other elements in vector `a` are unchanged. /// #[inline] #[target_feature(enable = "msa")] @@ -5902,9 +5905,9 @@ pub unsafe fn __msa_insve_h(a: v8i16, imm3: i32, c: v8i16) -> v8i16 { /// Element Insert Element /// -/// Set element imm1 in the result vector 'a' (four signed 32-bit integer numbers) to element 0 -/// in vector 'c' (four signed 32-bit integer numbers) value. -/// All other elements in vector 'a' are unchanged. +/// Set element `imm1` in the result vector `a` (four signed 32-bit integer numbers) to element 0 +/// in vector `c` (four signed 32-bit integer numbers) value. +/// All other elements in vector `a` are unchanged. /// #[inline] #[target_feature(enable = "msa")] @@ -5921,9 +5924,9 @@ pub unsafe fn __msa_insve_w(a: v4i32, imm2: i32, c: v4i32) -> v4i32 { /// Element Insert Element /// -/// Set element imm1 in the result vector 'a' (two signed 64-bit integer numbers) to element 0 -/// in vector 'c' (two signed 64-bit integer numbers) value. -/// All other elements in vector 'a' are unchanged. +/// Set element `imm1` in the result vector `a` (two signed 64-bit integer numbers) to element 0 +/// in vector `c` (two signed 64-bit integer numbers) value. +/// All other elements in vector `a` are unchanged. /// #[inline] #[target_feature(enable = "msa")] @@ -5940,8 +5943,8 @@ pub unsafe fn __msa_insve_d(a: v2i64, imm1: i32, c: v2i64) -> v2i64 { /// Vector Load /// -/// The WRLEN / 8 bytes at the ef fective memory location addressed by the base -/// mem_addr and the 10-bit signed immediate offset imm_s10 are fetched and placed in +/// The WRLEN / 8 bytes at the effective memory location addressed by the base +/// `mem_addr` and the 10-bit signed immediate offset `imm_s10` are fetched and placed in /// the vector (sixteen signed 8-bit integer numbers) value. /// #[inline] @@ -5959,8 +5962,8 @@ pub unsafe fn __msa_ld_b(mem_addr: *mut u8, imm_s10: i32) -> v16i8 { /// Vector Load /// -/// The WRLEN / 8 bytes at the ef fective memory location addressed by the base -/// mem_addr and the 10-bit signed immediate offset imm_s11 are fetched and placed in +/// The WRLEN / 8 bytes at the effective memory location addressed by the base +/// `mem_addr` and the 10-bit signed immediate offset `imm_s11` are fetched and placed in /// the vector (eight signed 16-bit integer numbers) value. /// #[inline] @@ -5978,8 +5981,8 @@ pub unsafe fn __msa_ld_h(mem_addr: *mut u8, imm_s11: i32) -> v8i16 { /// Vector Load /// -/// The WRLEN / 8 bytes at the ef fective memory location addressed by the base -/// mem_addr and the 10-bit signed immediate offset imm_s12 are fetched and placed in +/// The WRLEN / 8 bytes at the effective memory location addressed by the base +/// `mem_addr` and the 10-bit signed immediate offset `imm_s12` are fetched and placed in /// the vector (four signed 32-bit integer numbers) value. /// #[inline] @@ -5997,8 +6000,8 @@ pub unsafe fn __msa_ld_w(mem_addr: *mut u8, imm_s12: i32) -> v4i32 { /// Vector Load /// -/// The WRLEN / 8 bytes at the ef fective memory location addressed by the base -/// mem_addr and the 10-bit signed immediate offset imm_s13 are fetched and placed in +/// The WRLEN / 8 bytes at the effective memory location addressed by the base +/// `mem_addr` and the 10-bit signed immediate offset `imm_s13` are fetched and placed in /// the vector (two signed 64-bit integer numbers) value. /// #[inline] @@ -6092,11 +6095,11 @@ pub unsafe fn __msa_ldi_d(imm_s10: i32) -> v2i64 { /// Vector Fixed-Point Multiply and Add /// -/// The products of fixed-point elements in 'b' (eight signed 16-bit integer numbers) -/// by fixed-point elements in vector 'c' (eight signed 16-bit integer numbers) -/// are added to the fixed-pointelements in vector 'a' (eight signed 16-bit integer numbers) +/// The products of fixed-point elements in `b` (eight signed 16-bit integer numbers) +/// by fixed-point elements in vector `c` (eight signed 16-bit integer numbers) +/// are added to the fixed-point elements in vector `a` (eight signed 16-bit integer numbers). /// The multiplication result is not saturated, i.e. exact (-1) * (-1) = 1 is added to the destination. -/// The saturated fixed-point results are stored to vector 'a' +/// The saturated fixed-point results are stored to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6107,11 +6110,11 @@ pub unsafe fn __msa_madd_q_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply and Add /// -/// The products of fixed-point elements in 'b' (four signed 32-bit integer numbers) -/// by fixed-point elements in vector 'c' (four signed 32-bit integer numbers) -/// are added to the fixed-pointelements in vector 'a' (four signed 32-bit integer numbers) +/// The products of fixed-point elements in `b` (four signed 32-bit integer numbers) +/// by fixed-point elements in vector `c` (four signed 32-bit integer numbers) +/// are added to the fixed-point elements in vector `a` (four signed 32-bit integer numbers). /// The multiplication result is not saturated, i.e. exact (-1) * (-1) = 1 is added to the destination. -/// The saturated fixed-point results are stored to vector 'a' +/// The saturated fixed-point results are stored to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6122,11 +6125,11 @@ pub unsafe fn __msa_madd_q_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Fixed-Point Multiply and Add Rounded /// -/// The products of fixed-point elements in 'b' (eight signed 16-bit integer numbers) -/// by fixed-point elements in vector 'c' (eight signed 16-bit integer numbers) -/// are added to the fixed-pointelements in vector 'a' (eight signed 16-bit integer numbers) +/// The products of fixed-point elements in `b` (eight signed 16-bit integer numbers) +/// by fixed-point elements in vector `c` (eight signed 16-bit integer numbers) +/// are added to the fixed-point elements in vector `a` (eight signed 16-bit integer numbers). /// The multiplication result is not saturated, i.e. exact (-1) * (-1) = 1 is added to the destination. -/// The rounded and saturated fixed-point results are stored to vector 'a' +/// The rounded and saturated fixed-point results are stored to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6137,11 +6140,11 @@ pub unsafe fn __msa_maddr_q_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply and Add Rounded /// -/// The products of fixed-point elements in 'b' (four signed 32-bit integer numbers) -/// by fixed-point elements in vector 'c' (four signed 32-bit integer numbers) -/// are added to the fixed-pointelements in vector 'a' (four signed 32-bit integer numbers) +/// The products of fixed-point elements in `b` (four signed 32-bit integer numbers) +/// by fixed-point elements in vector `c` (four signed 32-bit integer numbers) +/// are added to the fixed-point elements in vector `a` (four signed 32-bit integer numbers). /// The multiplication result is not saturated, i.e. exact (-1) * (-1) = 1 is added to the destination. -/// The rounded and saturated fixed-point results are stored to vector 'a' +/// The rounded and saturated fixed-point results are stored to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6152,9 +6155,9 @@ pub unsafe fn __msa_maddr_q_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Multiply and Add /// -/// The integer elements in vector 'b' (sixteen signed 8-bit integer numbers) -/// are multiplied by integer elements in vector 'c' (sixteen signed 8-bit integer numbers) -/// and added to the integer elements in vector 'a' (sixteen signed 8-bit integer numbers) +/// The integer elements in vector `b` (sixteen signed 8-bit integer numbers) +/// are multiplied by integer elements in vector `c` (sixteen signed 8-bit integer numbers) +/// and added to the integer elements in vector `a` (sixteen signed 8-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -6166,9 +6169,9 @@ pub unsafe fn __msa_maddv_b(a: v16i8, b: v16i8, c: v16i8) -> v16i8 { /// Vector Multiply and Add /// -/// The integer elements in vector 'b' (eight signed 16-bit integer numbers) -/// are multiplied by integer elements in vector 'c' (eight signed 16-bit integer numbers) -/// and added to the integer elements in vector 'a' (eight signed 16-bit integer numbers) +/// The integer elements in vector `b` (eight signed 16-bit integer numbers) +/// are multiplied by integer elements in vector `c` (eight signed 16-bit integer numbers) +/// and added to the integer elements in vector `a` (eight signed 16-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -6180,9 +6183,9 @@ pub unsafe fn __msa_maddv_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Multiply and Add /// -/// The integer elements in vector 'b' (four signed 32-bit integer numbers) -/// are multiplied by integer elements in vector 'c' (four signed 32-bit integer numbers) -/// and added to the integer elements in vector 'a' (four signed 32-bit integer numbers) +/// The integer elements in vector `b` (four signed 32-bit integer numbers) +/// are multiplied by integer elements in vector `c` (four signed 32-bit integer numbers) +/// and added to the integer elements in vector `a` (four signed 32-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -6194,9 +6197,9 @@ pub unsafe fn __msa_maddv_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Multiply and Add /// -/// The integer elements in vector 'b' (two signed 64-bit integer numbers) -/// are multiplied by integer elements in vector 'c' (two signed 64-bit integer numbers) -/// and added to the integer elements in vector 'a' (two signed 64-bit integer numbers) +/// The integer elements in vector `b` (two signed 64-bit integer numbers) +/// are multiplied by integer elements in vector `c` (two signed 64-bit integer numbers) +/// and added to the integer elements in vector `a` (two signed 64-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -6209,9 +6212,9 @@ pub unsafe fn __msa_maddv_d(a: v2i64, b: v2i64, c: v2i64) -> v2i64 { /// Vector Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(sixteen signed 8-bit integer numbers) and -/// 'b'(sixteen signed 8-bit integer numbers) are written to vector -/// (sixteen signed 8-bit integer numbers) +/// signed elements in vector `a` (sixteen signed 8-bit integer numbers) and +/// `b` (sixteen signed 8-bit integer numbers) are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6223,9 +6226,9 @@ pub unsafe fn __msa_max_a_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(eight signed 16-bit integer numbers) and -/// 'b'(eight signed 16-bit integer numbers) are written to vector -/// (eight signed 16-bit integer numbers) +/// signed elements in vector `a` (eight signed 16-bit integer numbers) and +/// `b` (eight signed 16-bit integer numbers) are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6237,9 +6240,9 @@ pub unsafe fn __msa_max_a_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(four signed 32-bit integer numbers) and -/// 'b'(four signed 32-bit integer numbers) are written to vector -/// (four signed 32-bit integer numbers) +/// signed elements in vector `a` (four signed 32-bit integer numbers) and +/// `b` (four signed 32-bit integer numbers) are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6251,9 +6254,9 @@ pub unsafe fn __msa_max_a_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Maximum Based on Absolute Values /// /// The value with the largest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(two signed 64-bit integer numbers) and -/// 'b'(two signed 64-bit integer numbers) are written to vector -/// (two signed 64-bit integer numbers) +/// signed elements in vector `a` (two signed 64-bit integer numbers) and +/// `b` (two signed 64-bit integer numbers) are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6264,9 +6267,9 @@ pub unsafe fn __msa_max_a_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// and signed elements in vector 'b'(sixteen signed 8-bit integer numbers) are written to vector -/// (sixteen signed 8-bit integer numbers) +/// Maximum values between signed elements in vector `a` (sixteen signed 8-bit integer numbers) +/// and signed elements in vector `b` (sixteen signed 8-bit integer numbers) are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6277,9 +6280,9 @@ pub unsafe fn __msa_max_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(eight signed 16-bit integer numbers) -/// and signed elements in vector 'b'(eight signed 16-bit integer numbers) are written to vector -/// (eight signed 16-bit integer numbers) +/// Maximum values between signed elements in vector `a` (eight signed 16-bit integer numbers) +/// and signed elements in vector `b` (eight signed 16-bit integer numbers) are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6290,9 +6293,9 @@ pub unsafe fn __msa_max_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(four signed 32-bit integer numbers) -/// and signed elements in vector 'b'(four signed 32-bit integer numbers) are written to vector -/// (four signed 32-bit integer numbers) +/// Maximum values between signed elements in vector `a` (four signed 32-bit integer numbers) +/// and signed elements in vector `b` (four signed 32-bit integer numbers) are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6303,9 +6306,9 @@ pub unsafe fn __msa_max_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(two signed 64-bit integer numbers) -/// and signed elements in vector 'b'(two signed 64-bit integer numbers) are written to vector -/// (two signed 64-bit integer numbers) +/// Maximum values between signed elements in vector `a` (two signed 64-bit integer numbers) +/// and signed elements in vector `b` (two signed 64-bit integer numbers) are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6316,9 +6319,9 @@ pub unsafe fn __msa_max_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(sixteen unsigned 8-bit integer numbers) -/// and unsigned elements in vector 'b'(sixteen unsigned 8-bit integer numbers) are written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// and unsigned elements in vector `b` (sixteen unsigned 8-bit integer numbers) are written to vector +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6329,9 +6332,9 @@ pub unsafe fn __msa_max_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(eight unsigned 16-bit integer numbers) -/// and unsigned elements in vector 'b'(eight unsigned 16-bit integer numbers) are written to vector -/// (eight unsigned 16-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// and unsigned elements in vector `b` (eight unsigned 16-bit integer numbers) are written to vector +/// (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6342,9 +6345,9 @@ pub unsafe fn __msa_max_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(four unsigned 32-bit integer numbers) -/// and unsigned elements in vector 'b'(four unsigned 32-bit integer numbers) are written to vector -/// (four unsigned 32-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// and unsigned elements in vector `b` (four unsigned 32-bit integer numbers) are written to vector +/// (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6355,9 +6358,9 @@ pub unsafe fn __msa_max_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(two unsigned 64-bit integer numbers) -/// and unsigned elements in vector 'b'(two unsigned 64-bit integer numbers) are written to vector -/// (two unsigned 64-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// and unsigned elements in vector `b` (two unsigned 64-bit integer numbers) are written to vector +/// (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6368,9 +6371,9 @@ pub unsafe fn __msa_max_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Immediate Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (sixteen signed 8-bit integer numbers) +/// Maximum values between signed elements in vector `a` (sixteen signed 8-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6387,9 +6390,9 @@ pub unsafe fn __msa_maxi_s_b(a: v16i8, imm_s5: i32) -> v16i8 { /// Immediate Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(eight signed 16-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (eight signed 16-bit integer numbers) +/// Maximum values between signed elements in vector `a` (eight signed 16-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6406,9 +6409,9 @@ pub unsafe fn __msa_maxi_s_h(a: v8i16, imm_s5: i32) -> v8i16 { /// Immediate Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(four signed 32-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (four signed 32-bit integer numbers) +/// Maximum values between signed elements in vector `a` (four signed 32-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6425,9 +6428,9 @@ pub unsafe fn __msa_maxi_s_w(a: v4i32, imm_s5: i32) -> v4i32 { /// Immediate Signed Maximum /// -/// Maximum values between signed elements in vector 'a'(two signed 64-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (two signed 64-bit integer numbers) +/// Maximum values between signed elements in vector `a` (two signed 64-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6444,9 +6447,9 @@ pub unsafe fn __msa_maxi_s_d(a: v2i64, imm_s5: i32) -> v2i64 { /// Immediate Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(sixteen unsigned 8-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6463,9 +6466,9 @@ pub unsafe fn __msa_maxi_u_b(a: v16u8, imm5: i32) -> v16u8 { /// Immediate Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(eight unsigned 16-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (eight unsigned 16-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6482,9 +6485,9 @@ pub unsafe fn __msa_maxi_u_h(a: v8u16, imm5: i32) -> v8u16 { /// Immediate Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(four unsigned 32-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (four unsigned 32-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6501,9 +6504,9 @@ pub unsafe fn __msa_maxi_u_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Unsigned Maximum /// -/// Maximum values between unsigned elements in vector 'a'(two unsigned 64-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (two unsigned 64-bit integer numbers) +/// Maximum values between unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6521,9 +6524,9 @@ pub unsafe fn __msa_maxi_u_d(a: v2u64, imm5: i32) -> v2u64 { /// Vector Minimum Based on Absolute Value /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(sixteen signed 8-bit integer numbers) and -/// 'b'(sixteen signed 8-bit integer numbers) are written to vector -/// (sixteen signed 8-bit integer numbers) +/// signed elements in vector `a` (sixteen signed 8-bit integer numbers) and +/// `b` (sixteen signed 8-bit integer numbers) are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6535,9 +6538,9 @@ pub unsafe fn __msa_min_a_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Minimum Based on Absolute Value /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(eight signed 16-bit integer numbers) and -/// 'b'(eight signed 16-bit integer numbers) are written to vector -/// (eight signed 16-bit integer numbers) +/// signed elements in vector `a` (eight signed 16-bit integer numbers) and +/// `b` (eight signed 16-bit integer numbers) are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6549,9 +6552,9 @@ pub unsafe fn __msa_min_a_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Minimum Based on Absolute Value /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(four signed 32-bit integer numbers) and -/// 'b'(four signed 32-bit integer numbers) are written to vector -/// (four signed 32-bit integer numbers) +/// signed elements in vector `a` (four signed 32-bit integer numbers) and +/// `b` (four signed 32-bit integer numbers) are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6563,9 +6566,9 @@ pub unsafe fn __msa_min_a_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Minimum Based on Absolute Value /// /// The value with the smallest magnitude, i.e. absolute value, between corresponding -/// signed elements in vector 'a'(two signed 64-bit integer numbers) and -/// 'b'(two signed 64-bit integer numbers) are written to vector -/// (two signed 64-bit integer numbers) +/// signed elements in vector `a` (two signed 64-bit integer numbers) and +/// `b` (two signed 64-bit integer numbers) are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6576,9 +6579,9 @@ pub unsafe fn __msa_min_a_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// and signed elements in vector 'b'(sixteen signed 8-bit integer numbers) are written to vector -/// (sixteen signed 8-bit integer numbers) +/// Minimum values between signed elements in vector `a` (sixteen signed 8-bit integer numbers) +/// and signed elements in vector `b` (sixteen signed 8-bit integer numbers) are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6589,9 +6592,9 @@ pub unsafe fn __msa_min_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(eight signed 16-bit integer numbers) -/// and signed elements in vector 'b'(eight signed 16-bit integer numbers) are written to vector -/// (eight signed 16-bit integer numbers) +/// Minimum values between signed elements in vector `a` (eight signed 16-bit integer numbers) +/// and signed elements in vector `b` (eight signed 16-bit integer numbers) are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6602,9 +6605,9 @@ pub unsafe fn __msa_min_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(four signed 32-bit integer numbers) -/// and signed elements in vector 'b'(four signed 32-bit integer numbers) are written to vector -/// (four signed 32-bit integer numbers) +/// Minimum values between signed elements in vector `a` (four signed 32-bit integer numbers) +/// and signed elements in vector `b` (four signed 32-bit integer numbers) are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6615,9 +6618,9 @@ pub unsafe fn __msa_min_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(two signed 64-bit integer numbers) -/// and signed elements in vector 'b'(two signed 64-bit integer numbers) are written to vector -/// (two signed 64-bit integer numbers) +/// Minimum values between signed elements in vector `a` (two signed 64-bit integer numbers) +/// and signed elements in vector `b` (two signed 64-bit integer numbers) are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6628,9 +6631,9 @@ pub unsafe fn __msa_min_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (sixteen signed 8-bit integer numbers) +/// Minimum values between signed elements in vector `a` (sixteen signed 8-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6647,9 +6650,9 @@ pub unsafe fn __msa_mini_s_b(a: v16i8, imm_s5: i32) -> v16i8 { /// Immediate Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(eight signed 16-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (eight signed 16-bit integer numbers) +/// Minimum values between signed elements in vector `a` (eight signed 16-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6666,9 +6669,9 @@ pub unsafe fn __msa_mini_s_h(a: v8i16, imm_s5: i32) -> v8i16 { /// Immediate Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(four signed 32-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (four signed 32-bit integer numbers) +/// Minimum values between signed elements in vector `a` (four signed 32-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6685,9 +6688,9 @@ pub unsafe fn __msa_mini_s_w(a: v4i32, imm_s5: i32) -> v4i32 { /// Immediate Signed Minimum /// -/// Minimum values between signed elements in vector 'a'(two signed 64-bit integer numbers) -/// and the 5-bit signed immediate imm_s5 are written to vector -/// (two signed 64-bit integer numbers) +/// Minimum values between signed elements in vector `a` (two signed 64-bit integer numbers) +/// and the 5-bit signed immediate imm_s5 are written to vector +/// (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6704,9 +6707,9 @@ pub unsafe fn __msa_mini_s_d(a: v2i64, imm_s5: i32) -> v2i64 { /// Vector Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(sixteen unsigned 8-bit integer numbers) -/// and unsigned elements in vector 'b'(sixteen unsigned 8-bit integer numbers) are written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// and unsigned elements in vector `b` (sixteen unsigned 8-bit integer numbers) are written to vector +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6717,9 +6720,9 @@ pub unsafe fn __msa_min_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(eight unsigned 16-bit integer numbers) -/// and unsigned elements in vector 'b'(eight unsigned 16-bit integer numbers) are written to vector -/// (eight unsigned 16-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// and unsigned elements in vector `b` (eight unsigned 16-bit integer numbers) are written to vector +/// (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6730,9 +6733,9 @@ pub unsafe fn __msa_min_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(four unsigned 32-bit integer numbers) -/// and unsigned elements in vector 'b'(four unsigned 32-bit integer numbers) are written to vector -/// (four unsigned 32-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// and unsigned elements in vector `b` (four unsigned 32-bit integer numbers) are written to vector +/// (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6743,9 +6746,9 @@ pub unsafe fn __msa_min_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(two unsigned 64-bit integer numbers) -/// and unsigned elements in vector 'b'(two unsigned 64-bit integer numbers) are written to vector -/// (two unsigned 64-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// and unsigned elements in vector `b` (two unsigned 64-bit integer numbers) are written to vector +/// (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6756,9 +6759,9 @@ pub unsafe fn __msa_min_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Immediate Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(sixteen unsigned 8-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6775,9 +6778,9 @@ pub unsafe fn __msa_mini_u_b(a: v16u8, imm5: i32) -> v16u8 { /// Immediate Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(eight unsigned 16-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (eight unsigned 16-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6794,9 +6797,9 @@ pub unsafe fn __msa_mini_u_h(a: v8u16, imm5: i32) -> v8u16 { /// Immediate Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(four unsigned 32-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (four unsigned 32-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6813,9 +6816,9 @@ pub unsafe fn __msa_mini_u_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Unsigned Minimum /// -/// Minimum values between unsigned elements in vector 'a'(two unsigned 64-bit integer numbers) -/// and the 5-bit unsigned immediate imm5 are written to vector -/// (two unsigned 64-bit integer numbers) +/// Minimum values between unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// and the 5-bit unsigned immediate `imm5` are written to vector +/// (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -6832,10 +6835,10 @@ pub unsafe fn __msa_mini_u_d(a: v2u64, imm5: i32) -> v2u64 { /// Vector Signed Modulo /// -/// The signed integer elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are divided by signed integer elements in vector 'b'(sixteen signed 8-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (sixteen signed 8-bit integer numbers).If a divisor element vectorwt is zero, +/// The signed integer elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are divided by signed integer elements in vector `b` (sixteen signed 8-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (sixteen signed 8-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6847,10 +6850,10 @@ pub unsafe fn __msa_mod_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Modulo /// -/// The signed integer elements in vector 'a'(eight signed 16-bit integer numbers) -/// are divided by signed integer elements in vector 'b'(eight signed 16-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (eight signed 16-bit integer numbers).If a divisor element vectorwt is zero, +/// The signed integer elements in vector `a` (eight signed 16-bit integer numbers) +/// are divided by signed integer elements in vector `b` (eight signed 16-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (eight signed 16-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6862,10 +6865,10 @@ pub unsafe fn __msa_mod_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Modulo /// -/// The signed integer elements in vector 'a'(four signed 32-bit integer numbers) -/// are divided by signed integer elements in vector 'b'(four signed 32-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (four signed 32-bit integer numbers).If a divisor element vectorwt is zero, +/// The signed integer elements in vector `a` (four signed 32-bit integer numbers) +/// are divided by signed integer elements in vector `b` (four signed 32-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (four signed 32-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6877,10 +6880,10 @@ pub unsafe fn __msa_mod_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Modulo /// -/// The signed integer elements in vector 'a'(two signed 64-bit integer numbers) -/// are divided by signed integer elements in vector 'b'(two signed 64-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (two signed 64-bit integer numbers).If a divisor element vectorwt is zero, +/// The signed integer elements in vector `a` (two signed 64-bit integer numbers) +/// are divided by signed integer elements in vector `b` (two signed 64-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (two signed 64-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6892,10 +6895,10 @@ pub unsafe fn __msa_mod_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Modulo /// -/// The unsigned integer elements in vector 'a'(sixteen unsigned 8-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b'(sixteen unsigned 8-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (sixteen unsigned 8-bit integer numbers).If a divisor element vectorwt is zero, +/// The unsigned integer elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (sixteen unsigned 8-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (sixteen unsigned 8-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6907,10 +6910,10 @@ pub unsafe fn __msa_mod_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Modulo /// -/// The unsigned integer elements in vector 'a'(eight unsigned 16-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b'(eight unsigned 16-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (eight unsigned 16-bit integer numbers).If a divisor element vectorwt is zero, +/// The unsigned integer elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (eight unsigned 16-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (eight unsigned 16-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6922,10 +6925,10 @@ pub unsafe fn __msa_mod_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Modulo /// -/// The unsigned integer elements in vector 'a'(four unsigned 32-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b'(four unsigned 32-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (four unsigned 32-bit integer numbers).If a divisor element vectorwt is zero, +/// The unsigned integer elements in vector `a` (four unsigned 32-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (four unsigned 32-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (four unsigned 32-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6937,10 +6940,10 @@ pub unsafe fn __msa_mod_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Modulo /// -/// The unsigned integer elements in vector 'a'(two unsigned 64-bit integer numbers) -/// are divided by unsigned integer elements in vector 'b'(two unsigned 64-bit integer numbers) -/// The remainder of thesame sign as the dividend is written to vector -/// (two unsigned 64-bit integer numbers).If a divisor element vectorwt is zero, +/// The unsigned integer elements in vector `a` (two unsigned 64-bit integer numbers) +/// are divided by unsigned integer elements in vector `b` (two unsigned 64-bit integer numbers). +/// The remainder of the same sign as the dividend is written to vector +/// (two unsigned 64-bit integer numbers). If a divisor element vector `b` is zero, /// the result value is UNPREDICTABLE. /// #[inline] @@ -6952,7 +6955,7 @@ pub unsafe fn __msa_mod_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Move /// -/// Copy all WRLEN bits in vector 'a'(eight signed 16-bit integer numbers) +/// Copy all WRLEN bits in vector `a` (eight signed 16-bit integer numbers) /// to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -6964,12 +6967,12 @@ pub unsafe fn __msa_move_v(a: v16i8) -> v16i8 { /// Vector Fixed-Point Multiply and Subtract /// -/// The product of fixed-point elements in vector 'c'(eight signed 16-bit integer numbers) -/// by fixed-point elements in vector 'b'(eight signed 16-bit integer numbers) -/// are subtracted from the fixed-point elements in vector 'a' -/// (eight signed 16-bit integer numbers).The multiplication result is not saturated, +/// The product of fixed-point elements in vector `c` (eight signed 16-bit integer numbers) +/// by fixed-point elements in vector `b` (eight signed 16-bit integer numbers) +/// are subtracted from the fixed-point elements in vector `a` +/// (eight signed 16-bit integer numbers). The multiplication result is not saturated, /// i.e. exact (-1) * (-1) = 1 is subtracted from the destination. -/// The saturated fixed-point results are stored back to vector 'a' +/// The saturated fixed-point results are stored back to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6980,12 +6983,12 @@ pub unsafe fn __msa_msub_q_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply and Subtract /// -/// The product of fixed-point elements in vector 'c'(four signed 32-bit integer numbers) -/// by fixed-point elements in vector 'b'(four signed 32-bit integer numbers) -/// are subtracted from the fixed-point elements in vector 'a' -/// (four signed 32-bit integer numbers).The multiplication result is not saturated, +/// The product of fixed-point elements in vector `c` (four signed 32-bit integer numbers) +/// by fixed-point elements in vector `b` (four signed 32-bit integer numbers) +/// are subtracted from the fixed-point elements in vector `a` +/// (four signed 32-bit integer numbers). The multiplication result is not saturated, /// i.e. exact (-1) * (-1) = 1 is subtracted from the destination. -/// The saturated fixed-point results are stored back to vector 'a' +/// The saturated fixed-point results are stored back to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -6996,12 +6999,12 @@ pub unsafe fn __msa_msub_q_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Fixed-Point Multiply and Subtract Rounded /// -/// The product of fixed-point elements in vector 'c'(eight signed 16-bit integer numbers) -/// by fixed-point elements in vector 'b'(eight signed 16-bit integer numbers) -/// are subtracted from the fixed-point elements in vector 'a' -/// (eight signed 16-bit integer numbers).The multiplication result is not saturated, +/// The product of fixed-point elements in vector `c` (eight signed 16-bit integer numbers) +/// by fixed-point elements in vector `b` (eight signed 16-bit integer numbers) +/// are subtracted from the fixed-point elements in vector `a` +/// (eight signed 16-bit integer numbers). The multiplication result is not saturated, /// i.e. exact (-1) * (-1) = 1 is subtracted from the destination. -/// The rounded and saturated fixed-point results are stored back to vector 'a' +/// The rounded and saturated fixed-point results are stored back to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -7012,12 +7015,12 @@ pub unsafe fn __msa_msubr_q_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply and Subtract Rounded /// -/// The product of fixed-point elements in vector 'c'(four signed 32-bit integer numbers) -/// by fixed-point elements in vector 'b'(four signed 32-bit integer numbers) -/// are subtracted from the fixed-point elements in vector 'a' -/// (four signed 32-bit integer numbers).The multiplication result is not saturated, +/// The product of fixed-point elements in vector `c` (four signed 32-bit integer numbers) +/// by fixed-point elements in vector `b` (four signed 32-bit integer numbers) +/// are subtracted from the fixed-point elements in vector `a` +/// (four signed 32-bit integer numbers). The multiplication result is not saturated, /// i.e. exact (-1) * (-1) = 1 is subtracted from the destination. -/// The rounded and saturated fixed-point results are stored back to vector 'a' +/// The rounded and saturated fixed-point results are stored back to vector `a`. /// #[inline] #[target_feature(enable = "msa")] @@ -7028,9 +7031,9 @@ pub unsafe fn __msa_msubr_q_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Multiply and Subtract /// -/// The integer elements in vector 'c'(sixteen signed 8-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(sixteen signed 8-bit integer numbers) -/// and subtracted from the integer elements in vector 'a'(sixteen signed 8-bit integer numbers) +/// The integer elements in vector `c` (sixteen signed 8-bit integer numbers) +/// are multiplied by integer elements in vector `b` (sixteen signed 8-bit integer numbers) +/// and subtracted from the integer elements in vector `a` (sixteen signed 8-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7042,9 +7045,9 @@ pub unsafe fn __msa_msubv_b(a: v16i8, b: v16i8, c: v16i8) -> v16i8 { /// Vector Multiply and Subtract /// -/// The integer elements in vector 'c'(eight signed 16-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(eight signed 16-bit integer numbers) -/// and subtracted from the integer elements in vector 'a'(eight signed 16-bit integer numbers) +/// The integer elements in vector `c` (eight signed 16-bit integer numbers) +/// are multiplied by integer elements in vector `b` (eight signed 16-bit integer numbers) +/// and subtracted from the integer elements in vector `a` (eight signed 16-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7056,9 +7059,9 @@ pub unsafe fn __msa_msubv_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Multiply and Subtract /// -/// The integer elements in vector 'c'(four signed 32-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(four signed 32-bit integer numbers) -/// and subtracted from the integer elements in vector 'a'(four signed 32-bit integer numbers) +/// The integer elements in vector `c` (four signed 32-bit integer numbers) +/// are multiplied by integer elements in vector `b` (four signed 32-bit integer numbers) +/// and subtracted from the integer elements in vector `a` (four signed 32-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7070,9 +7073,9 @@ pub unsafe fn __msa_msubv_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Multiply and Subtract /// -/// The integer elements in vector 'c'(two signed 64-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(two signed 64-bit integer numbers) -/// and subtracted from the integer elements in vector 'a'(two signed 64-bit integer numbers) +/// The integer elements in vector `c` (two signed 64-bit integer numbers) +/// are multiplied by integer elements in vector `b` (two signed 64-bit integer numbers) +/// and subtracted from the integer elements in vector `a` (two signed 64-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7084,9 +7087,9 @@ pub unsafe fn __msa_msubv_d(a: v2i64, b: v2i64, c: v2i64) -> v2i64 { /// Vector Fixed-Point Multiply /// -/// The fixed-point elements in vector 'a'(eight signed 16-bit integer numbers) -/// multiplied by fixed-point elements in vector 'b'(eight signed 16-bit integer numbers) -/// The result is written to vector (eight signed 16-bit integer numbers) +/// The fixed-point elements in vector `a` (eight signed 16-bit integer numbers) +/// multiplied by fixed-point elements in vector `b` (eight signed 16-bit integer numbers). +/// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7097,9 +7100,9 @@ pub unsafe fn __msa_mul_q_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply /// -/// The fixed-point elements in vector 'a'(four signed 32-bit integer numbers) -/// multiplied by fixed-point elements in vector 'b'(four signed 32-bit integer numbers) -/// The result is written to vector (four signed 32-bit integer numbers) +/// The fixed-point elements in vector `a` (four signed 32-bit integer numbers) +/// multiplied by fixed-point elements in vector `b` (four signed 32-bit integer numbers). +/// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7110,9 +7113,9 @@ pub unsafe fn __msa_mul_q_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Fixed-Point Multiply Rounded /// -/// The fixed-point elements in vector 'a'(eight signed 16-bit integer numbers) -/// multiplied by fixed-point elements in vector 'b'(eight signed 16-bit integer numbers) -/// The rounded result is written to vector (eight signed 16-bit integer numbers) +/// The fixed-point elements in vector `a` (eight signed 16-bit integer numbers) +/// multiplied by fixed-point elements in vector `b` (eight signed 16-bit integer numbers). +/// The rounded result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7123,9 +7126,9 @@ pub unsafe fn __msa_mulr_q_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Fixed-Point Multiply Rounded /// -/// The fixed-point elements in vector 'a'(four signed 32-bit integer numbers) -/// multiplied by fixed-point elements in vector 'b'(four signed 32-bit integer numbers) -/// The rounded result is written to vector (four signed 32-bit integer numbers) +/// The fixed-point elements in vector `a` (four signed 32-bit integer numbers) +/// multiplied by fixed-point elements in vector `b` (four signed 32-bit integer numbers). +/// The rounded result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7136,9 +7139,9 @@ pub unsafe fn __msa_mulr_q_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Multiply /// -/// The integer elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(sixteen signed 8-bit integer numbers) -/// The result is written to vector (sixteen signed 8-bit integer numbers) +/// The integer elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are multiplied by integer elements in vector `b` (sixteen signed 8-bit integer numbers). +/// The result is written to vector (sixteen signed 8-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7150,9 +7153,9 @@ pub unsafe fn __msa_mulv_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Multiply /// -/// The integer elements in vector 'a'(eight signed 16-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(eight signed 16-bit integer numbers) -/// The result is written to vector (eight signed 16-bit integer numbers) +/// The integer elements in vector `a` (eight signed 16-bit integer numbers) +/// are multiplied by integer elements in vector `b` (eight signed 16-bit integer numbers). +/// The result is written to vector (eight signed 16-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7164,9 +7167,9 @@ pub unsafe fn __msa_mulv_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Multiply /// -/// The integer elements in vector 'a'(four signed 32-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(four signed 32-bit integer numbers) -/// The result is written to vector (four signed 32-bit integer numbers) +/// The integer elements in vector `a` (four signed 32-bit integer numbers) +/// are multiplied by integer elements in vector `b` (four signed 32-bit integer numbers). +/// The result is written to vector (four signed 32-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7178,9 +7181,9 @@ pub unsafe fn __msa_mulv_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Multiply /// -/// The integer elements in vector 'a'(two signed 64-bit integer numbers) -/// are multiplied by integer elements in vector 'b'(two signed 64-bit integer numbers) -/// The result is written to vector (two signed 64-bit integer numbers) +/// The integer elements in vector `a` (two signed 64-bit integer numbers) +/// are multiplied by integer elements in vector `b` (two signed 64-bit integer numbers). +/// The result is written to vector (two signed 64-bit integer numbers). /// The most significant half of the multiplication result is discarded. /// #[inline] @@ -7192,8 +7195,8 @@ pub unsafe fn __msa_mulv_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Leading Ones Count /// -/// The number of leading ones for elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// is stored to the elements in vector (sixteen signed 8-bit integer numbers) +/// The number of leading ones for elements in vector `a` (sixteen signed 8-bit integer numbers) +/// is stored to the elements in vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7204,8 +7207,8 @@ pub unsafe fn __msa_nloc_b(a: v16i8) -> v16i8 { /// Vector Leading Ones Count /// -/// The number of leading ones for elements in vector 'a'(eight signed 16-bit integer numbers) -/// is stored to the elements in vector (eight signed 16-bit integer numbers) +/// The number of leading ones for elements in vector `a` (eight signed 16-bit integer numbers) +/// is stored to the elements in vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7216,8 +7219,8 @@ pub unsafe fn __msa_nloc_h(a: v8i16) -> v8i16 { /// Vector Leading Ones Count /// -/// The number of leading ones for elements in vector 'a'(four signed 32-bit integer numbers) -/// is stored to the elements in vector (four signed 32-bit integer numbers) +/// The number of leading ones for elements in vector `a` (four signed 32-bit integer numbers) +/// is stored to the elements in vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7228,8 +7231,8 @@ pub unsafe fn __msa_nloc_w(a: v4i32) -> v4i32 { /// Vector Leading Ones Count /// -/// The number of leading ones for elements in vector 'a'(two signed 64-bit integer numbers) -/// is stored to the elements in vector (two signed 64-bit integer numbers) +/// The number of leading ones for elements in vector `a` (two signed 64-bit integer numbers) +/// is stored to the elements in vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7240,8 +7243,8 @@ pub unsafe fn __msa_nloc_d(a: v2i64) -> v2i64 { /// Vector Leading Zeros Count /// -/// The number of leading zeros for elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// is stored to the elements in vector (sixteen signed 8-bit integer numbers) +/// The number of leading zeros for elements in vector `a` (sixteen signed 8-bit integer numbers) +/// is stored to the elements in vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7252,8 +7255,8 @@ pub unsafe fn __msa_nlzc_b(a: v16i8) -> v16i8 { /// Vector Leading Zeros Count /// -/// The number of leading zeros for elements in vector 'a'(eight signed 16-bit integer numbers) -/// is stored to the elements in vector (eight signed 16-bit integer numbers) +/// The number of leading zeros for elements in vector `a` (eight signed 16-bit integer numbers) +/// is stored to the elements in vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7264,8 +7267,8 @@ pub unsafe fn __msa_nlzc_h(a: v8i16) -> v8i16 { /// Vector Leading Zeros Count /// -/// The number of leading zeros for elements in vector 'a'(four signed 32-bit integer numbers) -/// is stored to the elements in vector (four signed 32-bit integer numbers) +/// The number of leading zeros for elements in vector `a` (four signed 32-bit integer numbers) +/// is stored to the elements in vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7276,8 +7279,8 @@ pub unsafe fn __msa_nlzc_w(a: v4i32) -> v4i32 { /// Vector Leading Zeros Count /// -/// The number of leading zeros for elements in vector 'a'(two signed 64-bit integer numbers) -/// is stored to the elements in vector (two signed 64-bit integer numbers) +/// The number of leading zeros for elements in vector `a` (two signed 64-bit integer numbers) +/// is stored to the elements in vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7288,10 +7291,10 @@ pub unsafe fn __msa_nlzc_d(a: v2i64) -> v2i64 { /// Vector Logical Negated Or /// -/// Each bit of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the corresponding bit of vector 'b' (sixteen unsigned 8-bit integer numbers) +/// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the corresponding bit of vector `b` (sixteen unsigned 8-bit integer numbers) /// in a bitwise logical NOR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7302,10 +7305,10 @@ pub unsafe fn __msa_nor_v(a: v16u8, b: v16u8) -> v16u8 { /// Immediate Logical Negated Or /// -/// Each bit of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the 8-bit immediate imm8 +/// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the 8-bit immediate `imm8` /// in a bitwise logical NOR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7322,10 +7325,10 @@ pub unsafe fn __msa_nori_b(a: v16u8, imm8: i32) -> v16u8 { /// Vector Logical Or /// -/// Each bit of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the corresponding bit of vector 'b' (sixteen unsigned 8-bit integer numbers) +/// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the corresponding bit of vector `b` (sixteen unsigned 8-bit integer numbers) /// in a bitwise logical OR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7336,10 +7339,10 @@ pub unsafe fn __msa_or_v(a: v16u8, b: v16u8) -> v16u8 { /// Immediate Logical Or /// -/// Each bit of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the 8-bit immediate imm8 +/// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the 8-bit immediate `imm8` /// in a bitwise logical OR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7356,8 +7359,8 @@ pub unsafe fn __msa_ori_b(a: v16u8, imm8: i32) -> v16u8 { /// Vector Pack Even /// -/// Even elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// are copied to the left half of the result vector and even elements in vector 'b' +/// Even elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// are copied to the left half of the result vector and even elements in vector `b` /// (sixteen signed 8-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7369,8 +7372,8 @@ pub unsafe fn __msa_pckev_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Pack Even /// -/// Even elements in vectors 'a' (eight signed 16-bit integer numbers) -/// are copied to the left half of the result vector and even elements in vector 'b' +/// Even elements in vectors `a` (eight signed 16-bit integer numbers) +/// are copied to the left half of the result vector and even elements in vector `b` /// (eight signed 16-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7382,8 +7385,8 @@ pub unsafe fn __msa_pckev_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Pack Even /// -/// Even elements in vectors 'a' (four signed 32-bit integer numbers) -/// are copied to the left half of the result vector and even elements in vector 'b' +/// Even elements in vectors `a` (four signed 32-bit integer numbers) +/// are copied to the left half of the result vector and even elements in vector `b` /// (four signed 32-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7395,8 +7398,8 @@ pub unsafe fn __msa_pckev_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Pack Even /// -/// Even elements in vectors 'a' (two signed 64-bit integer numbers) -/// are copied to the left half of the result vector and even elements in vector 'b' +/// Even elements in vectors `a` (two signed 64-bit integer numbers) +/// are copied to the left half of the result vector and even elements in vector `b` /// (two signed 64-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7408,8 +7411,8 @@ pub unsafe fn __msa_pckev_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Pack Odd /// -/// Odd elements in vectors 'a' (sixteen signed 8-bit integer numbers) -/// are copied to the left half of the result vector and odd elements in vector 'b' +/// Odd elements in vectors `a` (sixteen signed 8-bit integer numbers) +/// are copied to the left half of the result vector and odd elements in vector `b` /// (sixteen signed 8-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7421,8 +7424,8 @@ pub unsafe fn __msa_pckod_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Pack Odd /// -/// Odd elements in vectors 'a' (eight signed 16-bit integer numbers) -/// are copied to the left half of the result vector and odd elements in vector 'b' +/// Odd elements in vectors `a` (eight signed 16-bit integer numbers) +/// are copied to the left half of the result vector and odd elements in vector `b` /// (eight signed 16-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7434,8 +7437,8 @@ pub unsafe fn __msa_pckod_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Pack Odd /// -/// Odd elements in vectors 'a' (four signed 32-bit integer numbers) -/// are copied to the left half of the result vector and odd elements in vector 'b' +/// Odd elements in vectors `a` (four signed 32-bit integer numbers) +/// are copied to the left half of the result vector and odd elements in vector `b` /// (four signed 32-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7447,8 +7450,8 @@ pub unsafe fn __msa_pckod_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Pack Odd /// -/// Odd elements in vectors 'a' (two signed 64-bit integer numbers) -/// are copied to the left half of the result vector and odd elements in vector 'b' +/// Odd elements in vectors `a` (two signed 64-bit integer numbers) +/// are copied to the left half of the result vector and odd elements in vector `b` /// (two signed 64-bit integer numbers) are copied to the right half of the result vector. /// #[inline] @@ -7460,8 +7463,8 @@ pub unsafe fn __msa_pckod_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Population Count /// -/// The number of bits set to 1 for elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// is stored to the elements in the result vector (sixteen signed 8-bit integer numbers) +/// The number of bits set to 1 for elements in vector `a` (sixteen signed 8-bit integer numbers) +/// is stored to the elements in the result vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7472,8 +7475,8 @@ pub unsafe fn __msa_pcnt_b(a: v16i8) -> v16i8 { /// Vector Population Count /// -/// The number of bits set to 1 for elements in vector 'a' (eight signed 16-bit integer numbers) -/// is stored to the elements in the result vector (eight signed 16-bit integer numbers) +/// The number of bits set to 1 for elements in vector `a` (eight signed 16-bit integer numbers) +/// is stored to the elements in the result vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7484,8 +7487,8 @@ pub unsafe fn __msa_pcnt_h(a: v8i16) -> v8i16 { /// Vector Population Count /// -/// The number of bits set to 1 for elements in vector 'a' (four signed 32-bit integer numbers) -/// is stored to the elements in the result vector (four signed 32-bit integer numbers) +/// The number of bits set to 1 for elements in vector `a` (four signed 32-bit integer numbers) +/// is stored to the elements in the result vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7496,8 +7499,8 @@ pub unsafe fn __msa_pcnt_w(a: v4i32) -> v4i32 { /// Vector Population Count /// -/// The number of bits set to 1 for elements in vector 'a' (two signed 64-bit integer numbers) -/// is stored to the elements in the result vector (two signed 64-bit integer numbers) +/// The number of bits set to 1 for elements in vector `a` (two signed 64-bit integer numbers) +/// is stored to the elements in the result vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7508,9 +7511,9 @@ pub unsafe fn __msa_pcnt_d(a: v2i64) -> v2i64 { /// Immediate Signed Saturate /// -/// Signed elements in vector 'a' (sixteen signed 8-bit integer numbers) -/// are saturated to signed values of imm3+1 bits without changing the data width -/// The result is stored in the vector (sixteen signed 8-bit integer numbers) +/// Signed elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are saturated to signed values of `imm3+1` bits without changing the data width. +/// The result is stored in the vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7527,9 +7530,9 @@ pub unsafe fn __msa_sat_s_b(a: v16i8, imm3: i32) -> v16i8 { /// Immediate Signed Saturate /// -/// Signed elements in vector 'a' (eight signed 16-bit integer numbers) -/// are saturated to signed values of imm4+1 bits without changing the data width -/// The result is stored in the vector (eight signed 16-bit integer numbers) +/// Signed elements in vector `a` (eight signed 16-bit integer numbers) +/// are saturated to signed values of `imm4+1` bits without changing the data width. +/// The result is stored in the vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7546,9 +7549,9 @@ pub unsafe fn __msa_sat_s_h(a: v8i16, imm4: i32) -> v8i16 { /// Immediate Signed Saturate /// -/// Signed elements in vector 'a' (four signed 32-bit integer numbers) -/// are saturated to signed values of imm5+1 bits without changing the data width -/// The result is stored in the vector (four signed 32-bit integer numbers) +/// Signed elements in vector `a` (four signed 32-bit integer numbers) +/// are saturated to signed values of `imm5+1` bits without changing the data width. +/// The result is stored in the vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7565,9 +7568,9 @@ pub unsafe fn __msa_sat_s_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Signed Saturate /// -/// Signed elements in vector 'a' (two signed 64-bit integer numbers) -/// are saturated to signed values of imm6+1 bits without changing the data width -/// The result is stored in the vector (two signed 64-bit integer numbers) +/// Signed elements in vector `a` (two signed 64-bit integer numbers) +/// are saturated to signed values of `imm6+1` bits without changing the data width. +/// The result is stored in the vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7584,9 +7587,9 @@ pub unsafe fn __msa_sat_s_d(a: v2i64, imm6: i32) -> v2i64 { /// Immediate Unsigned Saturate /// -/// Unsigned elements in vector 'a' (sixteen unsigned 8-bit integer numbers) -/// are saturated to unsigned values of imm3+1 bits without changing the data width -/// The result is stored in the vector (sixteen unsigned 8-bit integer numbers) +/// Unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are saturated to unsigned values of `imm3+1` bits without changing the data width. +/// The result is stored in the vector (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7603,9 +7606,9 @@ pub unsafe fn __msa_sat_u_b(a: v16u8, imm3: i32) -> v16u8 { /// Immediate Unsigned Saturate /// -/// Unsigned elements in vector 'a' (eight unsigned 16-bit integer numbers) -/// are saturated to unsigned values of imm4+1 bits without changing the data width -/// The result is stored in the vector (eight unsigned 16-bit integer numbers) +/// Unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are saturated to unsigned values of `imm4+1` bits without changing the data width. +/// The result is stored in the vector (eight unsigned 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7622,9 +7625,9 @@ pub unsafe fn __msa_sat_u_h(a: v8u16, imm4: i32) -> v8u16 { /// Immediate Unsigned Saturate /// -/// Unsigned elements in vector 'a' (four unsigned 32-bit integer numbers) -/// are saturated to unsigned values of imm5+1 bits without changing the data width -/// The result is stored in the vector (four unsigned 32-bit integer numbers) +/// Unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// are saturated to unsigned values of `imm5+1` bits without changing the data width. +/// The result is stored in the vector (four unsigned 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7641,9 +7644,9 @@ pub unsafe fn __msa_sat_u_w(a: v4u32, imm5: i32) -> v4u32 { /// Immediate Unsigned Saturate /// -/// Unsigned elements in vector 'a' (two unsigned 64-bit integer numbers) -/// are saturated to unsigned values of imm6+1 bits without changing the data width -/// The result is stored in the vector (two unsigned 64-bit integer numbers) +/// Unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// are saturated to unsigned values of `imm6+1` bits without changing the data width. +/// The result is stored in the vector (two unsigned 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7661,7 +7664,7 @@ pub unsafe fn __msa_sat_u_d(a: v2u64, imm6: i32) -> v2u64 { /// Immediate Set Shuffle Elements /// /// The set shuffle instruction works on 4-element sets. -/// All sets are shuffled in the same way: the element i82i+1..2i in 'a' +/// All sets are shuffled in the same way: the element i82i+1..2i in `a` /// (sixteen signed 8-bit integer numbers) is copied over the element i in result vector /// (sixteen signed 8-bit integer numbers), where i is 0, 1, 2, 3. /// @@ -7681,7 +7684,7 @@ pub unsafe fn __msa_shf_b(a: v16i8, imm8: i32) -> v16i8 { /// Immediate Set Shuffle Elements /// /// The set shuffle instruction works on 4-element sets. -/// All sets are shuffled in the same way: the element i82i+1..2i in 'a' +/// All sets are shuffled in the same way: the element i82i+1..2i in `a` /// (eight signed 16-bit integer numbers) is copied over the element i in result vector /// (eight signed 16-bit integer numbers), where i is 0, 1, 2, 3. /// @@ -7701,7 +7704,7 @@ pub unsafe fn __msa_shf_h(a: v8i16, imm8: i32) -> v8i16 { /// Immediate Set Shuffle Elements /// /// The set shuffle instruction works on 4-element sets. -/// All sets are shuffled in the same way: the element i82i+1..2i in 'a' +/// All sets are shuffled in the same way: the element i82i+1..2i in `a` /// (four signed 32-bit integer numbers) is copied over the element i in result vector /// (four signed 32-bit integer numbers), where i is 0, 1, 2, 3. /// @@ -7720,15 +7723,15 @@ pub unsafe fn __msa_shf_w(a: v4i32, imm8: i32) -> v4i32 { /// GPR Columns Slide /// -/// Vector registers 'a' (sixteen signed 8-bit integer numbers) and 'b' +/// Vector registers `a` (sixteen signed 8-bit integer numbers) and `b` /// (sixteen signed 8-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by the number of columns given in GPR 'c'. +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by the number of columns given in GPR `c`. /// The result is written to vector (sixteen signed 8-bit integer numbers). -/// GPR 'c' value is interpreted modulo the number of columns in destination rectangle, +/// GPR `c` value is interpreted modulo the number of columns in destination rectangle, /// or equivalently, the number of data format df elements in the destination vector. /// #[inline] @@ -7740,15 +7743,15 @@ pub unsafe fn __msa_sld_b(a: v16i8, b: v16i8, c: i32) -> v16i8 { /// GPR Columns Slide /// -/// Vector registers 'a' (eight signed 16-bit integer numbers) and 'b' +/// Vector registers `a` (eight signed 16-bit integer numbers) and `b` /// (eight signed 16-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by the number of columns given in GPR 'c'. +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by the number of columns given in GPR `c`. /// The result is written to vector (eight signed 16-bit integer numbers). -/// GPR 'c' value is interpreted modulo the number of columns in destination rectangle, +/// GPR `c` value is interpreted modulo the number of columns in destination rectangle, /// or equivalently, the number of data format df elements in the destination vector. /// #[inline] @@ -7760,15 +7763,15 @@ pub unsafe fn __msa_sld_h(a: v8i16, b: v8i16, c: i32) -> v8i16 { /// GPR Columns Slide /// -/// Vector registers 'a' (four signed 32-bit integer numbers) and 'b' +/// Vector registers `a` (four signed 32-bit integer numbers) and `b` /// (four signed 32-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by the number of columns given in GPR 'c'. +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by the number of columns given in GPR `c`. /// The result is written to vector (four signed 32-bit integer numbers). -/// GPR 'c' value is interpreted modulo the number of columns in destination rectangle, +/// GPR `c` value is interpreted modulo the number of columns in destination rectangle, /// or equivalently, the number of data format df elements in the destination vector. /// #[inline] @@ -7780,15 +7783,15 @@ pub unsafe fn __msa_sld_w(a: v4i32, b: v4i32, c: i32) -> v4i32 { /// GPR Columns Slide /// -/// Vector registers 'a' (two signed 64-bit integer numbers) and 'b' +/// Vector registers `a` (two signed 64-bit integer numbers) and `b` /// (two signed 64-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by the number of columns given in GPR 'c'. +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by the number of columns given in GPR `c`. /// The result is written to vector (two signed 64-bit integer numbers). -/// GPR 'c' value is interpreted modulo the number of columns in destination rectangle, +/// GPR `c` value is interpreted modulo the number of columns in destination rectangle, /// or equivalently, the number of data format df elements in the destination vector. /// #[inline] @@ -7800,13 +7803,13 @@ pub unsafe fn __msa_sld_d(a: v2i64, b: v2i64, c: i32) -> v2i64 { /// Immediate Columns Slide /// -/// Vector registers 'a' (sixteen signed 8-bit integer numbers) and 'b' +/// Vector registers `a` (sixteen signed 8-bit integer numbers) and `b` /// (sixteen signed 8-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by imm1 columns +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by `imm1` columns. /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -7824,13 +7827,13 @@ pub unsafe fn __msa_sldi_b(a: v16i8, b: v16i8, imm4: i32) -> v16i8 { /// Immediate Columns Slide /// -/// Vector registers 'a' (eight signed 16-bit integer numbers) and 'b' +/// Vector registers `a` (eight signed 16-bit integer numbers) and `b` /// (eight signed 16-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by imm1 columns +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by `imm1` columns. /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -7848,13 +7851,13 @@ pub unsafe fn __msa_sldi_h(a: v8i16, b: v8i16, imm3: i32) -> v8i16 { /// Immediate Columns Slide /// -/// Vector registers 'a' (four signed 32-bit integer numbers) and 'b' +/// Vector registers `a` (four signed 32-bit integer numbers) and `b` /// (four signed 32-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by imm1 columns +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by `imm1` columns. /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -7872,13 +7875,13 @@ pub unsafe fn __msa_sldi_w(a: v4i32, b: v4i32, imm2: i32) -> v4i32 { /// Immediate Columns Slide /// -/// Vector registers 'a' (two signed 64-bit integer numbers) and 'b' +/// Vector registers `a` (two signed 64-bit integer numbers) and `b` /// (two signed 64-bit integer numbers) contain 2-dimensional byte arrays (rectangles) -/// stored row-wise with as many rows asbytes in integer data format df. -/// The two source rectangles 'b' and 'a' are concatenated horizontally in the order -/// they appear in the syntax, i.e. first 'a' and then 'b'. Place a new destination -/// rectangle over 'b' and then slide it to the left over the concatenation of 'a' and 'b' -/// by imm1 columns +/// stored row-wise with as many rows as bytes in integer data format df. +/// The two source rectangles `b` and `a` are concatenated horizontally in the order +/// they appear in the syntax, i.e. first `a` and then `b`. Place a new destination +/// rectangle over `b` and then slide it to the left over the concatenation of `a` and `b` +/// by `imm1` columns. /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -7896,10 +7899,10 @@ pub unsafe fn __msa_sldi_d(a: v2i64, b: v2i64, imm1: i32) -> v2i64 { /// Vector Shift Left /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted left by the number of bits the elements in vector 'b' +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted left by the number of bits the elements in vector `b` /// (sixteen signed 8-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector (sixteen signed 8-bit integer numbers). +/// element in bits. The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7910,10 +7913,10 @@ pub unsafe fn __msa_sll_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Shift Left /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted left by the number of bits the elements in vector 'b' +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted left by the number of bits the elements in vector `b` /// (eight signed 16-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector (eight signed 16-bit integer numbers). +/// element in bits. The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7924,10 +7927,10 @@ pub unsafe fn __msa_sll_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Shift Left /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted left by the number of bits the elements in vector 'b' +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted left by the number of bits the elements in vector `b` /// (four signed 32-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector (four signed 32-bit integer numbers). +/// element in bits. The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7938,10 +7941,10 @@ pub unsafe fn __msa_sll_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Shift Left /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted left by the number of bits the elements in vector 'b' +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted left by the number of bits the elements in vector `b` /// (two signed 64-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(two signed 64-bit integer numbers). +/// element in bits. The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7952,9 +7955,9 @@ pub unsafe fn __msa_sll_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Shift Left /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted left by the imm4 bits. -/// The result is written to vector(sixteen signed 8-bit integer numbers). +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted left by `imm4` bits. +/// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7971,9 +7974,9 @@ pub unsafe fn __msa_slli_b(a: v16i8, imm4: i32) -> v16i8 { /// Immediate Shift Left /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted left by the imm3 bits. -/// The result is written to vector(eight signed 16-bit integer numbers). +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted left by `imm3` bits. +/// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -7990,9 +7993,9 @@ pub unsafe fn __msa_slli_h(a: v8i16, imm3: i32) -> v8i16 { /// Immediate Shift Left /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted left by the imm2 bits. -/// The result is written to vector(four signed 32-bit integer numbers). +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted left by `imm2` bits. +/// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8009,9 +8012,9 @@ pub unsafe fn __msa_slli_w(a: v4i32, imm2: i32) -> v4i32 { /// Immediate Shift Left /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted left by the imm1 bits. -/// The result is written to vector(two signed 64-bit integer numbers). +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted left by `imm1` bits. +/// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8028,9 +8031,9 @@ pub unsafe fn __msa_slli_d(a: v2i64, imm1: i32) -> v2i64 { /// GPR Element Splat /// -/// Replicate vector 'a'(sixteen signed 8-bit integer numbers) -/// element with index given by GPR 'b' to all elements in vector -/// (sixteen signed 8-bit integer numbers) GPR 'b' value is interpreted +/// Replicate vector `a` (sixteen signed 8-bit integer numbers) +/// element with index given by GPR `b` to all elements in vector +/// (sixteen signed 8-bit integer numbers) GPR `b` value is interpreted /// modulo the number of data format df elements in the destination vector. /// #[inline] @@ -8042,9 +8045,9 @@ pub unsafe fn __msa_splat_b(a: v16i8, b: i32) -> v16i8 { /// GPR Element Splat /// -/// Replicate vector 'a'(eight signed 16-bit integer numbers) -/// element with index given by GPR 'b' to all elements in vector -/// (eight signed 16-bit integer numbers) GPR 'b' value is interpreted +/// Replicate vector `a` (eight signed 16-bit integer numbers) +/// element with index given by GPR `b` to all elements in vector +/// (eight signed 16-bit integer numbers) GPR `b` value is interpreted /// modulo the number of data format df elements in the destination vector. /// #[inline] @@ -8056,9 +8059,9 @@ pub unsafe fn __msa_splat_h(a: v8i16, b: i32) -> v8i16 { /// GPR Element Splat /// -/// Replicate vector 'a'(four signed 32-bit integer numbers) -/// element with index given by GPR 'b' to all elements in vector -/// (four signed 32-bit integer numbers) GPR 'b' value is interpreted +/// Replicate vector `a` (four signed 32-bit integer numbers) +/// element with index given by GPR `b` to all elements in vector +/// (four signed 32-bit integer numbers) GPR `b` value is interpreted /// modulo the number of data format df elements in the destination vector. /// #[inline] @@ -8070,9 +8073,9 @@ pub unsafe fn __msa_splat_w(a: v4i32, b: i32) -> v4i32 { /// GPR Element Splat /// -/// Replicate vector 'a'(two signed 64-bit integer numbers) -/// element with index given by GPR 'b' to all elements in vector -/// (two signed 64-bit integer numbers) GPR 'b' value is interpreted +/// Replicate vector `a` (two signed 64-bit integer numbers) +/// element with index given by GPR `b` to all elements in vector +/// (two signed 64-bit integer numbers) GPR `b` value is interpreted /// modulo the number of data format df elements in the destination vector. /// #[inline] @@ -8084,7 +8087,7 @@ pub unsafe fn __msa_splat_d(a: v2i64, b: i32) -> v2i64 { /// Immediate Element Splat /// -/// Replicate element imm4 in vector 'a'(sixteen signed 8-bit integer numbers) +/// Replicate element `imm4` in vector `a` (sixteen signed 8-bit integer numbers) /// to all elements in vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -8102,7 +8105,7 @@ pub unsafe fn __msa_splati_b(a: v16i8, imm4: i32) -> v16i8 { /// Immediate Element Splat /// -/// Replicate element imm3 in vector 'a'(eight signed 16-bit integer numbers) +/// Replicate element `imm3` in vector `a` (eight signed 16-bit integer numbers) /// to all elements in vector (eight signed 16-bit integer numbers). /// #[inline] @@ -8120,7 +8123,7 @@ pub unsafe fn __msa_splati_h(a: v8i16, imm3: i32) -> v8i16 { /// Immediate Element Splat /// -/// Replicate element imm2 in vector 'a'(four signed 32-bit integer numbers) +/// Replicate element `imm2` in vector `a` (four signed 32-bit integer numbers) /// to all elements in vector (four signed 32-bit integer numbers). /// #[inline] @@ -8138,7 +8141,7 @@ pub unsafe fn __msa_splati_w(a: v4i32, imm2: i32) -> v4i32 { /// Immediate Element Splat /// -/// Replicate element imm1 in vector 'a'(two signed 64-bit integer numbers) +/// Replicate element `imm1` in vector `a` (two signed 64-bit integer numbers) /// to all elements in vector (two signed 64-bit integer numbers). /// #[inline] @@ -8156,10 +8159,10 @@ pub unsafe fn __msa_splati_d(a: v2i64, imm1: i32) -> v2i64 { /// Vector Shift Right Arithmetic /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (sixteen signed 8-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(sixteen signed 8-bit integer numbers). +/// element in bits.The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8170,10 +8173,10 @@ pub unsafe fn __msa_sra_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Shift Right Arithmetic /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (eight signed 16-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(eight signed 16-bit integer numbers). +/// element in bits.The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8184,10 +8187,10 @@ pub unsafe fn __msa_sra_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Shift Right Arithmetic /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (four signed 32-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(four signed 32-bit integer numbers). +/// element in bits.The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8198,10 +8201,10 @@ pub unsafe fn __msa_sra_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Shift Right Arithmetic /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (two signed 64-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(two signed 64-bit integer numbers). +/// element in bits.The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8212,9 +8215,9 @@ pub unsafe fn __msa_sra_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Shift Right Arithmetic /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right arithmetic by imm3 bits. -/// The result is written to vector(sixteen signed 8-bit integer numbers). +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right arithmetic by `imm3` bits. +/// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8231,9 +8234,9 @@ pub unsafe fn __msa_srai_b(a: v16i8, imm3: i32) -> v16i8 { /// Immediate Shift Right Arithmetic /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right arithmetic by imm4 bits. -/// The result is written to vector(eight signed 16-bit integer numbers). +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right arithmetic by `imm4` bits. +/// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8250,9 +8253,9 @@ pub unsafe fn __msa_srai_h(a: v8i16, imm4: i32) -> v8i16 { /// Immediate Shift Right Arithmetic /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right arithmetic by imm5 bits. -/// The result is written to vector(four signed 32-bit integer numbers). +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right arithmetic by `imm5` bits. +/// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8269,9 +8272,9 @@ pub unsafe fn __msa_srai_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Shift Right Arithmetic /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right arithmetic by imm6 bits. -/// The result is written to vector(two signed 64-bit integer numbers). +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right arithmetic by `imm6` bits. +/// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8288,11 +8291,11 @@ pub unsafe fn __msa_srai_d(a: v2i64, imm6: i32) -> v2i64 { /// Vector Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (sixteen signed 8-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(sixteen signed 8-bit integer numbers). +/// value (for rounding) and the result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8303,11 +8306,11 @@ pub unsafe fn __msa_srar_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (eight signed 16-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(eight signed 16-bit integer numbers). +/// value (for rounding) and the result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8318,11 +8321,11 @@ pub unsafe fn __msa_srar_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (four signed 32-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(four signed 32-bit integer numbers). +/// value (for rounding) and the result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8333,11 +8336,11 @@ pub unsafe fn __msa_srar_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right arithmetic by the number of bits the elements in vector 'b' +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right arithmetic by the number of bits the elements in vector `b` /// (two signed 64-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(two signed 64-bit integer numbers). +/// value (for rounding) and the result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8348,10 +8351,10 @@ pub unsafe fn __msa_srar_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right arithmetic by imm3 bits.The most significant +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right arithmetic by `imm3` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(sixteen signed 8-bit integer numbers). +/// the result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8368,10 +8371,10 @@ pub unsafe fn __msa_srari_b(a: v16i8, imm3: i32) -> v16i8 { /// Immediate Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right arithmetic by imm4 bits.The most significant +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right arithmetic by `imm4` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(eight signed 16-bit integer numbers). +/// the result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8388,10 +8391,10 @@ pub unsafe fn __msa_srari_h(a: v8i16, imm4: i32) -> v8i16 { /// Immediate Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right arithmetic by imm5 bits.The most significant +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right arithmetic by `imm5` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(four signed 32-bit integer numbers). +/// the result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8408,10 +8411,10 @@ pub unsafe fn __msa_srari_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Shift Right Arithmetic Rounded /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right arithmetic by imm6 bits.The most significant +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right arithmetic by `imm6` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(two signed 64-bit integer numbers). +/// the result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8428,10 +8431,10 @@ pub unsafe fn __msa_srari_d(a: v2i64, imm6: i32) -> v2i64 { /// Vector Shift Right Logical /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (sixteen signed 8-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(sixteen signed 8-bit integer numbers). +/// element in bits.The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8442,10 +8445,10 @@ pub unsafe fn __msa_srl_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Shift Right Logical /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (eight signed 16-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(eight signed 16-bit integer numbers). +/// element in bits.The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8456,10 +8459,10 @@ pub unsafe fn __msa_srl_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Shift Right Logical /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (four signed 32-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(four signed 32-bit integer numbers). +/// element in bits.The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8470,10 +8473,10 @@ pub unsafe fn __msa_srl_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Shift Right Logical /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (two signed 64-bit integer numbers) specify modulo the size of the -/// element in bits.The result is written to vector(two signed 64-bit integer numbers). +/// element in bits.The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8484,9 +8487,9 @@ pub unsafe fn __msa_srl_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Shift Right Logical /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right logical by imm4 bits. -/// The result is written to vector(sixteen signed 8-bit integer numbers). +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right logical by `imm4` bits. +/// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8503,9 +8506,9 @@ pub unsafe fn __msa_srli_b(a: v16i8, imm4: i32) -> v16i8 { /// Immediate Shift Right Logical /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right logical by imm3 bits. -/// The result is written to vector(eight signed 16-bit integer numbers). +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right logical by `imm3` bits. +/// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8522,9 +8525,9 @@ pub unsafe fn __msa_srli_h(a: v8i16, imm3: i32) -> v8i16 { /// Immediate Shift Right Logical /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right logical by imm2 bits. -/// The result is written to vector(four signed 32-bit integer numbers). +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right logical by `imm2` bits. +/// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8541,9 +8544,9 @@ pub unsafe fn __msa_srli_w(a: v4i32, imm2: i32) -> v4i32 { /// Immediate Shift Right Logical /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right logical by imm1 bits. -/// The result is written to vector(two signed 64-bit integer numbers). +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right logical by `imm1` bits. +/// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8560,11 +8563,11 @@ pub unsafe fn __msa_srli_d(a: v2i64, imm1: i32) -> v2i64 { /// Vector Shift Right Logical Rounded /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (sixteen signed 8-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(sixteen signed 8-bit integer numbers). +/// value (for rounding) and the result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8575,11 +8578,11 @@ pub unsafe fn __msa_srlr_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Shift Right Logical Rounded /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (eight signed 16-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(eight signed 16-bit integer numbers). +/// value (for rounding) and the result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8590,11 +8593,11 @@ pub unsafe fn __msa_srlr_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Shift Right Logical Rounded /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (four signed 32-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(four signed 32-bit integer numbers). +/// value (for rounding) and the result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8605,11 +8608,11 @@ pub unsafe fn __msa_srlr_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Shift Right Logical Rounded /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right logical by the number of bits the elements in vector 'b' +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right logical by the number of bits the elements in vector `b` /// (two signed 64-bit integer numbers) specify modulo the size of the /// element in bits.The most significant discarded bit is added to the shifted -/// value (for rounding) and the result is written to vector(two signed 64-bit integer numbers). +/// value (for rounding) and the result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8620,10 +8623,10 @@ pub unsafe fn __msa_srlr_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Shift Right Logical Rounded /// -/// The elements in vector 'a'(sixteen signed 8-bit integer numbers) -/// are shifted right logical by imm6 bits.The most significant +/// The elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are shifted right logical by `imm6` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(sixteen signed 8-bit integer numbers). +/// the result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8640,10 +8643,10 @@ pub unsafe fn __msa_srlri_b(a: v16i8, imm3: i32) -> v16i8 { /// Immediate Shift Right Logical Rounded /// -/// The elements in vector 'a'(eight signed 16-bit integer numbers) -/// are shifted right logical by imm6 bits.The most significant +/// The elements in vector `a` (eight signed 16-bit integer numbers) +/// are shifted right logical by `imm6` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(eight signed 16-bit integer numbers). +/// the result is written to vector (eight signed 16-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8660,10 +8663,10 @@ pub unsafe fn __msa_srlri_h(a: v8i16, imm4: i32) -> v8i16 { /// Immediate Shift Right Logical Rounded /// -/// The elements in vector 'a'(four signed 32-bit integer numbers) -/// are shifted right logical by imm6 bits.The most significant +/// The elements in vector `a` (four signed 32-bit integer numbers) +/// are shifted right logical by `imm6` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(four signed 32-bit integer numbers). +/// the result is written to vector (four signed 32-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8680,10 +8683,10 @@ pub unsafe fn __msa_srlri_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Shift Right Logical Rounded /// -/// The elements in vector 'a'(two signed 64-bit integer numbers) -/// are shifted right logical by imm6 bits.The most significant +/// The elements in vector `a` (two signed 64-bit integer numbers) +/// are shifted right logical by `imm6` bits.The most significant /// discarded bit is added to the shifted value (for rounding) and -/// the result is written to vector(two signed 64-bit integer numbers). +/// the result is written to vector (two signed 64-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -8700,9 +8703,9 @@ pub unsafe fn __msa_srlri_d(a: v2i64, imm6: i32) -> v2i64 { /// Vector Store /// -/// TheWRLEN / 8 bytes in vector 'a'(sixteen signed 8-bit integer numbers) +/// The WRLEN / 8 bytes in vector `a` (sixteen signed 8-bit integer numbers) /// are stored as elements of data format df at the effective memory location -/// addressed by the base mem_addr and the 10-bit signed immediate offset imm_s10 +/// addressed by the base `mem_addr` and the 10-bit signed immediate offset `imm_s10`. /// #[inline] #[target_feature(enable = "msa")] @@ -8719,9 +8722,9 @@ pub unsafe fn __msa_st_b(a: v16i8, mem_addr: *mut u8, imm_s10: i32) -> () { /// Vector Store /// -/// TheWRLEN / 8 bytes in vector 'a'(eight signed 16-bit integer numbers) +/// The WRLEN / 8 bytes in vector `a` (eight signed 16-bit integer numbers) /// are stored as elements of data format df at the effective memory location -/// addressed by the base mem_addr and the 11-bit signed immediate offset imm_s11 +/// addressed by the base `mem_addr` and the 11-bit signed immediate offset `imm_s11`. /// #[inline] #[target_feature(enable = "msa")] @@ -8738,9 +8741,9 @@ pub unsafe fn __msa_st_h(a: v8i16, mem_addr: *mut u8, imm_s11: i32) -> () { /// Vector Store /// -/// TheWRLEN / 8 bytes in vector 'a'(four signed 32-bit integer numbers) +/// The WRLEN / 8 bytes in vector `a` (four signed 32-bit integer numbers) /// are stored as elements of data format df at the effective memory location -/// addressed by the base mem_addr and the 12-bit signed immediate offset imm_s12 +/// addressed by the base `mem_addr` and the 12-bit signed immediate offset `imm_s12`. /// #[inline] #[target_feature(enable = "msa")] @@ -8757,9 +8760,9 @@ pub unsafe fn __msa_st_w(a: v4i32, mem_addr: *mut u8, imm_s12: i32) -> () { /// Vector Store /// -/// TheWRLEN / 8 bytes in vector 'a'(two signed 64-bit integer numbers) +/// The WRLEN / 8 bytes in vector `a` (two signed 64-bit integer numbers) /// are stored as elements of data format df at the effective memory location -/// addressed by the base mem_addr and the 13-bit signed immediate offset imm_s13 +/// addressed by the base `mem_addr` and the 13-bit signed immediate offset `imm_s13`. /// #[inline] #[target_feature(enable = "msa")] @@ -8777,7 +8780,7 @@ pub unsafe fn __msa_st_d(a: v2i64, mem_addr: *mut u8, imm_s13: i32) -> () { /// Vector Signed Saturated Subtract of Signed Values /// /// The elements in vector `b` (sixteen signed 8-bit integer numbers) -/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (sixteen signed 8-bit integer numbers). /// @@ -8791,7 +8794,7 @@ pub unsafe fn __msa_subs_s_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Signed Saturated Subtract of Signed Values /// /// The elements in vector `b` (eight signed 16-bit integer numbers) -/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers) +/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (eight signed 16-bit integer numbers). /// @@ -8805,7 +8808,7 @@ pub unsafe fn __msa_subs_s_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Signed Saturated Subtract of Signed Values /// /// The elements in vector `b` (four signed 32-bit integer numbers) -/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers) +/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (four signed 32-bit integer numbers). /// @@ -8819,7 +8822,7 @@ pub unsafe fn __msa_subs_s_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Signed Saturated Subtract of Signed Values /// /// The elements in vector `b` (two signed 64-bit integer numbers) -/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers) +/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers). /// Signed arithmetic is performed and overflows clamp to the largest and/or smallest /// representable signed values before writing the result to vector (two signed 64-bit integer numbers). /// @@ -8833,7 +8836,7 @@ pub unsafe fn __msa_subs_s_d(a: v2i64, b: v2i64) -> v2i64 { /// Vector Unsigned Saturated Subtract of Unsigned Values /// /// The elements in vector `b` (sixteen unsigned 8-bit integer numbers) -/// are subtracted from the elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are subtracted from the elements in vector `a` (sixteen unsigned 8-bit integer numbers). /// Unsigned arithmetic is performed and under-flows clamp to 0 before writing /// the result to vector (sixteen unsigned 8-bit integer numbers). /// @@ -8847,7 +8850,7 @@ pub unsafe fn __msa_subs_u_b(a: v16u8, b: v16u8) -> v16u8 { /// Vector Unsigned Saturated Subtract of Unsigned Values /// /// The elements in vector `b` (eight unsigned 16-bit integer numbers) -/// are subtracted from the elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are subtracted from the elements in vector `a` (eight unsigned 16-bit integer numbers). /// Unsigned arithmetic is performed and under-flows clamp to 0 before writing /// the result to vector (eight unsigned 16-bit integer numbers). /// @@ -8861,7 +8864,7 @@ pub unsafe fn __msa_subs_u_h(a: v8u16, b: v8u16) -> v8u16 { /// Vector Unsigned Saturated Subtract of Unsigned Values /// /// The elements in vector `b` (four unsigned 32-bit integer numbers) -/// are subtracted from the elements in vector `a` (four unsigned 32-bit integer numbers) +/// are subtracted from the elements in vector `a` (four unsigned 32-bit integer numbers). /// Unsigned arithmetic is performed and under-flows clamp to 0 before writing /// the result to vector (four unsigned 32-bit integer numbers). /// @@ -8875,7 +8878,7 @@ pub unsafe fn __msa_subs_u_w(a: v4u32, b: v4u32) -> v4u32 { /// Vector Unsigned Saturated Subtract of Unsigned Values /// /// The elements in vector `b` (two unsigned 64-bit integer numbers) -/// are subtracted from the elements in vector `a` (two unsigned 64-bit integer numbers) +/// are subtracted from the elements in vector `a` (two unsigned 64-bit integer numbers). /// Unsigned arithmetic is performed and under-flows clamp to 0 before writing /// the result to vector (two unsigned 64-bit integer numbers). /// @@ -8889,7 +8892,7 @@ pub unsafe fn __msa_subs_u_d(a: v2u64, b: v2u64) -> v2u64 { /// Vector Unsigned Saturated Subtract of Signed from Unsigned /// /// The signed elements in vector `b` (sixteen signed 8-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers). /// The signed result is unsigned saturated and written to /// to vector (sixteen unsigned 8-bit integer numbers). /// @@ -8903,7 +8906,7 @@ pub unsafe fn __msa_subsus_u_b(a: v16u8, b: v16i8) -> v16u8 { /// Vector Unsigned Saturated Subtract of Signed from Unsigned /// /// The signed elements in vector `b` (eight signed 16-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (eight unsigned 16-bit integer numbers). /// The signed result is unsigned saturated and written to /// to vector (eight unsigned 16-bit integer numbers). /// @@ -8917,7 +8920,7 @@ pub unsafe fn __msa_subsus_u_h(a: v8u16, b: v8i16) -> v8u16 { /// Vector Unsigned Saturated Subtract of Signed from Unsigned /// /// The signed elements in vector `b` (four signed 6432it integer numbers) -/// are subtracted from the unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (four unsigned 32-bit integer numbers). /// The signed result is unsigned saturated and written to /// to vector (four unsigned 32-bit integer numbers). /// @@ -8931,7 +8934,7 @@ pub unsafe fn __msa_subsus_u_w(a: v4u32, b: v4i32) -> v4u32 { /// Vector Unsigned Saturated Subtract of Signed from Unsigned /// /// The signed elements in vector `b` (two signed 64-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (two unsigned 64-bit integer numbers). /// The signed result is unsigned saturated and written to /// to vector (two unsigned 64-bit integer numbers). /// @@ -8945,7 +8948,7 @@ pub unsafe fn __msa_subsus_u_d(a: v2u64, b: v2i64) -> v2u64 { /// Vector Signed Saturated Subtract of Unsigned Values /// /// The unsigned elements in vector `b` (sixteen unsigned 8-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (sixteen unsigned 8-bit integer numbers). /// The signed result is signed saturated and written to /// to vector (sixteen unsigned 8-bit integer numbers). /// @@ -8959,7 +8962,7 @@ pub unsafe fn __msa_subsuu_s_b(a: v16u8, b: v16u8) -> v16i8 { /// Vector Signed Saturated Subtract of Unsigned Values /// /// The unsigned elements in vector `b` (eight unsigned 16-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (eight unsigned 16-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (eight unsigned 16-bit integer numbers). /// The signed result is signed saturated and written to /// to vector (eight unsigned 16-bit integer numbers). /// @@ -8973,7 +8976,7 @@ pub unsafe fn __msa_subsuu_s_h(a: v8u16, b: v8u16) -> v8i16 { /// Vector Signed Saturated Subtract of Unsigned Values /// /// The unsigned elements in vector `b` (four unsigned 32-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (four unsigned 32-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (four unsigned 32-bit integer numbers). /// The signed result is signed saturated and written to /// to vector (four unsigned 32-bit integer numbers). /// @@ -8987,7 +8990,7 @@ pub unsafe fn __msa_subsuu_s_w(a: v4u32, b: v4u32) -> v4i32 { /// Vector Signed Saturated Subtract of Unsigned Values /// /// The unsigned elements in vector `b` (two unsigned 64-bit integer numbers) -/// are subtracted from the unsigned elements in vector `a` (two unsigned 64-bit integer numbers) +/// are subtracted from the unsigned elements in vector `a` (two unsigned 64-bit integer numbers). /// The signed result is signed saturated and written to /// to vector (two unsigned 64-bit integer numbers). /// @@ -9001,7 +9004,7 @@ pub unsafe fn __msa_subsuu_s_d(a: v2u64, b: v2u64) -> v2i64 { /// Vector Subtract /// /// The elements in vector `b` (sixteen signed 8-bit integer numbers) -/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers) +/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -9014,7 +9017,7 @@ pub unsafe fn __msa_subv_b(a: v16i8, b: v16i8) -> v16i8 { /// Vector Subtract /// /// The elements in vector `b` (eight signed 16-bit integer numbers) -/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers) +/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -9027,7 +9030,7 @@ pub unsafe fn __msa_subv_h(a: v8i16, b: v8i16) -> v8i16 { /// Vector Subtract /// /// The elements in vector `b` (four signed 32-bit integer numbers) -/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers) +/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -9040,7 +9043,7 @@ pub unsafe fn __msa_subv_w(a: v4i32, b: v4i32) -> v4i32 { /// Vector Subtract /// /// The elements in vector `b` (two signed 64-bit integer numbers) -/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers) +/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers). /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -9052,8 +9055,8 @@ pub unsafe fn __msa_subv_d(a: v2i64, b: v2i64) -> v2i64 { /// Immediate Subtract /// -/// The 5-bit immediate unsigned value imm5 -/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` +/// are subtracted from the elements in vector `a` (sixteen signed 8-bit integer numbers). /// The result is written to vector (sixteen signed 8-bit integer numbers). /// #[inline] @@ -9071,8 +9074,8 @@ pub unsafe fn __msa_subvi_b(a: v16i8, imm5: i32) -> v16i8 { /// Immediate Subtract /// -/// The 5-bit immediate unsigned value imm5 -/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` +/// are subtracted from the elements in vector `a` (eight signed 16-bit integer numbers). /// The result is written to vector (eight signed 16-bit integer numbers). /// #[inline] @@ -9090,8 +9093,8 @@ pub unsafe fn __msa_subvi_h(a: v8i16, imm5: i32) -> v8i16 { /// Immediate Subtract /// -/// The 5-bit immediate unsigned value imm5 -/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` +/// are subtracted from the elements in vector `a` (four signed 32-bit integer numbers). /// The result is written to vector (four signed 32-bit integer numbers). /// #[inline] @@ -9109,8 +9112,8 @@ pub unsafe fn __msa_subvi_w(a: v4i32, imm5: i32) -> v4i32 { /// Immediate Subtract /// -/// The 5-bit immediate unsigned value imm5 -/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers) +/// The 5-bit immediate unsigned value `imm5` +/// are subtracted from the elements in vector `a` (two signed 64-bit integer numbers). /// The result is written to vector (two signed 64-bit integer numbers). /// #[inline] @@ -9128,13 +9131,13 @@ pub unsafe fn __msa_subvi_d(a: v2i64, imm5: i32) -> v2i64 { /// Vector Data Preserving Shuffle /// -/// The vector shuffle instructions selectively copy data elements from the -/// concatenation of vectors 'b' (sixteen signed 8-bit integer numbers) -/// and `c` (sixteen signed 8-bit integer numbers) in to vector 'a' -/// (sixteen signed 8-bit integer numbers) based on the corresponding control element in 'a' -/// The least significant 6 bits in 'a' control elements modulo the number of elements in -/// the concatenated vectors 'b','a' specify the index of the source element. -/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination elementis set to 0. +/// The vector shuffle instructions selectively copy data elements from the +/// concatenation of vectors `b` (sixteen signed 8-bit integer numbers) +/// and `c` (sixteen signed 8-bit integer numbers) in to vector `a` +/// (sixteen signed 8-bit integer numbers) based on the corresponding control element in `a`. +/// The least significant 6 bits in `a` control elements modulo the number of elements in +/// the concatenated vectors `b`, `a` specify the index of the source element. +/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination element is set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -9145,13 +9148,13 @@ pub unsafe fn __msa_vshf_b(a: v16i8, b: v16i8, c: v16i8) -> v16i8 { /// Vector Data Preserving Shuffle /// -/// The vector shuffle instructions selectively copy data elements from the -/// concatenation of vectors 'b' (eight signed 16-bit integer numbers) -/// and `c` (eight signed 16-bit integer numbers) in to vector 'a' -/// (eight signed 16-bit integer numbers) based on the corresponding control element in 'a' -/// The least significant 6 bits in 'a' control elements modulo the number of elements in -/// the concatenated vectors 'b','a' specify the index of the source element. -/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination elementis set to 0. +/// The vector shuffle instructions selectively copy data elements from the +/// concatenation of vectors `b` (eight signed 16-bit integer numbers) +/// and `c` (eight signed 16-bit integer numbers) in to vector `a` +/// (eight signed 16-bit integer numbers) based on the corresponding control element in `a`. +/// The least significant 6 bits in `a` control elements modulo the number of elements in +/// the concatenated vectors `b`, `a` specify the index of the source element. +/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination element is set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -9162,13 +9165,13 @@ pub unsafe fn __msa_vshf_h(a: v8i16, b: v8i16, c: v8i16) -> v8i16 { /// Vector Data Preserving Shuffle /// -/// The vector shuffle instructions selectively copy data elements from the -/// concatenation of vectors 'b' (four signed 32-bit integer numbers) -/// and `c` (four signed 32-bit integer numbers) in to vector 'a' -/// (four signed 32-bit integer numbers) based on the corresponding control element in 'a' -/// The least significant 6 bits in 'a' control elements modulo the number of elements in -/// the concatenated vectors 'b','a' specify the index of the source element. -/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination elementis set to 0. +/// The vector shuffle instructions selectively copy data elements from the +/// concatenation of vectors `b` (four signed 32-bit integer numbers) +/// and `c` (four signed 32-bit integer numbers) in to vector `a` +/// (four signed 32-bit integer numbers) based on the corresponding control element in `a`. +/// The least significant 6 bits in `a` control elements modulo the number of elements in +/// the concatenated vectors `b`, `a` specify the index of the source element. +/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination element is set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -9179,13 +9182,13 @@ pub unsafe fn __msa_vshf_w(a: v4i32, b: v4i32, c: v4i32) -> v4i32 { /// Vector Data Preserving Shuffle /// -/// The vector shuffle instructions selectively copy data elements from the -/// concatenation of vectors 'b' (two signed 64-bit integer numbers) -/// and `c` (two signed 64-bit integer numbers) in to vector 'a' -/// (two signed 64-bit integer numbers) based on the corresponding control element in 'a' -/// The least significant 6 bits in 'a' control elements modulo the number of elements in -/// the concatenated vectors 'b','a' specify the index of the source element. -/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination elementis set to 0. +/// The vector shuffle instructions selectively copy data elements from the +/// concatenation of vectors `b` (two signed 64-bit integer numbers) +/// and `c` (two signed 64-bit integer numbers) in to vector `a` +/// (two signed 64-bit integer numbers) based on the corresponding control element in `a`. +/// The least significant 6 bits in `a` control elements modulo the number of elements in +/// the concatenated vectors `b`, `a` specify the index of the source element. +/// If bit 6 or bit 7 is 1, there will be no copy, but rather the destination element is set to 0. /// #[inline] #[target_feature(enable = "msa")] @@ -9196,10 +9199,10 @@ pub unsafe fn __msa_vshf_d(a: v2i64, b: v2i64, c: v2i64) -> v2i64 { /// Vector Logical Exclusive Or /// -/// Each bit of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the corresponding bit of vector 'b' (sixteen unsigned 8-bit integer numbers) +/// Each bit of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the corresponding bit of vector `b` (sixteen unsigned 8-bit integer numbers) /// in a bitwise logical XOR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -9210,10 +9213,10 @@ pub unsafe fn __msa_xor_v(a: v16u8, b: v16u8) -> v16u8 { /// Immediate Logical Exclusive Or /// -/// Each byte of vector 'a'(sixteen unsigned 8-bit integer numbers) -/// is combined with the 8-bit immediate imm8 +/// Each byte of vector `a` (sixteen unsigned 8-bit integer numbers) +/// is combined with the 8-bit immediate `imm8` /// in a bitwise logical XOR operation. The result is written to vector -/// (sixteen unsigned 8-bit integer numbers) +/// (sixteen unsigned 8-bit integer numbers). /// #[inline] #[target_feature(enable = "msa")] @@ -11417,7 +11420,7 @@ mod tests { // FIXME: https://reviews.llvm.org/D59884 // If target type is i64, negative immediate loses the sign - // Test passes if 4294967293 is used instead -3 in vector 'a' + // Test passes if 4294967293 is used instead -3 in vector `a` // #[simd_test(enable = "msa")] // unsafe fn test_msa_ceqi_d() { // #[rustfmt::skip] @@ -14880,7 +14883,7 @@ mod tests { // FIXME: https://reviews.llvm.org/D59884 // If target type is i64, negative immediate loses the sign - // Test passes if 4294967185 is used instead -111 in vector 'r' + // Test passes if 4294967185 is used instead -111 in vector `r` // #[simd_test(enable = "msa")] // unsafe fn test_msa_ldi_d() { // let r = i64x2::new(-111, -111); @@ -15361,7 +15364,7 @@ mod tests { // FIXME: https://reviews.llvm.org/D59884 // If target type is i64, negative immediate loses the sign - // Test passes if 4294967293 is used instead -3 in vector 'r' + // Test passes if 4294967293 is used instead -3 in vector `r` // #[simd_test(enable = "msa")] // unsafe fn test_msa_maxi_s_d() { // #[rustfmt::skip] diff --git a/src/stdarch/crates/core_arch/src/mod.rs b/src/stdarch/crates/core_arch/src/mod.rs index 88603024b9..eecfaed363 100644 --- a/src/stdarch/crates/core_arch/src/mod.rs +++ b/src/stdarch/crates/core_arch/src/mod.rs @@ -8,11 +8,7 @@ mod acle; mod simd; -#[cfg_attr( - bootstrap, - doc(include = "../stdarch/crates/core_arch/src/core_arch_docs.md") -)] -#[cfg_attr(not(bootstrap), doc(include = "core_arch_docs.md"))] +#[doc(include = "core_arch_docs.md")] #[stable(feature = "simd_arch", since = "1.27.0")] pub mod arch { /// Platform-specific intrinsics for the `x86` platform. diff --git a/src/stdarch/crates/core_arch/src/powerpc/altivec.rs b/src/stdarch/crates/core_arch/src/powerpc/altivec.rs index ce43a5725b..3b6ee2ea19 100644 --- a/src/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/src/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -1832,7 +1832,6 @@ mod endian { { a.vec_mulo(b) } - } pub use self::endian::*; diff --git a/src/stdarch/crates/core_arch/src/simd_llvm.rs b/src/stdarch/crates/core_arch/src/simd_llvm.rs index 717ba5991a..7f18ca8f0f 100644 --- a/src/stdarch/crates/core_arch/src/simd_llvm.rs +++ b/src/stdarch/crates/core_arch/src/simd_llvm.rs @@ -27,7 +27,6 @@ extern "platform-intrinsic" { pub fn simd_sub(x: T, y: T) -> T; pub fn simd_mul(x: T, y: T) -> T; pub fn simd_div(x: T, y: T) -> T; - pub fn simd_rem(x: T, y: T) -> T; pub fn simd_shl(x: T, y: T) -> T; pub fn simd_shr(x: T, y: T) -> T; pub fn simd_and(x: T, y: T) -> T; diff --git a/src/stdarch/crates/core_arch/src/x86/avx.rs b/src/stdarch/crates/core_arch/src/x86/avx.rs index 56067ba5c9..90867e4ad7 100644 --- a/src/stdarch/crates/core_arch/src/x86/avx.rs +++ b/src/stdarch/crates/core_arch/src/x86/avx.rs @@ -1913,7 +1913,7 @@ pub unsafe fn _mm256_moveldup_ps(a: __m256) -> __m256 { } /// Duplicate even-indexed double-precision (64-bit) floating-point elements -/// from "a", and returns the results. +/// from `a`, and returns the results. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movedup_pd) #[inline] @@ -2741,8 +2741,8 @@ pub unsafe fn _mm256_set1_epi32(a: i32) -> __m256i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_set1_epi64x) #[inline] #[target_feature(enable = "avx")] -//#[cfg_attr(test, assert_instr(vmovddup))] -#[cfg_attr(test, assert_instr(vinsertf128))] +#[cfg_attr(all(test, target_arch = "x86_64"), assert_instr(vinsertf128))] +#[cfg_attr(all(test, target_arch = "x86"), assert_instr(vbroadcastsd))] // This intrinsic has no corresponding instruction. #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm256_set1_epi64x(a: i64) -> __m256i { diff --git a/src/stdarch/crates/core_arch/src/x86/avx2.rs b/src/stdarch/crates/core_arch/src/x86/avx2.rs index 84f3364b92..e137f0ce59 100644 --- a/src/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/src/stdarch/crates/core_arch/src/x86/avx2.rs @@ -641,16 +641,14 @@ pub unsafe fn _mm256_broadcastd_epi32(a: __m128i) -> __m256i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_broadcastq_epi64) #[inline] #[target_feature(enable = "avx2")] -#[cfg_attr(test, assert_instr(vpbroadcastq))] +// FIXME: https://github.com/rust-lang/stdarch/issues/791 +#[cfg_attr(test, assert_instr(vmovddup))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_broadcastq_epi64(a: __m128i) -> __m128i { - let zero = _mm_setzero_si128().as_i64x2(); - let ret = simd_shuffle2(a.as_i64x2(), zero, [0_u32; 2]); + let ret = simd_shuffle2(a.as_i64x2(), a.as_i64x2(), [0_u32; 2]); transmute::(ret) } -// N.B. `simd_shuffle4` with integer data types for `a` and `b` is -// often compiled to `vbroadcastsd`. /// Broadcasts the low packed 64-bit integer from `a` to all elements of /// the 256-bit returned value. /// @@ -660,8 +658,7 @@ pub unsafe fn _mm_broadcastq_epi64(a: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(vbroadcastsd))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm256_broadcastq_epi64(a: __m128i) -> __m256i { - let zero = _mm_setzero_si128(); - let ret = simd_shuffle4(a.as_i64x2(), zero.as_i64x2(), [0_u32; 4]); + let ret = simd_shuffle4(a.as_i64x2(), a.as_i64x2(), [0_u32; 4]); transmute::(ret) } diff --git a/src/stdarch/crates/core_arch/src/x86/sse.rs b/src/stdarch/crates/core_arch/src/x86/sse.rs index 3160ac57b8..1dcb94ef3b 100644 --- a/src/stdarch/crates/core_arch/src/x86/sse.rs +++ b/src/stdarch/crates/core_arch/src/x86/sse.rs @@ -1098,7 +1098,10 @@ pub unsafe fn _mm_movelh_ps(a: __m128, b: __m128) -> __m128 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_ps) #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(test, assert_instr(movmskps))] +// FIXME: LLVM9 trunk has the following bug: +// https://github.com/rust-lang/stdarch/issues/794 +// so we only temporarily test this on i686 and x86_64 but not on i586: +#[cfg_attr(all(test, target_feature = "sse2"), assert_instr(movmskps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_movemask_ps(a: __m128) -> i32 { movmskps(a) @@ -1109,21 +1112,7 @@ pub unsafe fn _mm_movemask_ps(a: __m128) -> i32 { /// from `a`. #[inline] #[target_feature(enable = "sse")] -#[cfg_attr( - all( - test, - any( - target_arch = "x86_64", - all(target_arch = "x86", target_feature = "sse2") - ) - ), - assert_instr(movhpd) -)] -// FIXME: 32-bit codegen without SSE2 generates two `shufps` instead of `movhps` -#[cfg_attr( - all(test, target_arch = "x86", not(target_feature = "sse2")), - assert_instr(shufps) -)] +#[cfg_attr(test, assert_instr(movhps))] // TODO: this function is actually not limited to floats, but that's what // what matches the C type most closely: `(__m128, *const __m64) -> __m128`. pub unsafe fn _mm_loadh_pi(a: __m128, p: *const __m64) -> __m128 { @@ -1137,16 +1126,7 @@ pub unsafe fn _mm_loadh_pi(a: __m128, p: *const __m64) -> __m128 { /// is copied from the upper half of `a`. #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(all(test, target_arch = "x86_64"), assert_instr(movlpd))] -#[cfg_attr( - all(test, target_arch = "x86", target_feature = "sse2"), - assert_instr(movlpd) -)] -// FIXME: On 32-bit targets without SSE2, it just generates two `movss`... -#[cfg_attr( - all(test, target_arch = "x86", not(target_feature = "sse2")), - assert_instr(movss) -)] +#[cfg_attr(test, assert_instr(movlps))] pub unsafe fn _mm_loadl_pi(a: __m128, p: *const __m64) -> __m128 { let q = p as *const f32x2; let b: f32x2 = *q; @@ -3457,7 +3437,7 @@ mod tests { } #[simd_test(enable = "sse")] - pub unsafe fn test_mm_cvtsi32_ss() { + unsafe fn test_mm_cvtsi32_ss() { let inputs = &[ (4555i32, 4555.0f32), (322223333, 322223330.0), @@ -3475,7 +3455,7 @@ mod tests { } #[simd_test(enable = "sse")] - pub unsafe fn test_mm_cvtss_f32() { + unsafe fn test_mm_cvtss_f32() { let a = _mm_setr_ps(312.0134, 5.0, 6.0, 7.0); assert_eq!(_mm_cvtss_f32(a), 312.0134); } diff --git a/src/stdarch/crates/core_arch/src/x86/sse2.rs b/src/stdarch/crates/core_arch/src/x86/sse2.rs index 21a3b4a081..5df06c8194 100644 --- a/src/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/src/stdarch/crates/core_arch/src/x86/sse2.rs @@ -2315,7 +2315,7 @@ pub unsafe fn _mm_ucomineq_sd(a: __m128d, b: __m128d) -> i32 { ucomineqsd(a, b) } -/// Converts packed double-precision (64-bit) floating-point elements in "a" to +/// Converts packed double-precision (64-bit) floating-point elements in `a` to /// packed single-precision (32-bit) floating-point elements /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps) @@ -2378,7 +2378,7 @@ pub unsafe fn _mm_cvtsd_ss(a: __m128, b: __m128d) -> __m128 { cvtsd2ss(a, b) } -/// Returns the lower double-precision (64-bit) floating-point element of "a". +/// Returns the lower double-precision (64-bit) floating-point element of `a`. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64) #[inline] @@ -2553,7 +2553,7 @@ pub unsafe fn _mm_load_sd(mem_addr: *const f64) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(test, assert_instr(movhpd))] +#[cfg_attr(test, assert_instr(movhps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_loadh_pd(a: __m128d, mem_addr: *const f64) -> __m128d { _mm_setr_pd(simd_extract(a, 0), *mem_addr) @@ -2566,7 +2566,7 @@ pub unsafe fn _mm_loadh_pd(a: __m128d, mem_addr: *const f64) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(test, assert_instr(movlpd))] +#[cfg_attr(test, assert_instr(movlps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_loadl_pd(a: __m128d, mem_addr: *const f64) -> __m128d { _mm_setr_pd(*mem_addr, simd_extract(a, 1)) @@ -2675,7 +2675,7 @@ pub unsafe fn _mm_storer_pd(mem_addr: *mut f64, a: __m128d) { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeh_pd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(all(test, not(target_os = "windows")), assert_instr(movhpd))] +#[cfg_attr(all(test, not(target_os = "windows")), assert_instr(movhps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_storeh_pd(mem_addr: *mut f64, a: __m128d) { *mem_addr = simd_extract(a, 1); @@ -2725,7 +2725,7 @@ pub unsafe fn _mm_load_pd1(mem_addr: *const f64) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(test, assert_instr(movapd))] +#[cfg_attr(test, assert_instr(movaps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_loadr_pd(mem_addr: *const f64) -> __m128d { let a = _mm_load_pd(mem_addr); @@ -2758,7 +2758,8 @@ pub unsafe fn _mm_loadu_pd(mem_addr: *const f64) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(test, assert_instr(shufpd, imm8 = 1))] +#[cfg_attr(all(test, not(target_os = "windows")), assert_instr(shufps, imm8 = 1))] +#[cfg_attr(all(test, target_os = "windows"), assert_instr(shufpd, imm8 = 1))] #[rustc_args_required_const(2)] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_shuffle_pd(a: __m128d, b: __m128d, imm8: i32) -> __m128d { @@ -2777,7 +2778,8 @@ pub unsafe fn _mm_shuffle_pd(a: __m128d, b: __m128d, imm8: i32) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sd) #[inline] #[target_feature(enable = "sse2")] -#[cfg_attr(test, assert_instr(movsd))] +#[cfg_attr(all(test, not(target_os = "windows")), assert_instr(movsd))] +#[cfg_attr(all(test, target_os = "windows"), assert_instr(movlps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_move_sd(a: __m128d, b: __m128d) -> __m128d { _mm_setr_pd(simd_extract(b, 0), simd_extract(a, 1)) @@ -4164,11 +4166,11 @@ mod tests { let a = _mm_setr_epi8( 0b1000_0000u8 as i8, 0b0, 0b1000_0000u8 as i8, 0b01, 0b0101, 0b1111_0000u8 as i8, 0, 0, - 0, 0, 0b1111_0000u8 as i8, 0b0101, + 0, 0b1011_0101u8 as i8, 0b1111_0000u8 as i8, 0b0101, 0b01, 0b1000_0000u8 as i8, 0b0, 0b1000_0000u8 as i8, ); let r = _mm_movemask_epi8(a); - assert_eq!(r, 0b10100100_00100101); + assert_eq!(r, 0b10100110_00100101); } #[simd_test(enable = "sse2")] diff --git a/src/stdarch/crates/core_arch/src/x86_64/sse.rs b/src/stdarch/crates/core_arch/src/x86_64/sse.rs index a93215072a..ec09282463 100644 --- a/src/stdarch/crates/core_arch/src/x86_64/sse.rs +++ b/src/stdarch/crates/core_arch/src/x86_64/sse.rs @@ -128,7 +128,7 @@ mod tests { } #[simd_test(enable = "sse")] - pub unsafe fn test_mm_cvtsi64_ss() { + unsafe fn test_mm_cvtsi64_ss() { let inputs = &[ (4555i64, 4555.0f32), (322223333, 322223330.0), diff --git a/src/stdarch/crates/std_detect/Cargo.toml b/src/stdarch/crates/std_detect/Cargo.toml index 8902868c62..acfcc116f4 100644 --- a/src/stdarch/crates/std_detect/Cargo.toml +++ b/src/stdarch/crates/std_detect/Cargo.toml @@ -17,8 +17,7 @@ license = "MIT/Apache-2.0" edition = "2015" [badges] -travis-ci = { repository = "rust-lang/stdarch" } -appveyor = { repository = "rust-lang/stdarch" } +azure-devops = { project = "stdarch", pipeline = "rust-lang2.stdarch" } is-it-maintained-issue-resolution = { repository = "rust-lang/stdarch" } is-it-maintained-open-issues = { repository = "rust-lang/stdarch" } maintenance = { status = "experimental" } diff --git a/src/stdarch/crates/std_detect/README.md b/src/stdarch/crates/std_detect/README.md index 1c83a54b80..df66dc64b2 100644 --- a/src/stdarch/crates/std_detect/README.md +++ b/src/stdarch/crates/std_detect/README.md @@ -1,7 +1,7 @@ `std::detect` - Rust's standard library run-time CPU feature detection ======= -[![Travis-CI Status]][travis] [![Appveyor Status]][appveyor] [![std_detect_crate_badge]][std_detect_crate_link] [![std_detect_docs_badge]][std_detect_docs_link] +[![Azure Pipelines Status]][azure] [![std_detect_crate_badge]][std_detect_crate_link] [![std_detect_docs_badge]][std_detect_docs_link] The private `std::detect` module implements run-time feature detection in Rust's @@ -75,10 +75,8 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `std_detect` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -[travis]: https://travis-ci.com/rust-lang/stdarch -[Travis-CI Status]: https://travis-ci.com/rust-lang/stdarch.svg?branch=master -[appveyor]: https://ci.appveyor.com/project/rust-lang-libs/stdarch/branch/master -[Appveyor Status]: https://ci.appveyor.com/api/projects/status/ix74qhmilpibn00x/branch/master?svg=true +[azure]: https://dev.azure.com/rust-lang2/stdarch/_build/latest?definitionId=2&branchName=auto +[Azure Pipelines Status]: https://dev.azure.com/rust-lang2/stdarch/_apis/build/status/rust-lang.stdarch?branchName=auto [std_detect_crate_badge]: https://img.shields.io/crates/v/std_detect.svg [std_detect_crate_link]: https://crates.io/crates/std_detect [std_detect_docs_badge]: https://docs.rs/std_detect/badge.svg diff --git a/src/stdarch/crates/std_detect/src/detect/mod.rs b/src/stdarch/crates/std_detect/src/detect/mod.rs index f446e88eed..80207daad8 100644 --- a/src/stdarch/crates/std_detect/src/detect/mod.rs +++ b/src/stdarch/crates/std_detect/src/detect/mod.rs @@ -64,7 +64,15 @@ mod bit; mod cache; cfg_if! { - if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + if #[cfg(miri)] { + // When running under miri all target-features that are not enabled at + // compile-time are reported as disabled at run-time. + // + // For features for which `cfg(target_feature)` returns true, + // this run-time detection logic is never called. + #[path = "os/other.rs"] + mod os; + } else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { // On x86/x86_64 no OS specific functionality is required. #[path = "os/x86.rs"] mod os; diff --git a/src/stdarch/crates/stdarch-verify/src/lib.rs b/src/stdarch/crates/stdarch-verify/src/lib.rs index cbe0530970..b7569fe5a2 100644 --- a/src/stdarch/crates/stdarch-verify/src/lib.rs +++ b/src/stdarch/crates/stdarch-verify/src/lib.rs @@ -37,14 +37,33 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream { let mut functions = Vec::new(); for &mut (ref mut file, ref path) in &mut files { - for item in file.items.drain(..) { - if let syn::Item::Fn(f) = item { - functions.push((f, path)) + for mut item in file.items.drain(..) { + match item { + syn::Item::Fn(f) => functions.push((f, path)), + syn::Item::Mod(ref mut m) => { + if let Some(ref mut m) = m.content { + for i in m.1.drain(..) { + if let syn::Item::Fn(f) = i { + functions.push((f, path)) + } + } + } + } + _ => (), } } } assert!(!functions.is_empty()); + let mut tests = std::collections::HashSet::::new(); + for f in &functions { + let id = format!("{}", f.0.ident); + if id.starts_with("test_") { + tests.insert(id); + } + } + assert!(!tests.is_empty()); + functions.retain(|&(ref f, _)| { if let syn::Visibility::Public(_) = f.vis { if f.unsafety.is_some() { @@ -84,6 +103,16 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream { quote! { None } }; let required_const = find_required_const(&f.attrs); + + // strip leading underscore from fn name when building a test + // _mm_foo -> mm_foo such that the test name is test_mm_foo. + let test_name_string = format!("{}", name); + let mut test_name_id = test_name_string.as_str(); + while test_name_id.starts_with('_') { + test_name_id = &test_name_id[1..]; + } + let has_test = tests.contains(&format!("test_{}", test_name_id)); + quote! { Function { name: stringify!(#name), @@ -93,6 +122,7 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream { instrs: &[#(#instrs),*], file: stringify!(#path), required_const: &[#(#required_const),*], + has_test: #has_test, } } }) diff --git a/src/stdarch/crates/stdarch-verify/tests/arm.rs b/src/stdarch/crates/stdarch-verify/tests/arm.rs index 53a0ede05e..83ba480e07 100644 --- a/src/stdarch/crates/stdarch-verify/tests/arm.rs +++ b/src/stdarch/crates/stdarch-verify/tests/arm.rs @@ -18,6 +18,7 @@ struct Function { instrs: &'static [&'static str], file: &'static str, required_const: &'static [usize], + has_test: bool, } static F16: Type = Type::PrimFloat(16); @@ -197,6 +198,155 @@ fn verify_all_signatures() { let mut all_valid = true; 'outer: for rust in FUNCTIONS { + if !rust.has_test { + let skip = [ + "vaddq_s64", + "vaddq_u64", + "vrsqrte_f32", + "vtbl1_s8", + "vtbl1_u8", + "vtbl1_p8", + "vtbl2_s8", + "vtbl2_u8", + "vtbl2_p8", + "vtbl3_s8", + "vtbl3_u8", + "vtbl3_p8", + "vtbl4_s8", + "vtbl4_u8", + "vtbl4_p8", + "vtbx1_s8", + "vtbx1_u8", + "vtbx1_p8", + "vtbx2_s8", + "vtbx2_u8", + "vtbx2_p8", + "vtbx3_s8", + "vtbx3_u8", + "vtbx3_p8", + "vtbx4_s8", + "vtbx4_u8", + "vtbx4_p8", + "udf", + "_clz_u8", + "_clz_u16", + "_clz_u32", + "_rbit_u32", + "_rev_u16", + "_rev_u32", + "__breakpoint", + "vpminq_f32", + "vpminq_f64", + "vpmaxq_f32", + "vpmaxq_f64", + "vcombine_s8", + "vcombine_s16", + "vcombine_s32", + "vcombine_s64", + "vcombine_u8", + "vcombine_u16", + "vcombine_u32", + "vcombine_u64", + "vcombine_p64", + "vcombine_f32", + "vcombine_p8", + "vcombine_p16", + "vcombine_f64", + "vtbl1_s8", + "vtbl1_u8", + "vtbl1_p8", + "vtbl2_s8", + "vtbl2_u8", + "vtbl2_p8", + "vtbl3_s8", + "vtbl3_u8", + "vtbl3_p8", + "vtbl4_s8", + "vtbl4_u8", + "vtbl4_p8", + "vtbx1_s8", + "vtbx1_u8", + "vtbx1_p8", + "vtbx2_s8", + "vtbx2_u8", + "vtbx2_p8", + "vtbx3_s8", + "vtbx3_u8", + "vtbx3_p8", + "vtbx4_s8", + "vtbx4_u8", + "vtbx4_p8", + "vqtbl1_s8", + "vqtbl1q_s8", + "vqtbl1_u8", + "vqtbl1q_u8", + "vqtbl1_p8", + "vqtbl1q_p8", + "vqtbx1_s8", + "vqtbx1q_s8", + "vqtbx1_u8", + "vqtbx1q_u8", + "vqtbx1_p8", + "vqtbx1q_p8", + "vqtbl2_s8", + "vqtbl2q_s8", + "vqtbl2_u8", + "vqtbl2q_u8", + "vqtbl2_p8", + "vqtbl2q_p8", + "vqtbx2_s8", + "vqtbx2q_s8", + "vqtbx2_u8", + "vqtbx2q_u8", + "vqtbx2_p8", + "vqtbx2q_p8", + "vqtbl3_s8", + "vqtbl3q_s8", + "vqtbl3_u8", + "vqtbl3q_u8", + "vqtbl3_p8", + "vqtbl3q_p8", + "vqtbx3_s8", + "vqtbx3q_s8", + "vqtbx3_u8", + "vqtbx3q_u8", + "vqtbx3_p8", + "vqtbx3q_p8", + "vqtbl4_s8", + "vqtbl4q_s8", + "vqtbl4_u8", + "vqtbl4q_u8", + "vqtbl4_p8", + "vqtbl4q_p8", + "vqtbx4_s8", + "vqtbx4q_s8", + "vqtbx4_u8", + "vqtbx4q_u8", + "vqtbx4_p8", + "vqtbx4q_p8", + "brk", + "_rev_u64", + "_clz_u64", + "_rbit_u64", + "_cls_u32", + "_cls_u64", + ]; + if !skip.contains(&rust.name) { + println!( + "missing run-time test named `test_{}` for `{}`", + { + let mut id = rust.name; + while id.starts_with('_') { + id = &id[1..]; + } + id + }, + rust.name + ); + all_valid = false; + } + } + // Skip some intrinsics that aren't NEON and are located in different // places than the whitelists below. match rust.name { diff --git a/src/stdarch/crates/stdarch-verify/tests/mips.rs b/src/stdarch/crates/stdarch-verify/tests/mips.rs index 9dba12b95a..ab6637b8f2 100644 --- a/src/stdarch/crates/stdarch-verify/tests/mips.rs +++ b/src/stdarch/crates/stdarch-verify/tests/mips.rs @@ -16,6 +16,7 @@ struct Function { instrs: &'static [&'static str], file: &'static str, required_const: &'static [usize], + has_test: bool, } static F16: Type = Type::PrimFloat(16); @@ -200,6 +201,34 @@ fn verify_all_signatures() { let mut all_valid = true; for rust in FUNCTIONS { + if !rust.has_test { + let skip = [ + "__msa_ceqi_d", + "__msa_cfcmsa", + "__msa_clei_s_d", + "__msa_clti_s_d", + "__msa_ctcmsa", + "__msa_ldi_d", + "__msa_maxi_s_d", + "__msa_mini_s_d", + "break_", + ]; + if !skip.contains(&rust.name) { + println!( + "missing run-time test named `test_{}` for `{}`", + { + let mut id = rust.name; + while id.starts_with('_') { + id = &id[1..]; + } + id + }, + rust.name + ); + all_valid = false; + } + } + // Skip some intrinsics that aren't part of MSA match rust.name { "break_" => continue, diff --git a/src/stdarch/crates/stdarch-verify/tests/x86-intel.rs b/src/stdarch/crates/stdarch-verify/tests/x86-intel.rs index c230dac6cb..572de603d3 100644 --- a/src/stdarch/crates/stdarch-verify/tests/x86-intel.rs +++ b/src/stdarch/crates/stdarch-verify/tests/x86-intel.rs @@ -27,6 +27,7 @@ struct Function { instrs: &'static [&'static str], file: &'static str, required_const: &'static [usize], + has_test: bool, } static F32: Type = Type::PrimFloat(32); @@ -140,6 +141,156 @@ fn verify_all_signatures() { let mut all_valid = true; 'outer: for rust in FUNCTIONS { + if !rust.has_test { + // FIXME: this list should be almost empty + let skip = [ + "__readeflags", + "__readeflags", + "__writeeflags", + "__writeeflags", + "_mm_comige_ss", + "_mm_cvt_ss2si", + "_mm_cvtt_ss2si", + "_mm_cvt_si2ss", + "_mm_set_ps1", + "_mm_load_ps1", + "_mm_store_ps1", + "_mm_getcsr", + "_mm_setcsr", + "_MM_GET_EXCEPTION_MASK", + "_MM_GET_EXCEPTION_STATE", + "_MM_GET_FLUSH_ZERO_MODE", + "_MM_GET_ROUNDING_MODE", + "_MM_SET_EXCEPTION_MASK", + "_MM_SET_EXCEPTION_STATE", + "_MM_SET_FLUSH_ZERO_MODE", + "_MM_SET_ROUNDING_MODE", + "_mm_prefetch", + "_mm_undefined_ps", + "_m_pmaxsw", + "_m_pmaxub", + "_m_pminsw", + "_m_pminub", + "_m_pavgb", + "_m_pavgw", + "_m_psadbw", + "_mm_cvt_pi2ps", + "_m_maskmovq", + "_m_pextrw", + "_m_pinsrw", + "_m_pmovmskb", + "_m_pshufw", + "_mm_cvtt_ps2pi", + "_mm_cvt_ps2pi", + "__cpuid_count", + "__cpuid", + "__get_cpuid_max", + "_xsave", + "_xrstor", + "_xsetbv", + "_xgetbv", + "_xsaveopt", + "_xsavec", + "_xsaves", + "_xrstors", + "_mm_bslli_si128", + "_mm_bsrli_si128", + "_mm_undefined_pd", + "_mm_undefined_si128", + "_mm_cvtps_ph", + "_mm256_cvtps_ph", + "_rdtsc", + "__rdtscp", + "_mm256_castps128_ps256", + "_mm256_castpd128_pd256", + "_mm256_castsi128_si256", + "_mm256_undefined_ps", + "_mm256_undefined_pd", + "_mm256_undefined_si256", + "_bextr2_u32", + "_mm_tzcnt_32", + "_mm512_setzero_si512", + "_mm512_setr_epi32", + "_mm512_set1_epi64", + "_m_paddb", + "_m_paddw", + "_m_paddd", + "_m_paddsb", + "_m_paddsw", + "_m_paddusb", + "_m_paddusw", + "_m_psubb", + "_m_psubw", + "_m_psubd", + "_m_psubsb", + "_m_psubsw", + "_m_psubusb", + "_m_psubusw", + "_mm_set_pi16", + "_mm_set_pi32", + "_mm_set_pi8", + "_mm_set1_pi16", + "_mm_set1_pi32", + "_mm_set1_pi8", + "_mm_setr_pi16", + "_mm_setr_pi32", + "_mm_setr_pi8", + "ud2", + "_mm_min_epi8", + "_mm_min_epi32", + "_xbegin", + "_xend", + "_rdrand16_step", + "_rdrand32_step", + "_rdseed16_step", + "_rdseed32_step", + "_fxsave", + "_fxrstor", + "_t1mskc_u64", + "_mm256_shuffle_epi32", + "_mm256_bslli_epi128", + "_mm256_bsrli_epi128", + "_mm256_unpackhi_epi8", + "_mm256_unpacklo_epi8", + "_mm256_unpackhi_epi16", + "_mm256_unpacklo_epi16", + "_mm256_unpackhi_epi32", + "_mm256_unpacklo_epi32", + "_mm256_unpackhi_epi64", + "_mm256_unpacklo_epi64", + "_xsave64", + "_xrstor64", + "_xsaveopt64", + "_xsavec64", + "_xsaves64", + "_xrstors64", + "_mm_cvtsi64x_si128", + "_mm_cvtsi128_si64x", + "_mm_cvtsi64x_sd", + "cmpxchg16b", + "_rdrand64_step", + "_rdseed64_step", + "_bextr2_u64", + "_mm_tzcnt_64", + "_fxsave64", + "_fxrstor64", + ]; + if !skip.contains(&rust.name) { + println!( + "missing run-time test named `test_{}` for `{}`", + { + let mut id = rust.name; + while id.starts_with('_') { + id = &id[1..]; + } + id + }, + rust.name + ); + all_valid = false; + } + } + match rust.name { // These aren't defined by Intel but they're defined by what appears // to be all other compilers. For more information see diff --git a/src/test/codegen/README.md b/src/test/codegen/README.md new file mode 100644 index 0000000000..00de55eeab --- /dev/null +++ b/src/test/codegen/README.md @@ -0,0 +1,2 @@ +The files here use the LLVM FileCheck framework, documented at +. diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs index ae2ff9994f..ded310d0ae 100644 --- a/src/test/codegen/adjustments.rs +++ b/src/test/codegen/adjustments.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs index bb90a9653f..2acf95de97 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -1,4 +1,5 @@ // compile-flags: -C no-prepopulate-passes +// ignore-tidy-linelength #![crate_type = "lib"] #![feature(c_variadic)] @@ -14,13 +15,13 @@ extern "C" { #[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_0() { // Ensure that we correctly call foreign C-variadic functions. - // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0) + // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0) foreign_c_variadic_0(0); - // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42) + // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42) foreign_c_variadic_0(0, 42i32); - // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024) + // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024) foreign_c_variadic_0(0, 42i32, 1024i32); - // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024, i32 0) + // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0) foreign_c_variadic_0(0, 42i32, 1024i32, 0i32); } @@ -34,18 +35,18 @@ pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) { #[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) { - // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42) + // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42) foreign_c_variadic_1(ap, 42i32); } #[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) { - // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42) + // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42) foreign_c_variadic_1(ap, 2i32, 42i32); } #[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) { - // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0) + // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0) foreign_c_variadic_1(ap, 2i32, 42i32, 0i32); } @@ -64,12 +65,12 @@ pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 { // Ensure that we generate the correct `call` signature when calling a Rust // defined C-variadic. pub unsafe fn test_c_variadic_call() { - // CHECK: call i32 (i32, ...) @c_variadic(i32 0) + // CHECK: call [[RET:(signext )?i32]] (i32, ...) @c_variadic([[PARAM]] 0) c_variadic(0); - // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42) + // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42) c_variadic(0, 42i32); - // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024) + // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024) c_variadic(0, 42i32, 1024i32); - // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024, i32 0) + // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0) c_variadic(0, 42i32, 1024i32, 0i32); } diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs index e152e6e9d1..f67487c83b 100644 --- a/src/test/codegen/fastcall-inreg.rs +++ b/src/test/codegen/fastcall-inreg.rs @@ -49,27 +49,27 @@ #![crate_type = "lib"] pub mod tests { - // CHECK: @f1(i32 inreg %arg0, i32 inreg %arg1, i32 %arg2) + // CHECK: @f1(i32 inreg %_1, i32 inreg %_2, i32 %_3) #[no_mangle] pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {} - // CHECK: @f2(i32* inreg %arg0, i32* inreg %arg1, i32* %arg2) + // CHECK: @f2(i32* inreg %_1, i32* inreg %_2, i32* %_3) #[no_mangle] pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {} - // CHECK: @f3(float %arg0, i32 inreg %arg1, i32 inreg %arg2, i32 %arg3) + // CHECK: @f3(float %_1, i32 inreg %_2, i32 inreg %_3, i32 %_4) #[no_mangle] pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {} - // CHECK: @f4(i32 inreg %arg0, float %arg1, i32 inreg %arg2, i32 %arg3) + // CHECK: @f4(i32 inreg %_1, float %_2, i32 inreg %_3, i32 %_4) #[no_mangle] pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {} - // CHECK: @f5(i64 %arg0, i32 %arg1) + // CHECK: @f5(i64 %_1, i32 %_2) #[no_mangle] pub extern "fastcall" fn f5(_: i64, _: i32) {} - // CHECK: @f6(i1 inreg zeroext %arg0, i32 inreg %arg1, i32 %arg2) + // CHECK: @f6(i1 inreg zeroext %_1, i32 inreg %_2, i32 %_3) #[no_mangle] pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {} } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index bd121ef24a..7e1791cd4f 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -18,48 +18,48 @@ pub fn boolean(x: bool) -> bool { x } -// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn readonly_borrow(_: &i32) { } -// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // static borrow may be captured #[no_mangle] pub fn static_borrow(_: &'static i32) { } -// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // borrow with named lifetime may be captured #[no_mangle] pub fn named_borrow<'r>(_: &'r i32) { } -// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) +// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) { } -// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) +// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %_1) // ... unless this is a mutable borrow, those never alias #[no_mangle] pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { } -// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %arg0) +// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_borrow(_: &mut i32) { } -// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %arg0) +// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { } -// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %arg0) +// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn borrowed_struct(_: &S) { @@ -80,36 +80,36 @@ pub fn struct_return() -> S { } // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } -// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn slice(_: &[u8]) { } -// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_slice(_: &mut [u8]) { } -// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %_1.0, [[USIZE]] %_1.1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_slice(_: &[UnsafeInner]) { } -// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn str(_: &[u8]) { } -// CHECK: @trait_borrow({}* nonnull align 1 %arg0.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %arg0.1) +// CHECK: @trait_borrow({}* nonnull align 1 %_1.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn trait_borrow(_: &Drop) { diff --git a/src/test/codegen/integer-cmp.rs b/src/test/codegen/integer-cmp.rs new file mode 100644 index 0000000000..8ada3cf09d --- /dev/null +++ b/src/test/codegen/integer-cmp.rs @@ -0,0 +1,28 @@ +// This is test for more optimal Ord implementation for integers. +// See for more info. + +// compile-flags: -C opt-level=3 + +#![crate_type = "lib"] + +use std::cmp::Ordering; + +// CHECK-LABEL: @cmp_signed +#[no_mangle] +pub fn cmp_signed(a: i64, b: i64) -> Ordering { +// CHECK: icmp slt +// CHECK: icmp ne +// CHECK: zext i1 +// CHECK: select i1 + a.cmp(&b) +} + +// CHECK-LABEL: @cmp_unsigned +#[no_mangle] +pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { +// CHECK: icmp ult +// CHECK: icmp ne +// CHECK: zext i1 +// CHECK: select i1 + a.cmp(&b) +} diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index 7f99ca724c..7aadc8a095 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -5,7 +5,6 @@ // verify that LLVM recognizes a loop involving 0..=n and will const-fold it. -//------------------------------------------------------------------------------ // Example from original issue #45222 fn foo2(n: u64) -> u64 { @@ -25,7 +24,6 @@ pub fn check_foo2() -> u64 { foo2(100000) } -//------------------------------------------------------------------------------ // Simplified example of #45222 fn triangle_inc(n: u64) -> u64 { @@ -43,7 +41,6 @@ pub fn check_triangle_inc() -> u64 { triangle_inc(100000) } -//------------------------------------------------------------------------------ // Demo in #48012 fn foo3r(n: u64) -> u64 { diff --git a/src/test/codegen/iter-fold-closure-no-dupes.rs b/src/test/codegen/iter-fold-closure-no-dupes.rs new file mode 100644 index 0000000000..ec58f7068a --- /dev/null +++ b/src/test/codegen/iter-fold-closure-no-dupes.rs @@ -0,0 +1,14 @@ +//! Check that fold closures aren't duplicated for each iterator type. +// compile-flags: -C opt-level=0 + +fn main() { + (0i32..10).by_ref().count(); + (0i32..=10).by_ref().count(); +} + +// `count` calls `fold`, which calls `try_fold` -- find the `fold` closure: +// CHECK: {{^define.*Iterator::fold::.*closure}} +// +// Only one closure is needed for both `count` calls, even from different +// monomorphized iterator types, as it's only generic over the item type. +// CHECK-NOT: {{^define.*Iterator::fold::.*closure}} diff --git a/src/test/codegen/iter-fold-closure-no-iterator.rs b/src/test/codegen/iter-fold-closure-no-iterator.rs new file mode 100644 index 0000000000..fbeafd5f39 --- /dev/null +++ b/src/test/codegen/iter-fold-closure-no-iterator.rs @@ -0,0 +1,10 @@ +//! Check that fold closures aren't generic in the iterator type. +// compile-flags: -C opt-level=0 + +fn main() { + (0i32..10).by_ref().count(); +} + +// `count` calls `fold`, which calls `try_fold` -- that `fold` closure should +// not be generic in the iterator type, only in the item type. +// CHECK-NOT: {{^define.*Iterator::fold::.*closure.*Range}} diff --git a/src/test/codegen/personality_lifetimes.rs b/src/test/codegen/personality_lifetimes.rs index 0d3d537a27..05888c0e73 100644 --- a/src/test/codegen/personality_lifetimes.rs +++ b/src/test/codegen/personality_lifetimes.rs @@ -20,12 +20,13 @@ pub fn test() { let _s = S; // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just // in the first one. + // CHECK: [[SLOT:%[0-9]+]] = alloca { i8*, i32 } // CHECK-LABEL: cleanup: - // CHECK: bitcast{{.*}}personalityslot - // CHECK-NEXT: call void @llvm.lifetime.start + // CHECK: [[BITCAST:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST]]) // CHECK-LABEL: cleanup1: - // CHECK: bitcast{{.*}}personalityslot - // CHECK-NEXT: call void @llvm.lifetime.start + // CHECK: [[BITCAST1:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST1]]) might_unwind(); let _t = S; might_unwind(); diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs index cbb9942347..15f99fd0c2 100644 --- a/src/test/codegen/refs.rs +++ b/src/test/codegen/refs.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index c348a8f7b8..87f29f6047 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -6,7 +6,7 @@ use std::iter; -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs index c9f3837565..e705d5ce3c 100644 --- a/src/test/codegen/repr-transparent.rs +++ b/src/test/codegen/repr-transparent.rs @@ -14,21 +14,21 @@ pub struct Zst2(()); #[repr(transparent)] pub struct F32(f32); -// CHECK: define float @test_F32(float %arg0) +// CHECK: define float @test_F32(float %_1) #[no_mangle] pub extern fn test_F32(_: F32) -> F32 { loop {} } #[repr(transparent)] pub struct Ptr(*mut u8); -// CHECK: define i8* @test_Ptr(i8* %arg0) +// CHECK: define i8* @test_Ptr(i8* %_1) #[no_mangle] pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} } #[repr(transparent)] pub struct WithZst(u64, Zst1); -// CHECK: define i64 @test_WithZst(i64 %arg0) +// CHECK: define i64 @test_WithZst(i64 %_1) #[no_mangle] pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} } @@ -36,14 +36,14 @@ pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} } pub struct WithZeroSizedArray(*const f32, [i8; 0]); // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. -// CHECK: define i32* @test_WithZeroSizedArray(i32* %arg0) +// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1) #[no_mangle] pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } #[repr(transparent)] pub struct Generic(T); -// CHECK: define double @test_Generic(double %arg0) +// CHECK: define double @test_Generic(double %_1) #[no_mangle] pub extern fn test_Generic(_: Generic) -> Generic { loop {} } @@ -53,14 +53,14 @@ pub struct GenericPlusZst(T, Zst2); #[repr(u8)] pub enum Bool { True, False, FileNotFound } -// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %arg0) +// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1) #[no_mangle] pub extern fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } #[repr(transparent)] pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); -// CHECK: define i16* @test_LifetimePhantom(i16* %arg0) +// CHECK: define i16* @test_LifetimePhantom(i16* %_1) #[no_mangle] pub extern fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { loop {} } @@ -70,28 +70,28 @@ pub struct UnitPhantom { val: T, unit: PhantomData } pub struct Px; -// CHECK: define float @test_UnitPhantom(float %arg0) +// CHECK: define float @test_UnitPhantom(float %_1) #[no_mangle] pub extern fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { loop {} } #[repr(transparent)] pub struct TwoZsts(Zst1, i8, Zst2); -// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %arg0) +// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1) #[no_mangle] pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } #[repr(transparent)] pub struct Nested1(Zst2, Generic); -// CHECK: define double @test_Nested1(double %arg0) +// CHECK: define double @test_Nested1(double %_1) #[no_mangle] pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} } #[repr(transparent)] pub struct Nested2(Nested1, Zst1); -// CHECK: define double @test_Nested2(double %arg0) +// CHECK: define double @test_Nested2(double %_1) #[no_mangle] pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} } @@ -101,7 +101,7 @@ struct f32x4(f32, f32, f32, f32); #[repr(transparent)] pub struct Vector(f32x4); -// CHECK: define <4 x float> @test_Vector(<4 x float> %arg0) +// CHECK: define <4 x float> @test_Vector(<4 x float> %_1) #[no_mangle] pub extern fn test_Vector(_: Vector) -> Vector { loop {} } @@ -111,7 +111,7 @@ impl Mirror for T { type It = Self; } #[repr(transparent)] pub struct StructWithProjection(::It); -// CHECK: define float @test_Projection(float %arg0) +// CHECK: define float @test_Projection(float %_1) #[no_mangle] pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } @@ -120,7 +120,7 @@ pub enum EnumF32 { Variant(F32) } -// CHECK: define float @test_EnumF32(float %arg0) +// CHECK: define float @test_EnumF32(float %_1) #[no_mangle] pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } @@ -129,7 +129,7 @@ pub enum EnumF32WithZsts { Variant(Zst1, F32, Zst2) } -// CHECK: define float @test_EnumF32WithZsts(float %arg0) +// CHECK: define float @test_EnumF32WithZsts(float %_1) #[no_mangle] pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } @@ -138,7 +138,7 @@ pub union UnionF32 { field: F32, } -// CHECK: define float @test_UnionF32(float %arg0) +// CHECK: define float @test_UnionF32(float %_1) #[no_mangle] pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } @@ -149,7 +149,7 @@ pub union UnionF32WithZsts { zst2: Zst2, } -// CHECK: define float @test_UnionF32WithZsts(float %arg0) +// CHECK: define float @test_UnionF32WithZsts(float %_1) #[no_mangle] pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } diff --git a/src/test/codegen/scalar-pair-bool.rs b/src/test/codegen/scalar-pair-bool.rs index 78d1025b13..d91ee7f816 100644 --- a/src/test/codegen/scalar-pair-bool.rs +++ b/src/test/codegen/scalar-pair-bool.rs @@ -20,24 +20,24 @@ pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) { pair } -// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.1) +// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) { // Make sure it can operate directly on the unpacked args - // CHECK: and i1 %arg0.0, %arg0.1 - // CHECK: or i1 %arg0.0, %arg0.1 + // CHECK: and i1 %_1.0, %_1.1 + // CHECK: or i1 %_1.0, %_1.1 (a && b, a || b) } -// CHECK: define void @pair_branches(i1 zeroext %arg0.0, i1 zeroext %arg0.1) +// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_branches((a, b): (bool, bool)) { // Make sure it can branch directly on the unpacked bool args - // CHECK: br i1 %arg0.0 + // CHECK: br i1 %_1.0 if a { println!("Hello!"); } - // CHECK: br i1 %arg0.1 + // CHECK: br i1 %_1.1 if b { println!("Goodbye!"); } diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index b7baffe166..7339df17b0 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -16,38 +16,38 @@ pub struct i64x4(i64, i64, i64, i64); #[derive(Copy, Clone)] pub union UnionI64x4{ a:(), b: i64x4 } -// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4(_: UnionI64x4) { loop {} } pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } -// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} } pub union UnionI64x4I64{ a: i64x4, b: i64 } -// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} } pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) } -// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} } pub union UnionF32{a:f32} -// CHECK: define float @test_UnionF32(float %arg0) +// CHECK: define float @test_UnionF32(float %_1) #[no_mangle] pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } pub union UnionF32F32{a:f32, b:f32} -// CHECK: define float @test_UnionF32F32(float %arg0) +// CHECK: define float @test_UnionF32F32(float %_1) #[no_mangle] pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } @@ -58,13 +58,13 @@ pub union UnionF32U32{a:f32, b:u32} pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } pub union UnionU128{a:u128} -// CHECK: define i128 @test_UnionU128(i128 %arg0) +// CHECK: define i128 @test_UnionU128(i128 %_1) #[no_mangle] pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} } #[repr(C)] pub union CUnionU128{a:u128} -// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0) +// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %_1) #[no_mangle] pub fn test_CUnionU128(_: CUnionU128) { loop {} } diff --git a/src/test/codegen/var-names.rs b/src/test/codegen/var-names.rs new file mode 100644 index 0000000000..3140a7c6b6 --- /dev/null +++ b/src/test/codegen/var-names.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -C no-prepopulate-passes + +#![crate_type = "lib"] + +// CHECK-LABEL: define i32 @test(i32 %a, i32 %b) +#[no_mangle] +pub fn test(a: u32, b: u32) -> u32 { + let c = a + b; + // CHECK: %c = add i32 %a, %b + let d = c; + let e = d * a; + // CHECK-NEXT: %e = mul i32 %c, %a + e + // CHECK-NEXT: ret i32 %e +} diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs similarity index 100% rename from src/test/ui/issues/issue-44415.rs rename to src/test/compile-fail/issue-44415.rs diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index c0ff90c3ff..8709fb6817 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -8,11 +8,11 @@ // gdb-command:run -// gdb-command:print *unique +// gdb-command:print *boxed_with_padding // gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} // gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} -// gdb-command:print *unique_dtor +// gdb-command:print *boxed_with_dtor // gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} // gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} @@ -21,13 +21,13 @@ // lldb-command:run -// lldb-command:print *unique +// lldb-command:print *boxed_with_padding // lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } -// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } +// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } -// lldb-command:print *unique_dtor +// lldb-command:print *boxed_with_dtor // lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } -// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } +// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } #![allow(unused_variables)] #![feature(box_syntax)] @@ -54,9 +54,9 @@ impl Drop for StructWithDestructor { fn main() { - let unique: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; + let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; - let unique_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; + let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; zzz(); // #break } diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index fef62534b3..8c86d2cf43 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -242,12 +242,12 @@ fn non_immediate_args(a: BigStruct, b: BigStruct) { fn binding(a: i64, b: u64, c: f64) { let x = 0; // #break - println!("") + println!() } fn assignment(mut a: u64, b: u64, c: f64) { a = b; // #break - println!("") + println!() } fn function_call(x: u64, y: u64, z: f64) { diff --git a/src/test/debuginfo/issue-22656.rs b/src/test/debuginfo/issue-22656.rs index 86d31909a0..e4634d96a6 100644 --- a/src/test/debuginfo/issue-22656.rs +++ b/src/test/debuginfo/issue-22656.rs @@ -15,7 +15,7 @@ // lldbg-check:[...]$0 = vec![1, 2, 3] // lldbr-check:(alloc::vec::Vec) v = vec![1, 2, 3] // lldb-command:print zs -// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 } +// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct[...], y: 123, z: ZeroSizedStruct[...], w: 456 } // lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 } // lldbr-command:continue diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index d859cbef39..50d3657d41 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -18,7 +18,7 @@ fn callee1(_x: u32, _y: i64) {} fn callee2(_x: u32, _y: i64) {} -// Change Callee (Function) ---------------------------------------------------- +// Change Callee (Function) #[cfg(cfail1)] pub fn change_callee_function() { callee1(1, 2) @@ -33,7 +33,7 @@ pub fn change_callee_function() { -// Change Argument (Function) -------------------------------------------------- +// Change Argument (Function) #[cfg(cfail1)] pub fn change_argument_function() { callee1(1, 2) @@ -48,7 +48,7 @@ pub fn change_argument_function() { -// Change Callee Indirectly (Function) ----------------------------------------- +// Change Callee Indirectly (Function) mod change_callee_indirectly_function { #[cfg(cfail1)] use super::callee1 as callee; @@ -73,7 +73,7 @@ impl Struct { fn method2(&self, _x: char, _y: bool) {} } -// Change Callee (Method) ------------------------------------------------------ +// Change Callee (Method) #[cfg(cfail1)] pub fn change_callee_method() { let s = Struct; @@ -90,7 +90,7 @@ pub fn change_callee_method() { -// Change Argument (Method) ---------------------------------------------------- +// Change Argument (Method) #[cfg(cfail1)] pub fn change_argument_method() { let s = Struct; @@ -107,7 +107,7 @@ pub fn change_argument_method() { -// Change Callee (Method, UFCS) ------------------------------------------------ +// Change Callee (Method, UFCS) #[cfg(cfail1)] pub fn change_ufcs_callee_method() { let s = Struct; @@ -124,7 +124,7 @@ pub fn change_ufcs_callee_method() { -// Change Argument (Method, UFCS) ---------------------------------------------- +// Change Argument (Method, UFCS) #[cfg(cfail1)] pub fn change_argument_method_ufcs() { let s = Struct; @@ -141,7 +141,7 @@ pub fn change_argument_method_ufcs() { -// Change To UFCS -------------------------------------------------------------- +// Change To UFCS #[cfg(cfail1)] pub fn change_to_ufcs() { let s = Struct; @@ -164,7 +164,7 @@ impl Struct2 { fn method1(&self, _x: char, _y: bool) {} } -// Change UFCS Callee Indirectly ----------------------------------------------- +// Change UFCS Callee Indirectly pub mod change_ufcs_callee_indirectly { #[cfg(cfail1)] use super::Struct as Struct; diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 24ab6b8e18..08693560d0 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change closure body --------------------------------------------------------- +// Change closure body #[cfg(cfail1)] pub fn change_closure_body() { let _ = || 1u32; @@ -29,7 +29,7 @@ pub fn change_closure_body() { -// Add parameter --------------------------------------------------------------- +// Add parameter #[cfg(cfail1)] pub fn add_parameter() { let x = 0u32; @@ -46,7 +46,7 @@ pub fn add_parameter() { -// Change parameter pattern ---------------------------------------------------- +// Change parameter pattern #[cfg(cfail1)] pub fn change_parameter_pattern() { let _ = |x: (u32,)| x; @@ -61,7 +61,7 @@ pub fn change_parameter_pattern() { -// Add `move` to closure ------------------------------------------------------- +// Add `move` to closure #[cfg(cfail1)] pub fn add_move() { let _ = || 1; @@ -76,7 +76,7 @@ pub fn add_move() { -// Add type ascription to parameter -------------------------------------------- +// Add type ascription to parameter #[cfg(cfail1)] pub fn add_type_ascription_to_parameter() { let closure = |x| x + 1u32; @@ -93,7 +93,7 @@ pub fn add_type_ascription_to_parameter() { -// Change parameter type ------------------------------------------------------- +// Change parameter type #[cfg(cfail1)] pub fn change_parameter_type() { let closure = |x: u32| (x as u64) + 1; diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 8e713a1d99..3d2eed8963 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change const visibility --------------------------------------------------- +// Change const visibility #[cfg(cfail1)] const CONST_VISIBILITY: u8 = 0; @@ -24,7 +24,7 @@ const CONST_VISIBILITY: u8 = 0; pub const CONST_VISIBILITY: u8 = 0; -// Change type from i32 to u32 ------------------------------------------------ +// Change type from i32 to u32 #[cfg(cfail1)] const CONST_CHANGE_TYPE_1: i32 = 0; @@ -34,7 +34,7 @@ const CONST_CHANGE_TYPE_1: i32 = 0; const CONST_CHANGE_TYPE_1: u32 = 0; -// Change type from Option to Option -------------------------------- +// Change type from Option to Option #[cfg(cfail1)] const CONST_CHANGE_TYPE_2: Option = None; @@ -44,7 +44,7 @@ const CONST_CHANGE_TYPE_2: Option = None; const CONST_CHANGE_TYPE_2: Option = None; -// Change value between simple literals --------------------------------------- +// Change value between simple literals #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { @@ -56,7 +56,7 @@ const CONST_CHANGE_VALUE_1: i16 = { }; -// Change value between expressions ------------------------------------------- +// Change value between expressions #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { @@ -88,7 +88,7 @@ const CONST_CHANGE_VALUE_4: i16 = { }; -// Change type indirectly ----------------------------------------------------- +// Change type indirectly struct ReferencedType1; struct ReferencedType2; diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index ca45d36a6b..70820dfaea 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 4515e36166..9cc2d3bcf6 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -11,7 +11,6 @@ #![allow(warnings)] -#![feature(intrinsics)] #![feature(linkage)] #![feature(rustc_attrs)] #![crate_type = "rlib"] @@ -99,17 +98,6 @@ pub fn make_extern() {} pub extern "C" fn make_extern() {} -// Extern C Extern Rust-Intrinsic ---------------------------------------------- - -#[cfg(cfail1)] -pub extern "C" fn make_intrinsic() {} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] -#[rustc_clean(cfg = "cfail3")] -pub extern "rust-intrinsic" fn make_intrinsic() {} - - // Type Parameter -------------------------------------------------------------- #[cfg(cfail1)] diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index b84c393573..4b73f1371f 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -14,7 +14,7 @@ #![feature(rustc_attrs)] #![crate_type="rlib"] -// Change condition (if) ------------------------------------------------------- +// Change condition (if) #[cfg(cfail1)] pub fn change_condition(x: bool) -> u32 { if x { @@ -35,7 +35,7 @@ pub fn change_condition(x: bool) -> u32 { return 0 } -// Change then branch (if) ----------------------------------------------------- +// Change then branch (if) #[cfg(cfail1)] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -58,7 +58,7 @@ pub fn change_then_branch(x: bool) -> u32 { -// Change else branch (if) ----------------------------------------------------- +// Change else branch (if) #[cfg(cfail1)] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -81,7 +81,7 @@ pub fn change_else_branch(x: bool) -> u32 { -// Add else branch (if) -------------------------------------------------------- +// Add else branch (if) #[cfg(cfail1)] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -109,7 +109,7 @@ pub fn add_else_branch(x: bool) -> u32 { -// Change condition (if let) --------------------------------------------------- +// Change condition (if let) #[cfg(cfail1)] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_x) = x { @@ -132,7 +132,7 @@ pub fn change_condition_if_let(x: Option) -> u32 { -// Change then branch (if let) ------------------------------------------------- +// Change then branch (if let) #[cfg(cfail1)] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -155,7 +155,7 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { -// Change else branch (if let) ------------------------------------------------- +// Change else branch (if let) #[cfg(cfail1)] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -178,7 +178,7 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { -// Add else branch (if let) ---------------------------------------------------- +// Add else branch (if let) #[cfg(cfail1)] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 4d39ed6870..08cf19d776 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -13,7 +13,7 @@ #![feature(rustc_attrs)] #![crate_type="rlib"] -// Change simple index --------------------------------------------------------- +// Change simple index #[cfg(cfail1)] fn change_simple_index(slice: &[u32]) -> u32 { slice[3] @@ -30,7 +30,7 @@ fn change_simple_index(slice: &[u32]) -> u32 { -// Change lower bound ---------------------------------------------------------- +// Change lower bound #[cfg(cfail1)] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..5] @@ -47,7 +47,7 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { -// Change upper bound ---------------------------------------------------------- +// Change upper bound #[cfg(cfail1)] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..5] @@ -64,7 +64,7 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { -// Add lower bound ------------------------------------------------------------- +// Add lower bound #[cfg(cfail1)] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[..4] @@ -81,7 +81,7 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { -// Add upper bound ------------------------------------------------------------- +// Add upper bound #[cfg(cfail1)] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..] @@ -98,7 +98,7 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { -// Change mutability ----------------------------------------------------------- +// Change mutability #[cfg(cfail1)] fn change_mutability(slice: &mut [u32]) -> u32 { (&mut slice[3..5])[0] @@ -115,7 +115,7 @@ fn change_mutability(slice: &mut [u32]) -> u32 { -// Exclusive to inclusive range ------------------------------------------------ +// Exclusive to inclusive range #[cfg(cfail1)] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..7] diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 538fd2c292..24d436f5f9 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -42,7 +42,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] pub fn method_body() { println!("Hello, world!"); @@ -63,7 +66,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] #[inline] pub fn method_body_inlined() { @@ -97,7 +103,7 @@ impl Foo { #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of")] + #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn method_selfness(&self) { } } diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index deb1c45a52..c50ee73d71 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -16,7 +16,7 @@ -// Change template ------------------------------------------------------------- +// Change template #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { @@ -51,7 +51,7 @@ pub fn change_template(a: i32) -> i32 { -// Change output ------------------------------------------------------------- +// Change output #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -88,7 +88,7 @@ pub fn change_output(a: i32) -> i32 { -// Change input ------------------------------------------------------------- +// Change input #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -123,7 +123,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { -// Change input constraint ----------------------------------------------------- +// Change input constraint #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -158,7 +158,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { -// Change clobber -------------------------------------------------------------- +// Change clobber #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -193,7 +193,7 @@ pub fn change_clobber(_a: i32) -> i32 { -// Change options -------------------------------------------------------------- +// Change options #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index 6222d948c9..a2222db4c5 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -59,7 +59,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -132,7 +132,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -182,7 +182,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index b370fcce8e..70b0a5ab78 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -17,7 +17,7 @@ #![crate_type="rlib"] -// Indexing expression --------------------------------------------------------- +// Indexing expression #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { @@ -32,7 +32,7 @@ pub fn indexing(slice: &[u8]) -> u8 { } -// Arithmetic overflow plus ---------------------------------------------------- +// Arithmetic overflow plus #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { @@ -47,7 +47,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { } -// Arithmetic overflow minus ---------------------------------------------------- +// Arithmetic overflow minus #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { @@ -62,7 +62,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { } -// Arithmetic overflow mult ---------------------------------------------------- +// Arithmetic overflow mult #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { @@ -77,7 +77,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { } -// Arithmetic overflow negation ------------------------------------------------ +// Arithmetic overflow negation #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { @@ -92,7 +92,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { } -// Division by zero ------------------------------------------------------------ +// Division by zero #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { @@ -106,7 +106,7 @@ pub fn division_by_zero(val: i32) -> i32 { } } -// Division by zero ------------------------------------------------------------ +// Division by zero #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { @@ -121,7 +121,7 @@ pub fn mod_by_zero(val: i32) -> i32 { } -// shift left ------------------------------------------------------------------ +// shift left #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { @@ -136,7 +136,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { } -// shift right ------------------------------------------------------------------ +// shift right #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 6f74e0fdbc..d70ebb08b7 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -16,7 +16,7 @@ #![crate_type="rlib"] -// Change static visibility --------------------------------------------------- +// Change static visibility #[cfg(cfail1)] static STATIC_VISIBILITY: u8 = 0; @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; pub static STATIC_VISIBILITY: u8 = 0; -// Change static mutability --------------------------------------------------- +// Change static mutability #[cfg(cfail1)] static STATIC_MUTABILITY: u8 = 0; @@ -36,7 +36,7 @@ static STATIC_MUTABILITY: u8 = 0; static mut STATIC_MUTABILITY: u8 = 0; -// Add linkage attribute ------------------------------------------------------ +// Add linkage attribute #[cfg(cfail1)] static STATIC_LINKAGE: u8 = 0; @@ -47,7 +47,7 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_LINKAGE: u8 = 0; -// Add no_mangle attribute ---------------------------------------------------- +// Add no_mangle attribute #[cfg(cfail1)] static STATIC_NO_MANGLE: u8 = 0; @@ -58,7 +58,7 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; -// Add thread_local attribute ------------------------------------------------- +// Add thread_local attribute #[cfg(cfail1)] static STATIC_THREAD_LOCAL: u8 = 0; @@ -69,7 +69,7 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; -// Change type from i16 to u64 ------------------------------------------------ +// Change type from i16 to u64 #[cfg(cfail1)] static STATIC_CHANGE_TYPE_1: i16 = 0; @@ -79,7 +79,7 @@ static STATIC_CHANGE_TYPE_1: i16 = 0; static STATIC_CHANGE_TYPE_1: u64 = 0; -// Change type from Option to Option --------------------------------- +// Change type from Option to Option #[cfg(cfail1)] static STATIC_CHANGE_TYPE_2: Option = None; @@ -89,7 +89,7 @@ static STATIC_CHANGE_TYPE_2: Option = None; static STATIC_CHANGE_TYPE_2: Option = None; -// Change value between simple literals --------------------------------------- +// Change value between simple literals #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_1: i16 = { @@ -101,7 +101,7 @@ static STATIC_CHANGE_VALUE_1: i16 = { }; -// Change value between expressions ------------------------------------------- +// Change value between expressions #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_2: i16 = { @@ -133,7 +133,7 @@ static STATIC_CHANGE_VALUE_4: i16 = { }; -// Change type indirectly ----------------------------------------------------- +// Change type indirectly struct ReferencedType1; struct ReferencedType2; diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index b708b99eab..456d5e7475 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -20,7 +20,7 @@ pub struct RegularStruct { z: i16, } -// Change field value (regular struct) ----------------------------------------- +// Change field value (regular struct) #[cfg(cfail1)] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -43,7 +43,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct { -// Change field order (regular struct) ----------------------------------------- +// Change field order (regular struct) #[cfg(cfail1)] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -66,7 +66,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct { -// Add field (regular struct) -------------------------------------------------- +// Add field (regular struct) #[cfg(cfail1)] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -100,7 +100,7 @@ pub fn add_field_regular_struct() -> RegularStruct { -// Change field label (regular struct) ----------------------------------------- +// Change field label (regular struct) #[cfg(cfail1)] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -141,7 +141,7 @@ pub struct RegularStruct2 { z: i8, } -// Change constructor path (regular struct) ------------------------------------ +// Change constructor path (regular struct) #[cfg(cfail1)] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct { @@ -164,7 +164,7 @@ pub fn change_constructor_path_regular_struct() { -// Change constructor path indirectly (regular struct) ------------------------- +// Change constructor path indirectly (regular struct) pub mod change_constructor_path_indirectly_regular_struct { #[cfg(cfail1)] use super::RegularStruct as Struct; @@ -189,7 +189,7 @@ pub mod change_constructor_path_indirectly_regular_struct { pub struct TupleStruct(i32, i64, i16); -// Change field value (tuple struct) ------------------------------------------- +// Change field value (tuple struct) #[cfg(cfail1)] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 2) @@ -206,7 +206,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { pub struct TupleStruct2(u16, u16, u16); -// Change constructor path (tuple struct) -------------------------------------- +// Change constructor path (tuple struct) #[cfg(cfail1)] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct(0, 1, 2); @@ -221,7 +221,7 @@ pub fn change_constructor_path_tuple_struct() { -// Change constructor path indirectly (tuple struct) --------------------------- +// Change constructor path indirectly (tuple struct) pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(cfail1)] use super::TupleStruct as Struct; diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 30b4e30682..3006cdccfb 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -18,10 +18,9 @@ #![feature(rustc_attrs)] #![crate_type="rlib"] #![feature(associated_type_defaults)] -#![feature(intrinsics)] -// Change trait visibility -------------------------------------------------------- +// Change trait visibility #[cfg(cfail1)] trait TraitVisibility { } @@ -32,7 +31,7 @@ pub trait TraitVisibility { } -// Change trait unsafety ---------------------------------------------------------- +// Change trait unsafety #[cfg(cfail1)] trait TraitUnsafety { } @@ -43,7 +42,7 @@ unsafe trait TraitUnsafety { } -// Add method --------------------------------------------------------------------- +// Add method #[cfg(cfail1)] trait TraitAddMethod { } @@ -57,7 +56,7 @@ pub trait TraitAddMethod { -// Change name of method ---------------------------------------------------------- +// Change name of method #[cfg(cfail1)] trait TraitChangeMethodName { fn method(); @@ -72,7 +71,7 @@ trait TraitChangeMethodName { -// Add return type to method ------------------------------------------------------ +// Add return type to method #[cfg(cfail1)] trait TraitAddReturnType { fn method(); @@ -89,7 +88,7 @@ trait TraitAddReturnType { -// Change return type of method --------------------------------------------------- +// Change return type of method #[cfg(cfail1)] trait TraitChangeReturnType { fn method() -> u32; @@ -106,7 +105,7 @@ trait TraitChangeReturnType { -// Add parameter to method -------------------------------------------------------- +// Add parameter to method #[cfg(cfail1)] trait TraitAddParameterToMethod { fn method(); @@ -123,7 +122,7 @@ trait TraitAddParameterToMethod { -// Change name of method parameter ------------------------------------------------ +// Change name of method parameter #[cfg(cfail1)] trait TraitChangeMethodParameterName { fn method(a: u32); @@ -148,7 +147,7 @@ trait TraitChangeMethodParameterName { -// Change type of method parameter (i32 => i64) ----------------------------------- +// Change type of method parameter (i32 => i64) #[cfg(cfail1)] trait TraitChangeMethodParameterType { fn method(a: i32); @@ -165,7 +164,7 @@ trait TraitChangeMethodParameterType { -// Change type of method parameter (&i32 => &mut i32) ----------------------------- +// Change type of method parameter (&i32 => &mut i32) #[cfg(cfail1)] trait TraitChangeMethodParameterTypeRef { fn method(a: &i32); @@ -182,7 +181,7 @@ trait TraitChangeMethodParameterTypeRef { -// Change order of method parameters ---------------------------------------------- +// Change order of method parameters #[cfg(cfail1)] trait TraitChangeMethodParametersOrder { fn method(a: i32, b: i64); @@ -199,7 +198,7 @@ trait TraitChangeMethodParametersOrder { -// Add default implementation to method ------------------------------------------- +// Add default implementation to method #[cfg(cfail1)] trait TraitAddMethodAutoImplementation { fn method(); @@ -216,7 +215,7 @@ trait TraitAddMethodAutoImplementation { -// Change order of methods -------------------------------------------------------- +// Change order of methods #[cfg(cfail1)] trait TraitChangeOrderOfMethods { fn method0(); @@ -233,7 +232,7 @@ trait TraitChangeOrderOfMethods { -// Change mode of self parameter -------------------------------------------------- +// Change mode of self parameter #[cfg(cfail1)] trait TraitChangeModeSelfRefToMut { fn method(&self); @@ -284,7 +283,7 @@ trait TraitChangeModeSelfOwnToRef { -// Add unsafe modifier to method -------------------------------------------------- +// Add unsafe modifier to method #[cfg(cfail1)] trait TraitAddUnsafeModifier { fn method(); @@ -301,7 +300,7 @@ trait TraitAddUnsafeModifier { -// Add extern modifier to method -------------------------------------------------- +// Add extern modifier to method #[cfg(cfail1)] trait TraitAddExternModifier { fn method(); @@ -318,7 +317,7 @@ trait TraitAddExternModifier { -// Change extern "C" to extern "rust-intrinsic" ----------------------------------- +// Change extern "C" to extern "stdcall" #[cfg(cfail1)] trait TraitChangeExternCToRustIntrinsic { extern "C" fn method(); @@ -330,12 +329,12 @@ trait TraitChangeExternCToRustIntrinsic { trait TraitChangeExternCToRustIntrinsic { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - extern "rust-intrinsic" fn method(); + extern "stdcall" fn method(); } -// Add type parameter to method --------------------------------------------------- +// Add type parameter to method #[cfg(cfail1)] trait TraitAddTypeParameterToMethod { fn method(); @@ -352,7 +351,7 @@ trait TraitAddTypeParameterToMethod { -// Add lifetime parameter to method ----------------------------------------------- +// Add lifetime parameter to method #[cfg(cfail1)] trait TraitAddLifetimeParameterToMethod { fn method(); @@ -373,7 +372,7 @@ trait TraitAddLifetimeParameterToMethod { trait ReferencedTrait0 { } trait ReferencedTrait1 { } -// Add trait bound to method type parameter --------------------------------------- +// Add trait bound to method type parameter #[cfg(cfail1)] trait TraitAddTraitBoundToMethodTypeParameter { fn method(); @@ -390,7 +389,7 @@ trait TraitAddTraitBoundToMethodTypeParameter { -// Add builtin bound to method type parameter ------------------------------------- +// Add builtin bound to method type parameter #[cfg(cfail1)] trait TraitAddBuiltinBoundToMethodTypeParameter { fn method(); @@ -407,7 +406,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { -// Add lifetime bound to method lifetime parameter ------------------------------------ +// Add lifetime bound to method lifetime parameter #[cfg(cfail1)] trait TraitAddLifetimeBoundToMethodLifetimeParameter { fn method<'a, 'b>(a: &'a u32, b: &'b u32); @@ -424,7 +423,7 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { -// Add second trait bound to method type parameter -------------------------------- +// Add second trait bound to method type parameter #[cfg(cfail1)] trait TraitAddSecondTraitBoundToMethodTypeParameter { fn method(); @@ -441,7 +440,7 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { -// Add second builtin bound to method type parameter ------------------------------ +// Add second builtin bound to method type parameter #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { fn method(); @@ -458,7 +457,7 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { -// Add second lifetime bound to method lifetime parameter ----------------------------- +// Add second lifetime bound to method lifetime parameter #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32); @@ -475,7 +474,7 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { -// Add associated type ------------------------------------------------------------ +// Add associated type #[cfg(cfail1)] trait TraitAddAssociatedType { @@ -495,7 +494,7 @@ trait TraitAddAssociatedType { -// Add trait bound to associated type --------------------------------------------- +// Add trait bound to associated type #[cfg(cfail1)] trait TraitAddTraitBoundToAssociatedType { type Associated; @@ -519,7 +518,7 @@ trait TraitAddTraitBoundToAssociatedType { -// Add lifetime bound to associated type ------------------------------------------ +// Add lifetime bound to associated type #[cfg(cfail1)] trait TraitAddLifetimeBoundToAssociatedType<'a> { type Associated; @@ -540,7 +539,7 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { -// Add default to associated type ------------------------------------------------- +// Add default to associated type #[cfg(cfail1)] trait TraitAddDefaultToAssociatedType { type Associated; @@ -561,7 +560,7 @@ trait TraitAddDefaultToAssociatedType { -// Add associated constant -------------------------------------------------------- +// Add associated constant #[cfg(cfail1)] trait TraitAddAssociatedConstant { fn method(); @@ -578,7 +577,7 @@ trait TraitAddAssociatedConstant { -// Add initializer to associated constant ----------------------------------------- +// Add initializer to associated constant #[cfg(cfail1)] trait TraitAddInitializerToAssociatedConstant { const Value: u32; @@ -601,7 +600,7 @@ trait TraitAddInitializerToAssociatedConstant { -// Change type of associated constant --------------------------------------------- +// Change type of associated constant #[cfg(cfail1)] trait TraitChangeTypeOfAssociatedConstant { const Value: u32; @@ -624,7 +623,7 @@ trait TraitChangeTypeOfAssociatedConstant { -// Add super trait ---------------------------------------------------------------- +// Add super trait #[cfg(cfail1)] trait TraitAddSuperTrait { } @@ -635,7 +634,7 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } -// Add builtin bound (Send or Copy) ----------------------------------------------- +// Add builtin bound (Send or Copy) #[cfg(cfail1)] trait TraitAddBuiltiBound { } @@ -646,7 +645,7 @@ trait TraitAddBuiltiBound : Send { } -// Add 'static lifetime bound to trait -------------------------------------------- +// Add 'static lifetime bound to trait #[cfg(cfail1)] trait TraitAddStaticLifetimeBound { } @@ -657,7 +656,7 @@ trait TraitAddStaticLifetimeBound : 'static { } -// Add super trait as second bound ------------------------------------------------ +// Add super trait as second bound #[cfg(cfail1)] trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } @@ -676,7 +675,7 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } -// Add builtin bound as second bound ---------------------------------------------- +// Add builtin bound as second bound #[cfg(cfail1)] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } @@ -695,7 +694,7 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } -// Add 'static bounds as second bound --------------------------------------------- +// Add 'static bounds as second bound #[cfg(cfail1)] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } @@ -714,7 +713,7 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } -// Add type parameter to trait ---------------------------------------------------- +// Add type parameter to trait #[cfg(cfail1)] trait TraitAddTypeParameterToTrait { } @@ -725,7 +724,7 @@ trait TraitAddTypeParameterToTrait { } -// Add lifetime parameter to trait ------------------------------------------------ +// Add lifetime parameter to trait #[cfg(cfail1)] trait TraitAddLifetimeParameterToTrait { } @@ -736,7 +735,7 @@ trait TraitAddLifetimeParameterToTrait<'a> { } -// Add trait bound to type parameter of trait ------------------------------------- +// Add trait bound to type parameter of trait #[cfg(cfail1)] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -747,7 +746,7 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } -// Add lifetime bound to type parameter of trait ---------------------------------- +// Add lifetime bound to type parameter of trait #[cfg(cfail1)] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } @@ -758,7 +757,7 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } -// Add lifetime bound to lifetime parameter of trait ------------------------------ +// Add lifetime bound to lifetime parameter of trait #[cfg(cfail1)] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } @@ -769,7 +768,7 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } -// Add builtin bound to type parameter of trait ----------------------------------- +// Add builtin bound to type parameter of trait #[cfg(cfail1)] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -780,7 +779,7 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } -// Add second type parameter to trait --------------------------------------------- +// Add second type parameter to trait #[cfg(cfail1)] trait TraitAddSecondTypeParameterToTrait { } @@ -791,7 +790,7 @@ trait TraitAddSecondTypeParameterToTrait { } -// Add second lifetime parameter to trait ----------------------------------------- +// Add second lifetime parameter to trait #[cfg(cfail1)] trait TraitAddSecondLifetimeParameterToTrait<'a> { } @@ -802,7 +801,7 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } -// Add second trait bound to type parameter of trait ------------------------------ +// Add second trait bound to type parameter of trait #[cfg(cfail1)] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -813,7 +812,7 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -824,7 +823,7 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } -// Add second lifetime bound to lifetime parameter of trait------------------------ +// Add second lifetime bound to lifetime parameter of trait #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } @@ -835,7 +834,7 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> -// Add second builtin bound to type parameter of trait ---------------------------- +// Add second builtin bound to type parameter of trait #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -846,13 +845,12 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } -// -------------------------------------------------------------------------------- struct ReferenceType0 {} struct ReferenceType1 {} -// Add trait bound to type parameter of trait in where clause---------------------- +// Add trait bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } @@ -863,7 +861,7 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 -// Add lifetime bound to type parameter of trait in where clause------------------- +// Add lifetime bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } @@ -874,7 +872,7 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } -// Add lifetime bound to lifetime parameter of trait in where clause--------------- +// Add lifetime bound to lifetime parameter of trait in where clause #[cfg(cfail1)] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } @@ -885,7 +883,7 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b -// Add builtin bound to type parameter of trait in where clause-------------------- +// Add builtin bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } @@ -896,7 +894,7 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } -// Add second trait bound to type parameter of trait in where clause--------------- +// Add second trait bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -908,7 +906,7 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere -// Add second lifetime bound to type parameter of trait in where clause------------ +// Add second lifetime bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } @@ -919,7 +917,7 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: -// Add second lifetime bound to lifetime parameter of trait in where clause-------- +// Add second lifetime bound to lifetime parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } @@ -930,7 +928,7 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe -// Add second builtin bound to type parameter of trait in where clause------------- +// Add second builtin bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -940,7 +938,7 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } -// Change return type of method indirectly by modifying a use statement------------ +// Change return type of method indirectly by modifying a use statement mod change_return_type_of_method_indirectly_use { #[cfg(cfail1)] use super::ReferenceType0 as ReturnType; @@ -958,7 +956,7 @@ mod change_return_type_of_method_indirectly_use { -// Change type of method parameter indirectly by modifying a use statement--------- +// Change type of method parameter indirectly by modifying a use statement mod change_method_parameter_type_indirectly_by_use { #[cfg(cfail1)] use super::ReferenceType0 as ArgType; diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 39b28ec190..da3c957741 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_condition() { let mut _x = 0; @@ -60,7 +60,7 @@ pub fn change_loop_condition() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -128,7 +128,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -178,7 +178,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -205,7 +205,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 0607218546..3be42e7a4e 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_condition() { let mut _x = 0; @@ -60,7 +60,7 @@ pub fn change_loop_condition() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -128,7 +128,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -178,7 +178,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -205,7 +205,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index d9fa3d3d47..8dc6b73edf 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -57,25 +57,18 @@ impl Drop for S { // } // // bb5: { -// drop(_4) -> [return: bb8, unwind: bb6]; +// StorageDead(_4); +// StorageDead(_3); +// _0 = (); +// drop(_1) -> bb8; // } -// // bb6 (cleanup): { // drop(_1) -> bb1; // } -// // bb7 (cleanup): { // drop(_4) -> bb6; // } -// // bb8: { -// StorageDead(_4); -// StorageDead(_3); -// _0 = (); -// drop(_1) -> bb9; -// } -// -// bb9: { // StorageDead(_1); // return; // } diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs index bcdb937542..109304d6d2 100644 --- a/src/test/mir-opt/generator-storage-dead-unwind.rs +++ b/src/test/mir-opt/generator-storage-dead-unwind.rs @@ -57,7 +57,7 @@ fn main() { // StorageLive(_6); // StorageLive(_7); // _7 = move _2; -// _6 = const take::(move _7) -> [return: bb9, unwind: bb8]; +// _6 = const take::(move _7) -> [return: bb7, unwind: bb9]; // } // bb3 (cleanup): { // StorageDead(_2); @@ -75,17 +75,7 @@ fn main() { // bb6: { // generator_drop; // } -// bb7 (cleanup): { -// StorageDead(_3); -// StorageDead(_2); -// drop(_1) -> bb1; -// } -// bb8 (cleanup): { -// StorageDead(_7); -// StorageDead(_6); -// goto -> bb7; -// } -// bb9: { +// bb7: { // StorageDead(_7); // StorageDead(_6); // StorageLive(_8); @@ -93,6 +83,16 @@ fn main() { // _9 = move _3; // _8 = const take::(move _9) -> [return: bb10, unwind: bb11]; // } +// bb8 (cleanup): { +// StorageDead(_3); +// StorageDead(_2); +// drop(_1) -> bb1; +// } +// bb9 (cleanup): { +// StorageDead(_7); +// StorageDead(_6); +// goto -> bb8; +// } // bb10: { // StorageDead(_9); // StorageDead(_8); @@ -104,7 +104,7 @@ fn main() { // bb11 (cleanup): { // StorageDead(_9); // StorageDead(_8); -// goto -> bb7; +// goto -> bb8; // } // bb12: { // return; diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs index 18e0642eb3..c898d3a6f1 100644 --- a/src/test/mir-opt/match-arm-scopes.rs +++ b/src/test/mir-opt/match-arm-scopes.rs @@ -8,8 +8,6 @@ // all of the bindings for that scope. // * No drop flags are used. -#![feature(nll, bind_by_move_pattern_guards)] - fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 { match items { (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1, diff --git a/src/test/mir-opt/no-spurious-drop-after-call.rs b/src/test/mir-opt/no-spurious-drop-after-call.rs new file mode 100644 index 0000000000..782bc31186 --- /dev/null +++ b/src/test/mir-opt/no-spurious-drop-after-call.rs @@ -0,0 +1,24 @@ +// ignore-wasm32-bare compiled with panic=abort by default + +// Test that after the call to `std::mem::drop` we do not generate a +// MIR drop of the argument. (We used to have a `DROP(_2)` in the code +// below, as part of bb3.) + +fn main() { + std::mem::drop("".to_string()); +} + +// END RUST SOURCE +// START rustc.main.ElaborateDrops.before.mir +// bb2: { +// StorageDead(_3); +// _1 = const std::mem::drop::(move _2) -> [return: bb3, unwind: bb4]; +// } +// bb3: { +// StorageDead(_2); +// StorageDead(_4); +// StorageDead(_1); +// _0 = (); +// return; +// } +// END rustc.main.ElaborateDrops.before.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 33ee0fe61b..db36a1fab5 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -1,3 +1,4 @@ +// ignore-wasm32-bare compiled with panic=abort by default // ignore-tidy-linelength // compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats @@ -11,6 +12,10 @@ impl Test { fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x } } +impl Drop for Test { + fn drop(&mut self) {} +} + fn main() { let mut x = 0; { @@ -60,10 +65,12 @@ fn main() { // ... // bb0: { // ... -// _3 = const Test::foo(move _4, move _6) -> bb1; +// _3 = const Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3]; // } // -// bb1: { +// ... +// +// bb2: { // Retag(_3); // ... // _9 = move _3; @@ -80,25 +87,20 @@ fn main() { // _12 = move _13 as *mut i32 (Misc); // Retag([raw] _12); // ... -// _16 = move _17(move _18) -> bb2; +// _16 = move _17(move _18) -> bb5; // } // -// bb2: { +// bb5: { // Retag(_16); // ... -// _20 = const Test::foo_shr(move _21, move _23) -> bb3; -// } -// -// bb3: { -// ... -// return; +// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7]; // } // // ... // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 { +// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(22), local_id: 72 }], _2: &i32) -> &i32 { // ... // bb0: { // Retag([fn entry] _1); @@ -113,3 +115,17 @@ fn main() { // } // } // END rustc.main-{{closure}}.EraseRegions.after.mir +// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir +// fn std::ptr::real_drop_in_place(_1: &mut Test) -> () { +// ... +// bb0: { +// Retag([raw] _1); +// _2 = &mut (*_1); +// _3 = const ::drop(move _2) -> bb1; +// } +// +// bb1: { +// return; +// } +// } +// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir diff --git a/src/test/pretty/macro.rs b/src/test/pretty/macro.rs index 39677d1dc2..1e1e1dbfb3 100644 --- a/src/test/pretty/macro.rs +++ b/src/test/pretty/macro.rs @@ -2,6 +2,6 @@ #![feature(decl_macro)] -macro mac { ($ arg : expr) => { $ arg + $ arg } } +pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } } fn main() { } diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 02d93238dd..619cce685d 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -259,8 +259,6 @@ fn _12() { } } -///////////////// - fn foo() { } fn foo3(_: i32, _: (), _: ()) { } fn qux(_: i32) { } diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile index a0bc8cf668..8339e230bb 100644 --- a/src/test/run-make-fulldeps/libtest-json/Makefile +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -2,13 +2,17 @@ # Test expected libtest's JSON output -OUTPUT_FILE := $(TMPDIR)/libtest-json-output.json +OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json +OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json all: $(RUSTC) --test f.rs - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true - cat $(OUTPUT_FILE) | "$(PYTHON)" validate_json.py + cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_json.py + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_json.py # Compare to output file - diff output.json $(OUTPUT_FILE) + diff output-default.json $(OUTPUT_FILE_DEFAULT) + diff output-stdout-success.json $(OUTPUT_FILE_STDOUT_SUCCESS) diff --git a/src/test/run-make-fulldeps/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs index f5e44c2c24..95ff36bd76 100644 --- a/src/test/run-make-fulldeps/libtest-json/f.rs +++ b/src/test/run-make-fulldeps/libtest-json/f.rs @@ -1,11 +1,12 @@ #[test] fn a() { + println!("print from successful test"); // Should pass } #[test] fn b() { - assert!(false) + assert!(false); } #[test] diff --git a/src/test/run-make-fulldeps/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output-default.json similarity index 91% rename from src/test/run-make-fulldeps/libtest-json/output.json rename to src/test/run-make-fulldeps/libtest-json/output-default.json index 0caf268aa0..8046d72221 100644 --- a/src/test/run-make-fulldeps/libtest-json/output.json +++ b/src/test/run-make-fulldeps/libtest-json/output-default.json @@ -2,7 +2,7 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:8:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json new file mode 100644 index 0000000000..303316278d --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json @@ -0,0 +1,10 @@ +{ "type": "suite", "event": "started", "test_count": 4 } +{ "type": "test", "event": "started", "name": "a" } +{ "type": "test", "name": "a", "event": "ok", "stdout": "print from successful test\n" } +{ "type": "test", "event": "started", "name": "b" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } +{ "type": "test", "event": "started", "name": "c" } +{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" } +{ "type": "test", "event": "started", "name": "d" } +{ "type": "test", "name": "d", "event": "ignored" } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0 } diff --git a/src/test/run-make-fulldeps/lto-empty/Makefile b/src/test/run-make-fulldeps/lto-empty/Makefile new file mode 100644 index 0000000000..345d10bc4b --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: cdylib-fat cdylib-thin + +cdylib-fat: + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + +cdylib-thin: + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + diff --git a/src/test/run-make-fulldeps/lto-empty/lib.rs b/src/test/run-make-fulldeps/lto-empty/lib.rs new file mode 100644 index 0000000000..e3663c7907 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/lib.rs @@ -0,0 +1 @@ +#![crate_type = "cdylib"] diff --git a/src/test/run-make-fulldeps/reproducible-build-2/Makefile b/src/test/run-make-fulldeps/reproducible-build-2/Makefile index b96954fea0..45c9a74272 100644 --- a/src/test/run-make-fulldeps/reproducible-build-2/Makefile +++ b/src/test/run-make-fulldeps/reproducible-build-2/Makefile @@ -5,7 +5,8 @@ # Objects are reproducible but their path is not. all: \ - fat_lto + fat_lto \ + sysroot fat_lto: rm -rf $(TMPDIR) && mkdir $(TMPDIR) @@ -14,3 +15,12 @@ fat_lto: cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a $(RUSTC) reproducible-build.rs -C lto=fat cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1 + +sysroot: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot + cp -r $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 3b4df73cdf..9a113b7fa6 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -12,7 +12,7 @@ RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR) ifdef RUSTC_LINKER RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER) -RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options +RUSTDOC := $(RUSTDOC) -Clinker=$(RUSTC_LINKER) endif #CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs index 42445b9056..93c47d32f9 100644 --- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs +++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![allow(dead_code)] // check dtor calling order when casting enums. diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs index 925ffe75fe..fb2b4d4763 100644 --- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - // This would previously leak the Box because we wouldn't // schedule cleanups when auto borrowing trait objects. // This program should be valgrind clean. diff --git a/src/test/run-pass-valgrind/cleanup-stdin.rs b/src/test/run-pass-valgrind/cleanup-stdin.rs index 3505074293..cf8f81cf5a 100644 --- a/src/test/run-pass-valgrind/cleanup-stdin.rs +++ b/src/test/run-pass-valgrind/cleanup-stdin.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - fn main() { let _ = std::io::stdin(); let _ = std::io::stdout(); diff --git a/src/test/run-pass-valgrind/down-with-thread-dtors.rs b/src/test/run-pass-valgrind/down-with-thread-dtors.rs index c3567a9b20..8531b8d832 100644 --- a/src/test/run-pass-valgrind/down-with-thread-dtors.rs +++ b/src/test/run-pass-valgrind/down-with-thread-dtors.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // ignore-emscripten thread_local!(static FOO: Foo = Foo); diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 7533a7bd23..5b8433f614 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - static mut DROP_RAN: bool = false; struct Foo; diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index ebf0c17fec..991fe00950 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - static mut DROP_RAN: isize = 0; struct Foo; diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs index e15908dfcc..f0c2dda5ab 100644 --- a/src/test/run-pass-valgrind/dst-dtor-3.rs +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![feature(unsized_tuple_coercion)] static mut DROP_RAN: bool = false; diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs index 52bf0c364b..ad6d46f7c0 100644 --- a/src/test/run-pass-valgrind/dst-dtor-4.rs +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![feature(unsized_tuple_coercion)] static mut DROP_RAN: isize = 0; diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs index cd5edb84bd..a68c6f3355 100644 --- a/src/test/run-pass-valgrind/exit-flushes.rs +++ b/src/test/run-pass-valgrind/exit-flushes.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // ignore-cloudabi // ignore-emscripten // ignore-sgx no processes diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs index 4ea804a184..ea1403645a 100644 --- a/src/test/run-pass-valgrind/osx-frameworks.rs +++ b/src/test/run-pass-valgrind/osx-frameworks.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // pretty-expanded FIXME #23616 #![feature(rustc_private)] diff --git a/src/test/rustdoc-js-std/vec-new.js b/src/test/rustdoc-js-std/vec-new.js index e4daa5065d..e1a3256876 100644 --- a/src/test/rustdoc-js-std/vec-new.js +++ b/src/test/rustdoc-js-std/vec-new.js @@ -4,5 +4,6 @@ const EXPECTED = { 'others': [ { 'path': 'std::vec::Vec', 'name': 'new' }, { 'path': 'std::vec::Vec', 'name': 'ne' }, + { 'path': 'std::rc::Rc', 'name': 'ne' }, ], }; diff --git a/src/test/rustdoc-js/exact-match.js b/src/test/rustdoc-js/exact-match.js new file mode 100644 index 0000000000..b0a411bee5 --- /dev/null +++ b/src/test/rustdoc-js/exact-match.js @@ -0,0 +1,9 @@ +const QUERY = 'si::pc'; + +const EXPECTED = { + 'others': [ + { 'path': 'exact_match::Si', 'name': 'pc' }, + { 'path': 'exact_match::Psi', 'name': 'pc' }, + { 'path': 'exact_match::Si', 'name': 'pa' }, + ], +}; diff --git a/src/test/rustdoc-js/exact-match.rs b/src/test/rustdoc-js/exact-match.rs new file mode 100644 index 0000000000..2eacc0a358 --- /dev/null +++ b/src/test/rustdoc-js/exact-match.rs @@ -0,0 +1,68 @@ +macro_rules! imp { + ($name:ident) => { + pub struct $name { + pub op: usize, + } + impl $name { + pub fn op() {} + pub fn cmp() {} + pub fn map() {} + pub fn pop() {} + pub fn ptr() {} + pub fn rpo() {} + pub fn drop() {} + pub fn copy() {} + pub fn zip() {} + pub fn sup() {} + pub fn pa() {} + pub fn pb() {} + pub fn pc() {} + pub fn pd() {} + pub fn pe() {} + pub fn pf() {} + pub fn pg() {} + pub fn ph() {} + pub fn pi() {} + pub fn pj() {} + pub fn pk() {} + pub fn pl() {} + pub fn pm() {} + pub fn pn() {} + pub fn po() {} + } + }; + ($name:ident, $($names:ident),*) => { + imp!($name); + imp!($($names),*); + }; +} +macro_rules! en { + ($name:ident) => { + pub enum $name { + Ptr, + Rp, + Rpo, + Pt, + Drop, + Dr, + Dro, + Sup, + Op, + Cmp, + Map, + Mp, + } + }; + ($name:ident, $($names:ident),*) => { + en!($name); + en!($($names),*); + }; +} + +imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd); +imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp); +imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp); + +en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); + +pub struct P; diff --git a/src/test/rustdoc-js/module-substring.js b/src/test/rustdoc-js/module-substring.js new file mode 100644 index 0000000000..a446c39eba --- /dev/null +++ b/src/test/rustdoc-js/module-substring.js @@ -0,0 +1,9 @@ +const QUERY = 'ig::pc'; + +const EXPECTED = { + 'others': [ + { 'path': 'module_substring::Sig', 'name': 'pc' }, + { 'path': 'module_substring::Si', 'name': 'pc' }, + { 'path': 'module_substring::Si', 'name': 'pa' }, + ], +}; diff --git a/src/test/rustdoc-js/module-substring.rs b/src/test/rustdoc-js/module-substring.rs new file mode 100644 index 0000000000..2eacc0a358 --- /dev/null +++ b/src/test/rustdoc-js/module-substring.rs @@ -0,0 +1,68 @@ +macro_rules! imp { + ($name:ident) => { + pub struct $name { + pub op: usize, + } + impl $name { + pub fn op() {} + pub fn cmp() {} + pub fn map() {} + pub fn pop() {} + pub fn ptr() {} + pub fn rpo() {} + pub fn drop() {} + pub fn copy() {} + pub fn zip() {} + pub fn sup() {} + pub fn pa() {} + pub fn pb() {} + pub fn pc() {} + pub fn pd() {} + pub fn pe() {} + pub fn pf() {} + pub fn pg() {} + pub fn ph() {} + pub fn pi() {} + pub fn pj() {} + pub fn pk() {} + pub fn pl() {} + pub fn pm() {} + pub fn pn() {} + pub fn po() {} + } + }; + ($name:ident, $($names:ident),*) => { + imp!($name); + imp!($($names),*); + }; +} +macro_rules! en { + ($name:ident) => { + pub enum $name { + Ptr, + Rp, + Rpo, + Pt, + Drop, + Dr, + Dro, + Sup, + Op, + Cmp, + Map, + Mp, + } + }; + ($name:ident, $($names:ident),*) => { + en!($name); + en!($($names),*); + }; +} + +imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd); +imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp); +imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp); + +en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); + +pub struct P; diff --git a/src/test/rustdoc-js/search-short-types.js b/src/test/rustdoc-js/search-short-types.js index 0ebf4860cf..d14672af71 100644 --- a/src/test/rustdoc-js/search-short-types.js +++ b/src/test/rustdoc-js/search-short-types.js @@ -3,6 +3,8 @@ const QUERY = 'P'; const EXPECTED = { 'others': [ { 'path': 'search_short_types', 'name': 'P' }, + { 'path': 'search_short_types::VeryLongTypeName', 'name': 'p' }, { 'path': 'search_short_types', 'name': 'Ap' }, + { 'path': 'search_short_types::VeryLongTypeName', 'name': 'ap' }, ], }; diff --git a/src/test/rustdoc-js/search-short-types.rs b/src/test/rustdoc-js/search-short-types.rs index 2eacc0a358..a4083f9a76 100644 --- a/src/test/rustdoc-js/search-short-types.rs +++ b/src/test/rustdoc-js/search-short-types.rs @@ -66,3 +66,9 @@ imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); pub struct P; + +pub struct VeryLongTypeName; +impl VeryLongTypeName { + pub fn p() {} + pub fn ap() {} +} diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs index d2cdeb8f8f..fcbd7cabc6 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.rs +++ b/src/test/rustdoc-ui/failed-doctest-output.rs @@ -3,6 +3,7 @@ // adapted to use that, and that normalize line can go away // compile-flags:--test +// rustc-env:RUST_BACKTRACE=0 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // failure-status: 101 diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index e362ecf349..ef1b419f52 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -1,13 +1,13 @@ running 2 tests -test $DIR/failed-doctest-output.rs - OtherStruct (line 20) ... FAILED -test $DIR/failed-doctest-output.rs - SomeStruct (line 10) ... FAILED +test $DIR/failed-doctest-output.rs - OtherStruct (line 21) ... FAILED +test $DIR/failed-doctest-output.rs - SomeStruct (line 11) ... FAILED failures: ----- $DIR/failed-doctest-output.rs - OtherStruct (line 20) stdout ---- +---- $DIR/failed-doctest-output.rs - OtherStruct (line 21) stdout ---- error[E0425]: cannot find value `no` in this scope - --> $DIR/failed-doctest-output.rs:21:1 + --> $DIR/failed-doctest-output.rs:22:1 | 3 | no | ^^ not found in this scope @@ -16,7 +16,7 @@ error: aborting due to previous error For more information about this error, try `rustc --explain E0425`. Couldn't compile the test. ----- $DIR/failed-doctest-output.rs - SomeStruct (line 10) stdout ---- +---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ---- Test executable failed (exit code 101). stdout: @@ -32,8 +32,8 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. failures: - $DIR/failed-doctest-output.rs - OtherStruct (line 20) - $DIR/failed-doctest-output.rs - SomeStruct (line 10) + $DIR/failed-doctest-output.rs - OtherStruct (line 21) + $DIR/failed-doctest-output.rs - SomeStruct (line 11) test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs index 2b02d47d4b..97a0f4aaec 100644 --- a/src/test/rustdoc-ui/invalid-syntax.rs +++ b/src/test/rustdoc-ui/invalid-syntax.rs @@ -64,3 +64,21 @@ pub fn blargh() {} /// \_ #[doc = "```"] pub fn crazy_attrs() {} + +/// ```rust +/// ``` +pub fn empty_rust() {} + +/// ``` +/// +/// +/// ``` +pub fn empty_rust_with_whitespace() {} + +/// ``` +/// let x = 1; +/// ``` +/// +/// \____/ +/// +pub fn indent_after_fenced() {} diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 3bebbecb9d..6f50edae65 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -179,6 +179,46 @@ LL | | #[doc = "```"] | = help: mark blocks that do not contain Rust code as text: ```text +warning: Rust code block is empty + --> $DIR/invalid-syntax.rs:68:5 + | +LL | /// ```rust + | _____^ +LL | | /// ``` + | |_______^ + +warning: Rust code block is empty + --> $DIR/invalid-syntax.rs:72:5 + | +LL | /// ``` + | _____^ +LL | | /// +LL | | /// +LL | | /// ``` + | |_______^ +help: mark blocks that do not contain Rust code as text + | +LL | /// ```text + | ^^^^^^^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \____/ + | ^ + +warning: could not parse code block as Rust code + --> $DIR/invalid-syntax.rs:82:9 + | +LL | /// \____/ + | ^^^^^^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \____/ + | ^ + error: unknown start of token: \ --> :1:1 | diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index ee622e74a0..bb6af7995a 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -95,5 +95,5 @@ impl Qux for Bar { /// Docs for QUX_DEFAULT1 in impl. const QUX_DEFAULT1: i16 = 7; // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32' - // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait." + // @has - '//*[@class="docblock hidden"]' "Docs for QUX_DEFAULT2 in trait." } diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 7384f7027d..5f9708a397 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option' pub async fn foo() -> Option { None diff --git a/src/test/rustdoc/async-move-doctest.rs b/src/test/rustdoc/async-move-doctest.rs index 4272313278..2ba61388c9 100644 --- a/src/test/rustdoc/async-move-doctest.rs +++ b/src/test/rustdoc/async-move-doctest.rs @@ -1,13 +1,11 @@ // compile-flags:--test // edition:2018 -// prior to setting the default edition for the doctest pre-parser, this doctest would fail due to -// a fatal parsing error +// Prior to setting the default edition for the doctest pre-parser, +// this doctest would fail due to a fatal parsing error. // see https://github.com/rust-lang/rust/issues/59313 //! ``` -//! #![feature(async_await)] -//! //! fn foo() { //! drop(async move {}); //! } diff --git a/src/test/rustdoc/edition-flag.rs b/src/test/rustdoc/edition-flag.rs index 5571245f28..ddbc2be651 100644 --- a/src/test/rustdoc/edition-flag.rs +++ b/src/test/rustdoc/edition-flag.rs @@ -1,10 +1,7 @@ // compile-flags:--test -Z unstable-options // edition:2018 -#![feature(async_await)] - /// ```rust -/// #![feature(async_await)] /// fn main() { /// let _ = async { }; /// } diff --git a/src/test/rustdoc/inline_cross/assoc-items.rs b/src/test/rustdoc/inline_cross/assoc-items.rs index d4f05bab5c..7eb3e43cb1 100644 --- a/src/test/rustdoc/inline_cross/assoc-items.rs +++ b/src/test/rustdoc/inline_cross/assoc-items.rs @@ -16,15 +16,15 @@ extern crate assoc_items; // @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16' // @has - '//*[@class="docblock"]' 'dox for ConstNoDefault' // @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16' -// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault' +// @has - '//*[@class="docblock hidden"]' 'docs for ConstWithDefault' // @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault = i32' // @has - '//*[@class="docblock"]' 'dox for TypeNoDefault' // @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32' -// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault' +// @has - '//*[@class="docblock hidden"]' 'docs for TypeWithDefault' // @has - '//*[@id="method.method_no_default"]' 'fn method_no_default()' // @has - '//*[@class="docblock"]' 'dox for method_no_default' // @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()' -// @has - '//*[@class="docblock"]' 'docs for method_with_default' +// @has - '//*[@class="docblock hidden"]' 'docs for method_with_default' pub use assoc_items::MyStruct; // @has foo/trait.MyTrait.html diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs new file mode 100644 index 0000000000..913ba8f2a1 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -0,0 +1,28 @@ +// edition:2018 + +use std::ops::Deref; + +pub fn func<'a>(_x: impl Clone + Into> + 'a) {} + +pub fn func2( + _x: impl Deref> + Iterator, + _y: impl Iterator, +) {} + +pub fn func3(_x: impl Iterator> + Clone) {} + +pub fn func4>(_x: T) {} + +pub async fn async_fn() {} + +pub struct Foo; + +impl Foo { + pub fn method<'a>(_x: impl Clone + Into> + 'a) {} +} + +pub struct Bar; + +impl Bar { + pub async fn async_foo(&self) {} +} diff --git a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs index c99ef74433..37465ccf1c 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro #![crate_type="proc-macro"] #![crate_name="some_macros"] @@ -25,3 +26,9 @@ pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn some_derive(_item: TokenStream) -> TokenStream { TokenStream::new() } + +/// Doc comment from the original crate +#[proc_macro] +pub fn reexported_macro(_input: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs index cadeccb60c..4591bb526a 100644 --- a/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs +++ b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs @@ -8,5 +8,5 @@ extern crate impl_inline_without_trait; // @has 'foo/struct.MyStruct.html' // @has - '//*[@id="method.my_trait_method"]' 'fn my_trait_method()' -// @has - '//*[@class="docblock"]' 'docs for my_trait_method' +// @has - '//*[@class="docblock hidden"]' 'docs for my_trait_method' pub use impl_inline_without_trait::MyStruct; diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs new file mode 100644 index 0000000000..6f4a48c83c --- /dev/null +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -0,0 +1,40 @@ +// aux-build:impl_trait_aux.rs +// edition:2018 + +extern crate impl_trait_aux; + +// @has impl_trait/fn.func.html +// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func; + +// @has impl_trait/fn.func2.html +// @has - '//pre[@class="rust fn"]' "func2(" +// @has - '//pre[@class="rust fn"]' "_x: impl Deref> + Iterator," +// @has - '//pre[@class="rust fn"]' "_y: impl Iterator)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func2; + +// @has impl_trait/fn.func3.html +// @has - '//pre[@class="rust fn"]' "func3(" +// @has - '//pre[@class="rust fn"]' "_x: impl Clone + Iterator>)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func3; + +// @has impl_trait/fn.func4.html +// @has - '//pre[@class="rust fn"]' "func4(" +// @has - '//pre[@class="rust fn"]' "T: Iterator," +pub use impl_trait_aux::func4; + +// @has impl_trait/fn.async_fn.html +// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()" +pub use impl_trait_aux::async_fn; + +// @has impl_trait/struct.Foo.html +// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" +// @!has - '//code[@id="method.v"]' 'where' +pub use impl_trait_aux::Foo; + +// @has impl_trait/struct.Bar.html +// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo(" +pub use impl_trait_aux::Bar; diff --git a/src/test/rustdoc/inline_cross/proc_macro.rs b/src/test/rustdoc/inline_cross/proc_macro.rs index e1cdcf4940..3dc8de3fe5 100644 --- a/src/test/rustdoc/inline_cross/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/proc_macro.rs @@ -1,16 +1,28 @@ // aux-build:proc_macro.rs // build-aux-docs -// FIXME: if/when proc-macros start exporting their doc attributes across crates, we can turn on -// cross-crate inlining for them - extern crate some_macros; // @has proc_macro/index.html -// @has - '//a/@href' '../some_macros/macro.some_proc_macro.html' -// @has - '//a/@href' '../some_macros/attr.some_proc_attr.html' -// @has - '//a/@href' '../some_macros/derive.SomeDerive.html' -// @!has proc_macro/macro.some_proc_macro.html -// @!has proc_macro/attr.some_proc_attr.html -// @!has proc_macro/derive.SomeDerive.html -pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive}; +// @has - '//a/@href' 'macro.some_proc_macro.html' +// @has - '//a/@href' 'attr.some_proc_attr.html' +// @has - '//a/@href' 'derive.SomeDerive.html' +// @has proc_macro/macro.some_proc_macro.html +// @has proc_macro/attr.some_proc_attr.html +// @has proc_macro/derive.SomeDerive.html + +// @has proc_macro/macro.some_proc_macro.html +// @has - 'a proc-macro that swallows its input and does nothing.' +pub use some_macros::some_proc_macro; + +// @has proc_macro/macro.reexported_macro.html +// @has - 'Doc comment from the original crate' +pub use some_macros::reexported_macro; + +// @has proc_macro/attr.some_proc_attr.html +// @has - 'a proc-macro attribute that passes its item through verbatim.' +pub use some_macros::some_proc_attr; + +// @has proc_macro/derive.SomeDerive.html +// @has - 'a derive attribute that adds nothing to its input.' +pub use some_macros::SomeDerive; diff --git a/src/test/rustdoc/manual_impl.rs b/src/test/rustdoc/manual_impl.rs index c9e4f4e0d3..11ddab5f7f 100644 --- a/src/test/rustdoc/manual_impl.rs +++ b/src/test/rustdoc/manual_impl.rs @@ -24,10 +24,10 @@ pub trait T { // @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait implementation.' // @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait a_method implementation.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait b_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait c_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait b_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait c_method definition.' // @!has - '//*[@class="docblock"]' 'There is another line' -// @has - '//*[@class="docblock"]' 'Read more' +// @has - '//*[@class="docblock hidden"]' 'Read more' pub struct S1(usize); /// Docs associated with the S1 trait implementation. @@ -44,7 +44,7 @@ impl T for S1 { // @has - '//*[@class="docblock"]' 'Docs associated with the S2 trait c_method implementation.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait c_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait b_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait b_method definition.' pub struct S2(usize); /// Docs associated with the S2 trait implementation. diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs index 4bd0b092b5..82196e413e 100644 --- a/src/test/rustdoc/proc-macro.rs +++ b/src/test/rustdoc/proc-macro.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro --document-private-items #![crate_type="proc-macro"] #![crate_name="some_macros"] @@ -58,7 +59,7 @@ pub fn some_derive(_item: TokenStream) -> TokenStream { } // @has some_macros/foo/index.html -pub mod foo { +mod foo { // @has - '//code' 'pub use some_proc_macro;' // @has - '//a/@href' '../../some_macros/macro.some_proc_macro.html' pub use some_proc_macro; diff --git a/src/test/rustdoc/rustc-macro-crate.rs b/src/test/rustdoc/rustc-macro-crate.rs index 2f6308b20c..dd5edc984d 100644 --- a/src/test/rustdoc/rustc-macro-crate.rs +++ b/src/test/rustdoc/rustc-macro-crate.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro #![crate_type = "proc-macro"] diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index c2685c7f74..c053c71524 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc_driver; -extern crate rustc_plugin; extern crate syntax; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ext::base::SyntaxExtension; use syntax::feature_gate::AttributeType; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index ad42ee1d1e..6fb99b2c98 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -3,11 +3,10 @@ #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::attr; use syntax::ext::base::*; use syntax::feature_gate::AttributeType::Whitelisted; diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 2826ae75be..17386d7e1a 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -4,12 +4,11 @@ #![feature(box_syntax)] #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index a811edd37c..000e10392e 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -4,12 +4,11 @@ #![feature(box_syntax)] #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index 3206ddee62..a377b07bd3 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -6,12 +6,11 @@ // Load rustc as a plugin to get macros. #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::hir; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index 4d57be49ca..02675191f7 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -8,12 +8,11 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index ea7c75fbbe..40f8d490ac 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -6,11 +6,10 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); declare_tool_lint!( diff --git a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs b/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs index 1832fee434..2ff1c2e363 100644 --- a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs b/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs index 6e446241d5..89bc9a2b9d 100644 --- a/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(_reg: &mut Registry) {} diff --git a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs b/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs index d9b2740e47..ee82c0adc8 100644 --- a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs +++ b/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs @@ -6,7 +6,6 @@ extern crate syntax; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax_pos; extern crate proc_macro; diff --git a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs index c22605afd0..e5c4f5b8f7 100644 --- a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs +++ b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs @@ -4,12 +4,11 @@ #![feature(box_syntax, rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use std::any::Any; use std::cell::RefCell; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; struct Foo { foo: isize diff --git a/src/test/ui-fulldeps/auxiliary/plugin-args.rs b/src/test/ui-fulldeps/auxiliary/plugin-args.rs index f3cd2397b2..5ff24cff23 100644 --- a/src/test/ui-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/ui-fulldeps/auxiliary/plugin-args.rs @@ -6,7 +6,6 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use std::borrow::ToOwned; @@ -17,7 +16,7 @@ use syntax::print::pprust; use syntax::symbol::Symbol; use syntax_pos::Span; use syntax::tokenstream::TokenStream; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; struct Expander { args: Vec, diff --git a/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs b/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs index 7a91b54bf6..1c0de98da5 100644 --- a/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs +++ b/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs @@ -4,10 +4,9 @@ #![feature(plugin_registrar, rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(_: &mut Registry) {} diff --git a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs index 77fa5c2cd7..2b57e9289b 100644 --- a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs +++ b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs @@ -12,16 +12,15 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use syntax::parse::token::{self, Token}; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream) -> Box { static NUMERALS: &'static [(&'static str, usize)] = &[ @@ -37,7 +36,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) return DummyResult::any(sp); } - let text = match args[0] { + let text = match args.into_trees().next().unwrap() { TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); diff --git a/src/test/ui-fulldeps/compiler-calls.rs b/src/test/ui-fulldeps/compiler-calls.rs index ea24f5809d..bd9113c707 100644 --- a/src/test/ui-fulldeps/compiler-calls.rs +++ b/src/test/ui-fulldeps/compiler-calls.rs @@ -24,7 +24,7 @@ impl rustc_driver::Callbacks for TestCalls<'_> { fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::report_ices_to_stderr_if_any(|| { + rustc_driver::catch_fatal_errors(|| { rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }, None, None).ok(); }).ok(); assert_eq!(count, 2); diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs index 9f67f642df..d79ef62c31 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs @@ -13,3 +13,5 @@ use rustc_macros::HashStable; #[derive(HashStable)] //~^ use of unstable library feature 'rustc_private' struct Test; + +fn main() {} diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr index 02056d30ea..e2dc0c3be7 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `hash_stable_is_unstable` - | - = note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs` - error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? --> $DIR/hash-stable-is-unstable.rs:3:1 | @@ -47,7 +43,6 @@ LL | #[derive(HashStable)] = note: for more information, see https://github.com/rust-lang/rust/issues/27812 = help: add `#![feature(rustc_private)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0601, E0658. -For more information about an error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 09f58521e5..596f515da2 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -32,13 +32,15 @@ use syntax::print::pprust; use syntax::ptr::P; -fn parse_expr(ps: &ParseSess, src: &str) -> P { +fn parse_expr(ps: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); - let mut p = parse::new_parser_from_source_str(ps, - FileName::Custom(src_as_string.clone()), - src_as_string); - p.parse_expr().unwrap() + let mut p = parse::new_parser_from_source_str( + ps, + FileName::Custom(src_as_string.clone()), + src_as_string, + ); + p.parse_expr().map_err(|mut e| e.cancel()).ok() } @@ -150,12 +152,12 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e))); }, 19 => { - let ps = vec![P(Pat { + let pat = P(Pat { id: DUMMY_NODE_ID, node: PatKind::Wild, span: DUMMY_SP, - })]; - iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(ps.clone(), e))) + }); + iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e))) }, _ => panic!("bad counter value in iter_exprs"), } @@ -209,22 +211,23 @@ fn run() { let printed = pprust::expr_to_string(&e); println!("printed: {}", printed); - let mut parsed = parse_expr(&ps, &printed); - - // We want to know if `parsed` is structurally identical to `e`, ignoring trivial - // differences like placement of `Paren`s or the exact ranges of node spans. - // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s - // everywhere we can, then pretty-print. This should give an unambiguous representation of - // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't - // relying on the correctness of the very thing we're testing. - RemoveParens.visit_expr(&mut e); - AddParens.visit_expr(&mut e); - let text1 = pprust::expr_to_string(&e); - RemoveParens.visit_expr(&mut parsed); - AddParens.visit_expr(&mut parsed); - let text2 = pprust::expr_to_string(&parsed); - assert!(text1 == text2, - "exprs are not equal:\n e = {:?}\n parsed = {:?}", - text1, text2); + // Ignore expressions with chained comparisons that fail to parse + if let Some(mut parsed) = parse_expr(&ps, &printed) { + // We want to know if `parsed` is structurally identical to `e`, ignoring trivial + // differences like placement of `Paren`s or the exact ranges of node spans. + // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s + // everywhere we can, then pretty-print. This should give an unambiguous representation + // of each `Expr`, and it bypasses nearly all of the parenthesization logic, so we + // aren't relying on the correctness of the very thing we're testing. + RemoveParens.visit_expr(&mut e); + AddParens.visit_expr(&mut e); + let text1 = pprust::expr_to_string(&e); + RemoveParens.visit_expr(&mut parsed); + AddParens.visit_expr(&mut parsed); + let text2 = pprust::expr_to_string(&parsed); + assert!(text1 == text2, + "exprs are not equal:\n e = {:?}\n parsed = {:?}", + text1, text2); + } }); } diff --git a/src/test/ui/abi-sysv64-arg-passing.rs b/src/test/ui/abi/abi-sysv64-arg-passing.rs similarity index 100% rename from src/test/ui/abi-sysv64-arg-passing.rs rename to src/test/ui/abi/abi-sysv64-arg-passing.rs diff --git a/src/test/ui/abi-sysv64-register-usage.rs b/src/test/ui/abi/abi-sysv64-register-usage.rs similarity index 100% rename from src/test/ui/abi-sysv64-register-usage.rs rename to src/test/ui/abi/abi-sysv64-register-usage.rs diff --git a/src/test/ui/abort-on-c-abi.rs b/src/test/ui/abi/abort-on-c-abi.rs similarity index 100% rename from src/test/ui/abort-on-c-abi.rs rename to src/test/ui/abi/abort-on-c-abi.rs diff --git a/src/test/ui/anon-extern-mod.rs b/src/test/ui/abi/anon-extern-mod.rs similarity index 100% rename from src/test/ui/anon-extern-mod.rs rename to src/test/ui/abi/anon-extern-mod.rs diff --git a/src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs similarity index 100% rename from src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs rename to src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs similarity index 100% rename from src/test/ui/auxiliary/foreign_lib.rs rename to src/test/ui/abi/auxiliary/foreign_lib.rs diff --git a/src/test/ui/c-stack-as-value.rs b/src/test/ui/abi/c-stack-as-value.rs similarity index 100% rename from src/test/ui/c-stack-as-value.rs rename to src/test/ui/abi/c-stack-as-value.rs diff --git a/src/test/ui/cabi-int-widening.rs b/src/test/ui/abi/cabi-int-widening.rs similarity index 100% rename from src/test/ui/cabi-int-widening.rs rename to src/test/ui/abi/cabi-int-widening.rs diff --git a/src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs similarity index 100% rename from src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs rename to src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs b/src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs similarity index 100% rename from src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs rename to src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs diff --git a/src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs similarity index 100% rename from src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs rename to src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/duplicated-external-mods.rs b/src/test/ui/abi/duplicated-external-mods.rs similarity index 100% rename from src/test/ui/duplicated-external-mods.rs rename to src/test/ui/abi/duplicated-external-mods.rs diff --git a/src/test/ui/extern/auxiliary/extern-crosscrate-source.rs b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs similarity index 100% rename from src/test/ui/extern/auxiliary/extern-crosscrate-source.rs rename to src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs diff --git a/src/test/ui/extern/extern-call-deep.rs b/src/test/ui/abi/extern/extern-call-deep.rs similarity index 100% rename from src/test/ui/extern/extern-call-deep.rs rename to src/test/ui/abi/extern/extern-call-deep.rs diff --git a/src/test/ui/extern/extern-call-deep2.rs b/src/test/ui/abi/extern/extern-call-deep2.rs similarity index 100% rename from src/test/ui/extern/extern-call-deep2.rs rename to src/test/ui/abi/extern/extern-call-deep2.rs diff --git a/src/test/ui/extern/extern-call-direct.rs b/src/test/ui/abi/extern/extern-call-direct.rs similarity index 100% rename from src/test/ui/extern/extern-call-direct.rs rename to src/test/ui/abi/extern/extern-call-direct.rs diff --git a/src/test/ui/extern/extern-call-indirect.rs b/src/test/ui/abi/extern/extern-call-indirect.rs similarity index 100% rename from src/test/ui/extern/extern-call-indirect.rs rename to src/test/ui/abi/extern/extern-call-indirect.rs diff --git a/src/test/ui/extern/extern-call-scrub.rs b/src/test/ui/abi/extern/extern-call-scrub.rs similarity index 100% rename from src/test/ui/extern/extern-call-scrub.rs rename to src/test/ui/abi/extern/extern-call-scrub.rs diff --git a/src/test/ui/extern/extern-crosscrate.rs b/src/test/ui/abi/extern/extern-crosscrate.rs similarity index 100% rename from src/test/ui/extern/extern-crosscrate.rs rename to src/test/ui/abi/extern/extern-crosscrate.rs diff --git a/src/test/ui/extern/extern-pass-TwoU16s.rs b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs similarity index 100% rename from src/test/ui/extern/extern-pass-TwoU16s.rs rename to src/test/ui/abi/extern/extern-pass-TwoU16s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU32s.rs b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs similarity index 100% rename from src/test/ui/extern/extern-pass-TwoU32s.rs rename to src/test/ui/abi/extern/extern-pass-TwoU32s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU64s.rs b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs similarity index 100% rename from src/test/ui/extern/extern-pass-TwoU64s.rs rename to src/test/ui/abi/extern/extern-pass-TwoU64s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU8s.rs b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs similarity index 100% rename from src/test/ui/extern/extern-pass-TwoU8s.rs rename to src/test/ui/abi/extern/extern-pass-TwoU8s.rs diff --git a/src/test/ui/extern/extern-pass-char.rs b/src/test/ui/abi/extern/extern-pass-char.rs similarity index 100% rename from src/test/ui/extern/extern-pass-char.rs rename to src/test/ui/abi/extern/extern-pass-char.rs diff --git a/src/test/ui/extern/extern-pass-double.rs b/src/test/ui/abi/extern/extern-pass-double.rs similarity index 100% rename from src/test/ui/extern/extern-pass-double.rs rename to src/test/ui/abi/extern/extern-pass-double.rs diff --git a/src/test/ui/extern/extern-pass-empty.rs b/src/test/ui/abi/extern/extern-pass-empty.rs similarity index 100% rename from src/test/ui/extern/extern-pass-empty.rs rename to src/test/ui/abi/extern/extern-pass-empty.rs diff --git a/src/test/ui/extern/extern-pass-u32.rs b/src/test/ui/abi/extern/extern-pass-u32.rs similarity index 100% rename from src/test/ui/extern/extern-pass-u32.rs rename to src/test/ui/abi/extern/extern-pass-u32.rs diff --git a/src/test/ui/extern/extern-pass-u64.rs b/src/test/ui/abi/extern/extern-pass-u64.rs similarity index 100% rename from src/test/ui/extern/extern-pass-u64.rs rename to src/test/ui/abi/extern/extern-pass-u64.rs diff --git a/src/test/ui/extern/extern-return-TwoU16s.rs b/src/test/ui/abi/extern/extern-return-TwoU16s.rs similarity index 100% rename from src/test/ui/extern/extern-return-TwoU16s.rs rename to src/test/ui/abi/extern/extern-return-TwoU16s.rs diff --git a/src/test/ui/extern/extern-return-TwoU32s.rs b/src/test/ui/abi/extern/extern-return-TwoU32s.rs similarity index 100% rename from src/test/ui/extern/extern-return-TwoU32s.rs rename to src/test/ui/abi/extern/extern-return-TwoU32s.rs diff --git a/src/test/ui/extern/extern-return-TwoU64s.rs b/src/test/ui/abi/extern/extern-return-TwoU64s.rs similarity index 100% rename from src/test/ui/extern/extern-return-TwoU64s.rs rename to src/test/ui/abi/extern/extern-return-TwoU64s.rs diff --git a/src/test/ui/extern/extern-return-TwoU8s.rs b/src/test/ui/abi/extern/extern-return-TwoU8s.rs similarity index 100% rename from src/test/ui/extern/extern-return-TwoU8s.rs rename to src/test/ui/abi/extern/extern-return-TwoU8s.rs diff --git a/src/test/ui/foreign/auxiliary/foreign_lib.rs b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs similarity index 100% rename from src/test/ui/foreign/auxiliary/foreign_lib.rs rename to src/test/ui/abi/foreign/auxiliary/foreign_lib.rs diff --git a/src/test/ui/foreign/foreign-call-no-runtime.rs b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs similarity index 100% rename from src/test/ui/foreign/foreign-call-no-runtime.rs rename to src/test/ui/abi/foreign/foreign-call-no-runtime.rs diff --git a/src/test/ui/foreign/foreign-dupe.rs b/src/test/ui/abi/foreign/foreign-dupe.rs similarity index 100% rename from src/test/ui/foreign/foreign-dupe.rs rename to src/test/ui/abi/foreign/foreign-dupe.rs diff --git a/src/test/ui/foreign/foreign-fn-with-byval.rs b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs similarity index 100% rename from src/test/ui/foreign/foreign-fn-with-byval.rs rename to src/test/ui/abi/foreign/foreign-fn-with-byval.rs diff --git a/src/test/ui/foreign/foreign-no-abi.rs b/src/test/ui/abi/foreign/foreign-no-abi.rs similarity index 100% rename from src/test/ui/foreign/foreign-no-abi.rs rename to src/test/ui/abi/foreign/foreign-no-abi.rs diff --git a/src/test/ui/invoke-external-foreign.rs b/src/test/ui/abi/invoke-external-foreign.rs similarity index 100% rename from src/test/ui/invoke-external-foreign.rs rename to src/test/ui/abi/invoke-external-foreign.rs diff --git a/src/test/ui/lib-defaults.rs b/src/test/ui/abi/lib-defaults.rs similarity index 100% rename from src/test/ui/lib-defaults.rs rename to src/test/ui/abi/lib-defaults.rs diff --git a/src/test/ui/macros/macros-in-extern.rs b/src/test/ui/abi/macros/macros-in-extern.rs similarity index 100% rename from src/test/ui/macros/macros-in-extern.rs rename to src/test/ui/abi/macros/macros-in-extern.rs diff --git a/src/test/ui/macros/macros-in-extern.stderr b/src/test/ui/abi/macros/macros-in-extern.stderr similarity index 100% rename from src/test/ui/macros/macros-in-extern.stderr rename to src/test/ui/abi/macros/macros-in-extern.stderr diff --git a/src/test/ui/mir/mir_codegen_calls_variadic.rs b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs similarity index 100% rename from src/test/ui/mir/mir_codegen_calls_variadic.rs rename to src/test/ui/abi/mir/mir_codegen_calls_variadic.rs diff --git a/src/test/ui/numbers-arithmetic/i128-ffi.rs b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs similarity index 100% rename from src/test/ui/numbers-arithmetic/i128-ffi.rs rename to src/test/ui/abi/numbers-arithmetic/i128-ffi.rs diff --git a/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs new file mode 100644 index 0000000000..27efa44f98 --- /dev/null +++ b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs @@ -0,0 +1,112 @@ +// force-host +// no-prefer-dynamic + +// Proc macros commonly used by tests. +// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +// Macro that return empty token stream. + +#[proc_macro] +pub fn empty(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(Empty, attributes(empty_helper))] +pub fn empty_derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +// Macro that panics. + +#[proc_macro] +pub fn panic_bang(_: TokenStream) -> TokenStream { + panic!("panic-bang"); +} + +#[proc_macro_attribute] +pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream { + panic!("panic-attr"); +} + +#[proc_macro_derive(Panic, attributes(panic_helper))] +pub fn panic_derive(_: TokenStream) -> TokenStream { + panic!("panic-derive"); +} + +// Macros that return the input stream. + +#[proc_macro] +pub fn identity(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Identity, attributes(identity_helper))] +pub fn identity_derive(input: TokenStream) -> TokenStream { + input +} + +// Macros that iterate and re-collect the input stream. + +#[proc_macro] +pub fn recollect(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_derive(Recollect, attributes(recollect_helper))] +pub fn recollect_derive(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +// Macros that print their input in the original and re-collected forms (if they differ). + +fn print_helper(input: TokenStream, kind: &str) -> TokenStream { + let input_display = format!("{}", input); + let input_debug = format!("{:#?}", input); + let recollected = input.into_iter().collect(); + let recollected_display = format!("{}", recollected); + let recollected_debug = format!("{:#?}", recollected); + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); + if recollected_display != input_display { + println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); + } + println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); + if recollected_debug != input_debug { + println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); + } + recollected +} + +#[proc_macro] +pub fn print_bang(input: TokenStream) -> TokenStream { + print_helper(input, "BANG") +} + +#[proc_macro_attribute] +pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream { + print_helper(input, "ATTR") +} + +#[proc_macro_derive(Print, attributes(print_helper))] +pub fn print_derive(input: TokenStream) -> TokenStream { + print_helper(input, "DERIVE") +} diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/abi/proc-macro/macros-in-extern.rs similarity index 100% rename from src/test/ui/proc-macro/macros-in-extern.rs rename to src/test/ui/abi/proc-macro/macros-in-extern.rs diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/abi/proc-macro/macros-in-extern.stderr similarity index 100% rename from src/test/ui/proc-macro/macros-in-extern.stderr rename to src/test/ui/abi/proc-macro/macros-in-extern.stderr diff --git a/src/test/ui/segfault-no-out-of-stack.rs b/src/test/ui/abi/segfault-no-out-of-stack.rs similarity index 100% rename from src/test/ui/segfault-no-out-of-stack.rs rename to src/test/ui/abi/segfault-no-out-of-stack.rs diff --git a/src/test/ui/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs similarity index 100% rename from src/test/ui/stack-probes-lto.rs rename to src/test/ui/abi/stack-probes-lto.rs diff --git a/src/test/ui/stack-probes.rs b/src/test/ui/abi/stack-probes.rs similarity index 100% rename from src/test/ui/stack-probes.rs rename to src/test/ui/abi/stack-probes.rs diff --git a/src/test/ui/statics/static-mut-foreign.rs b/src/test/ui/abi/statics/static-mut-foreign.rs similarity index 100% rename from src/test/ui/statics/static-mut-foreign.rs rename to src/test/ui/abi/statics/static-mut-foreign.rs diff --git a/src/test/ui/structs-enums/struct-return.rs b/src/test/ui/abi/struct-enums/struct-return.rs similarity index 100% rename from src/test/ui/structs-enums/struct-return.rs rename to src/test/ui/abi/struct-enums/struct-return.rs diff --git a/src/test/ui/union/union-c-interop.rs b/src/test/ui/abi/union/union-c-interop.rs similarity index 100% rename from src/test/ui/union/union-c-interop.rs rename to src/test/ui/abi/union/union-c-interop.rs diff --git a/src/test/ui/variadic-ffi.rs b/src/test/ui/abi/variadic-ffi.rs similarity index 100% rename from src/test/ui/variadic-ffi.rs rename to src/test/ui/abi/variadic-ffi.rs diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs new file mode 100644 index 0000000000..9bd8406a27 --- /dev/null +++ b/src/test/ui/allocator/hygiene.rs @@ -0,0 +1,31 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +#![allow(nonstandard_style)] + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[allow(dead_code)] +struct u8; +#[allow(dead_code)] +struct usize; +#[allow(dead_code)] +static arg0: () = (); + +#[global_allocator] +pub static GLOBAL: A = A(AtomicUsize::new(0)); + +fn main() { + let n = GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/src/test/ui/anon-params-denied-2018.rs b/src/test/ui/anon-params-denied-2018.rs index abff827506..5721f5d235 100644 --- a/src/test/ui/anon-params-denied-2018.rs +++ b/src/test/ui/anon-params-denied-2018.rs @@ -3,7 +3,7 @@ // edition:2018 trait T { - fn foo(i32); //~ expected one of `:` or `@`, found `)` + fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)` fn bar_with_default_impl(String, String) {} //~^ ERROR expected one of `:` diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr index 438bcf4274..a58998e489 100644 --- a/src/test/ui/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params-denied-2018.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:6:15 | LL | fn foo(i32); - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -14,11 +14,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo(_: i32); | ^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:8:36 | LL | fn bar_with_default_impl(String, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -30,11 +30,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn bar_with_default_impl(_: String, String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:8:44 | LL | fn bar_with_default_impl(String, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -46,11 +46,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn bar_with_default_impl(String, _: String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:13:22 | LL | fn baz(a:usize, b, c: usize) -> usize { - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index 0ca3ca8437..fbe2d192d0 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -5,12 +5,9 @@ LL | f1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _` - | -note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 - | +... LL | fn f1(_: F) where F: Fn(&(), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------ required by this bound in `f1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 @@ -19,12 +16,9 @@ LL | f1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &()) -> _` - | -note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 - | +... LL | fn f1(_: F) where F: Fn(&(), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------ required by this bound in `f1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 @@ -33,12 +27,9 @@ LL | f2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _` - | -note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 - | +... LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ----------------------- required by this bound in `f2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 @@ -47,12 +38,9 @@ LL | f2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'a (), &()) -> _` - | -note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 - | +... LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------- required by this bound in `f2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 @@ -61,12 +49,9 @@ LL | f3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&(), &'r ()) -> _` - | -note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 - | +... LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------- required by this bound in `f3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 @@ -75,12 +60,9 @@ LL | f3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &()) -> _` - | -note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 - | +... LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------- required by this bound in `f3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 @@ -89,12 +71,9 @@ LL | f4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _` - | -note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 - | +... LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ----------------------- required by this bound in `f4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 @@ -103,12 +82,9 @@ LL | f4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &'r ()) -> _` - | -note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 - | +... LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------- required by this bound in `f4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 @@ -117,12 +93,9 @@ LL | f5(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), &'r ()) -> _` - | -note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 - | +... LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- -------------------------- required by this bound in `f5` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 @@ -131,12 +104,9 @@ LL | f5(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'r (), &'r ()) -> _` - | -note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 - | +... LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------------ required by this bound in `f5` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 @@ -145,12 +115,9 @@ LL | g1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _` - | -note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 - | +... LL | fn g1(_: F) where F: Fn(&(), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------------------- required by this bound in `g1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 @@ -159,12 +126,9 @@ LL | g1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 - | +... LL | fn g1(_: F) where F: Fn(&(), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------------------- required by this bound in `g1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 @@ -173,12 +137,9 @@ LL | g2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _` - | -note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 - | +... LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ---------------- required by this bound in `g2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 @@ -187,12 +148,9 @@ LL | g2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` - | -note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 - | +... LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ---------------- required by this bound in `g2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 @@ -201,12 +159,9 @@ LL | g3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 - | +... LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------------------------------ required by this bound in `g3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 @@ -215,12 +170,9 @@ LL | g3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 - | +... LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ---------------------------- required by this bound in `g3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 @@ -229,12 +181,9 @@ LL | g4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` - | -note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 - | +... LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------------------- required by this bound in `g4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 @@ -243,12 +192,9 @@ LL | g4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` - | -note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 - | +... LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------------------- required by this bound in `g4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 @@ -257,12 +203,9 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _` - | -note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 - | +... LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- -------------------------------------------- required by this bound in `h1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 @@ -271,12 +214,9 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _` - | -note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 - | +... LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- -------------------------------------------- required by this bound in `h1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 @@ -285,12 +225,9 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _` - | -note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 - | +... LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- --------------------------------------------------------- required by this bound in `h2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 @@ -299,12 +236,9 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` - | -note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 - | +... LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ------------------------------------------------ required by this bound in `h2` error: aborting due to 22 previous errors diff --git a/src/test/ui/array-break-length.rs b/src/test/ui/array-break-length.rs index 2696aea5e8..959f4a2bab 100644 --- a/src/test/ui/array-break-length.rs +++ b/src/test/ui/array-break-length.rs @@ -1,11 +1,11 @@ fn main() { loop { - |_: [_; break]| {} //~ ERROR: `break` outside of loop + |_: [_; break]| {} //~ ERROR: `break` outside of a loop //~^ ERROR mismatched types } loop { - |_: [_; continue]| {} //~ ERROR: `continue` outside of loop + |_: [_; continue]| {} //~ ERROR: `continue` outside of a loop //~^ ERROR mismatched types } } diff --git a/src/test/ui/array-break-length.stderr b/src/test/ui/array-break-length.stderr index 0e0dc8f623..45f529bafe 100644 --- a/src/test/ui/array-break-length.stderr +++ b/src/test/ui/array-break-length.stderr @@ -1,14 +1,14 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/array-break-length.rs:3:17 | LL | |_: [_; break]| {} - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/array-break-length.rs:8:17 | LL | |_: [_; continue]| {} - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop error[E0308]: mismatched types --> $DIR/array-break-length.rs:3:9 diff --git a/src/test/ui/asm/asm-out-read-uninit.rs b/src/test/ui/asm/asm-out-read-uninit.rs index 003f1fc5bb..78458ff60d 100644 --- a/src/test/ui/asm/asm-out-read-uninit.rs +++ b/src/test/ui/asm/asm-out-read-uninit.rs @@ -20,7 +20,7 @@ pub fn main() { let x: isize; unsafe { asm!("mov $1, $0" : "=r"(x) : "r"(x)); - //~^ ERROR use of possibly uninitialized variable: `x` + //~^ ERROR use of possibly-uninitialized variable: `x` } foo(x); } diff --git a/src/test/ui/asm/asm-out-read-uninit.stderr b/src/test/ui/asm/asm-out-read-uninit.stderr index 6d0445d4b7..71aeda2ad4 100644 --- a/src/test/ui/asm/asm-out-read-uninit.stderr +++ b/src/test/ui/asm/asm-out-read-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/asm-out-read-uninit.rs:22:43 | LL | asm!("mov $1, $0" : "=r"(x) : "r"(x)); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-array-len.stderr b/src/test/ui/associated-const/associated-const-array-len.stderr index ff56d112c8..2fdfa3da30 100644 --- a/src/test/ui/associated-const/associated-const-array-len.stderr +++ b/src/test/ui/associated-const/associated-const-array-len.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/associated-const-array-len.rs:5:16 | +LL | const ID: usize; + | ---------------- required by `Foo::ID` +... LL | const X: [i32; ::ID] = [0, 1, 2]; | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `Foo::ID` - --> $DIR/associated-const-array-len.rs:2:5 - | -LL | const ID: usize; - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.stderr b/src/test/ui/associated-const/associated-const-generic-obligations.stderr index eeee26a756..ca6118cb3b 100644 --- a/src/test/ui/associated-const/associated-const-generic-obligations.stderr +++ b/src/test/ui/associated-const/associated-const-generic-obligations.stderr @@ -9,6 +9,8 @@ LL | const FROM: &'static str = "foo"; | = note: expected type `::Out` found type `&'static str` + = note: consider constraining the associated type `::Out` to `&'static str` or calling a method that returns `::Out` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-in-trait.stderr b/src/test/ui/associated-const/associated-const-in-trait.stderr index dff268a55c..a5d7fc5b70 100644 --- a/src/test/ui/associated-const/associated-const-in-trait.stderr +++ b/src/test/ui/associated-const/associated-const-in-trait.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/associated-const-in-trait.rs:9:6 | +LL | const N: usize; + | - the trait cannot contain associated consts like `N` +... LL | impl dyn Trait { | ^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot contain associated consts like `N` error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr index 573b8ed39b..30b6b4f390 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22 | +LL | const Y: usize; + | --------------- required by `Foo::Y` +... LL | let _array = [4; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | = help: consider adding a `where A: Foo` bound -note: required by `Foo::Y` - --> $DIR/associated-const-type-parameter-arrays-2.rs:2:5 - | -LL | const Y: usize; - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr index bf1ee38571..30fa9891a1 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/associated-const-type-parameter-arrays.rs:16:23 | +LL | const Y: usize; + | --------------- required by `Foo::Y` +... LL | let _array: [u32; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | = help: consider adding a `where A: Foo` bound -note: required by `Foo::Y` - --> $DIR/associated-const-type-parameter-arrays.rs:2:5 - | -LL | const Y: usize; - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs new file mode 100644 index 0000000000..a58cec5342 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -0,0 +1,32 @@ +// This test documents that `type Out = Box>;` +// is allowed and will correctly reject an opaque `type Out` which +// does not satisfy the bound `::Assoc: Copy`. +// +// FIXME(rust-lang/lang): I think this behavior is logical if we want to allow +// `dyn Trait` but we should decide if we want that. // Centril +// +// Additionally, as reported in https://github.com/rust-lang/rust/issues/63594, +// we check that the spans for the error message are sane here. + +#![feature(associated_type_bounds)] + +fn main() {} + +trait Bar { type Assoc; } + +trait Thing { + type Out; + fn func() -> Self::Out; +} + +struct AssocNoCopy; +impl Bar for AssocNoCopy { type Assoc = String; } + +impl Thing for AssocNoCopy { + type Out = Box>; + //~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied + + fn func() -> Self::Out { + Box::new(AssocNoCopy) + } +} diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr new file mode 100644 index 0000000000..b6b49c2e90 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28 + | +LL | type Out = Box>; + | ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` + | + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index aebf29cc33..06e8230aa1 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -24,6 +24,9 @@ LL | | } error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -35,15 +38,13 @@ LL | | } | = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Send` bound -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -55,15 +56,13 @@ LL | | } | = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Sync` bound -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug` --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -74,11 +73,6 @@ LL | | } | |_^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` | = help: the trait `for<'a> std::fmt::Debug` is not implemented for `<_ as Lam<&'a u8>>::App` -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index 9db5233e21..ceca54b7cd 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(associated_type_bounds)] diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index 1f2d755ed7..a89fd9807d 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -1,161 +1,184 @@ // compile-fail // ignore-tidy-linelength -// error-pattern:could not find defining uses #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] +#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash [incomplete_features] #![feature(untagged_unions)] use std::iter; struct SI1> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SI2> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SI3> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW1 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW2 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW3 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI1> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI2> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI3> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW1 where T: Iterator { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW2 where T: Iterator { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW3 where T: Iterator { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI1> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI2> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI3> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW1 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW2 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW3 where T: Iterator { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI1>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI2>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI3>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW1() where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW2() where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW3() where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT1() -> impl Iterator { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT2() -> impl Iterator { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT3() -> impl Iterator { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT1(_: impl Iterator) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT2(_: impl Iterator) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT3(_: impl Iterator) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT1: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT2: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT3: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT1: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT2: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT3: impl Iterator = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit1() { let _: impl Iterator = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit2() { let _: impl Iterator = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit3() { let _: impl Iterator = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI1> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI2> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI3> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW1 where T: Iterator = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW2 where T: Iterator = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW3 where T: Iterator = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type ETAI1> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI2> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI3> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI4 = impl Iterator; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI5 = impl Iterator; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI6 = impl Iterator; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses trait TRI1> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRI2> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRI3> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS1: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS2: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS3: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW1 where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW2 where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW3 where T: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW1 where Self: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW2 where Self: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW3 where Self: Iterator {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA1 { type A: Iterator; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA2 { type A: Iterator; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA3 { type A: Iterator; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TADyn1 = dyn Iterator; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type TADyn2 = Box>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type TADyn3 = dyn Iterator; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses fn main() {} diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index 7f3a65ab69..e5e85d6856 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/duplicate.rs:7:12 + --> $DIR/duplicate.rs:6:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:12:36 + --> $DIR/duplicate.rs:11:36 | LL | struct SI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -15,7 +15,7 @@ LL | struct SI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:14:36 + --> $DIR/duplicate.rs:13:36 | LL | struct SI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -23,7 +23,7 @@ LL | struct SI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:16:39 + --> $DIR/duplicate.rs:15:39 | LL | struct SI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -31,7 +31,7 @@ LL | struct SI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:18:45 + --> $DIR/duplicate.rs:17:45 | LL | struct SW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -39,7 +39,7 @@ LL | struct SW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:20:45 + --> $DIR/duplicate.rs:19:45 | LL | struct SW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -47,7 +47,7 @@ LL | struct SW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:22:48 + --> $DIR/duplicate.rs:21:48 | LL | struct SW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -55,7 +55,7 @@ LL | struct SW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:25:34 + --> $DIR/duplicate.rs:24:34 | LL | enum EI1> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -63,7 +63,7 @@ LL | enum EI1> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:27:34 + --> $DIR/duplicate.rs:26:34 | LL | enum EI2> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -71,7 +71,7 @@ LL | enum EI2> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:29:37 + --> $DIR/duplicate.rs:28:37 | LL | enum EI3> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -79,7 +79,7 @@ LL | enum EI3> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:31:43 + --> $DIR/duplicate.rs:30:43 | LL | enum EW1 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -87,7 +87,7 @@ LL | enum EW1 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:33:43 + --> $DIR/duplicate.rs:32:43 | LL | enum EW2 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -95,7 +95,7 @@ LL | enum EW2 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:35:46 + --> $DIR/duplicate.rs:34:46 | LL | enum EW3 where T: Iterator { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -103,7 +103,7 @@ LL | enum EW3 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:38:35 + --> $DIR/duplicate.rs:37:35 | LL | union UI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -111,7 +111,7 @@ LL | union UI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:40:35 + --> $DIR/duplicate.rs:39:35 | LL | union UI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -119,7 +119,7 @@ LL | union UI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:42:38 + --> $DIR/duplicate.rs:41:38 | LL | union UI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -127,7 +127,7 @@ LL | union UI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:44:44 + --> $DIR/duplicate.rs:43:44 | LL | union UW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -135,7 +135,7 @@ LL | union UW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:46:44 + --> $DIR/duplicate.rs:45:44 | LL | union UW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -143,7 +143,7 @@ LL | union UW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:48:47 + --> $DIR/duplicate.rs:47:47 | LL | union UW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -151,7 +151,7 @@ LL | union UW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:51:32 + --> $DIR/duplicate.rs:50:32 | LL | fn FI1>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -159,7 +159,7 @@ LL | fn FI1>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:53:32 + --> $DIR/duplicate.rs:52:32 | LL | fn FI2>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -167,7 +167,7 @@ LL | fn FI2>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:55:35 + --> $DIR/duplicate.rs:54:35 | LL | fn FI3>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -175,7 +175,7 @@ LL | fn FI3>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:57:43 + --> $DIR/duplicate.rs:56:43 | LL | fn FW1() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -183,7 +183,7 @@ LL | fn FW1() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:59:43 + --> $DIR/duplicate.rs:58:43 | LL | fn FW2() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -191,7 +191,7 @@ LL | fn FW2() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:61:46 + --> $DIR/duplicate.rs:60:46 | LL | fn FW3() where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -199,7 +199,7 @@ LL | fn FW3() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:70:40 + --> $DIR/duplicate.rs:69:40 | LL | fn FAPIT1(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -207,7 +207,7 @@ LL | fn FAPIT1(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:72:40 + --> $DIR/duplicate.rs:71:40 | LL | fn FAPIT2(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -215,7 +215,7 @@ LL | fn FAPIT2(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:74:43 + --> $DIR/duplicate.rs:73:43 | LL | fn FAPIT3(_: impl Iterator) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -223,7 +223,7 @@ LL | fn FAPIT3(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:64:42 + --> $DIR/duplicate.rs:63:42 | LL | fn FRPIT1() -> impl Iterator { iter::empty() } | ---------- ^^^^^^^^^^ re-bound here @@ -231,7 +231,7 @@ LL | fn FRPIT1() -> impl Iterator { iter::empty() } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:66:42 + --> $DIR/duplicate.rs:65:42 | LL | fn FRPIT2() -> impl Iterator { iter::empty() } | ---------- ^^^^^^^^^^ re-bound here @@ -239,7 +239,7 @@ LL | fn FRPIT2() -> impl Iterator { iter::empty() } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:68:45 + --> $DIR/duplicate.rs:67:45 | LL | fn FRPIT3() -> impl Iterator { iter::empty() } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -247,7 +247,7 @@ LL | fn FRPIT3() -> impl Iterator { iter::empty() | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:77:39 + --> $DIR/duplicate.rs:76:39 | LL | const CIT1: impl Iterator = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -255,7 +255,7 @@ LL | const CIT1: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:79:39 + --> $DIR/duplicate.rs:78:39 | LL | const CIT2: impl Iterator = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -263,7 +263,7 @@ LL | const CIT2: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:81:42 + --> $DIR/duplicate.rs:80:42 | LL | const CIT3: impl Iterator = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -271,7 +271,7 @@ LL | const CIT3: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:83:40 + --> $DIR/duplicate.rs:82:40 | LL | static SIT1: impl Iterator = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -279,7 +279,7 @@ LL | static SIT1: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:85:40 + --> $DIR/duplicate.rs:84:40 | LL | static SIT2: impl Iterator = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -287,7 +287,7 @@ LL | static SIT2: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:87:43 + --> $DIR/duplicate.rs:86:43 | LL | static SIT3: impl Iterator = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -295,7 +295,7 @@ LL | static SIT3: impl Iterator = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:90:46 + --> $DIR/duplicate.rs:89:46 | LL | fn lit1() { let _: impl Iterator = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -303,7 +303,7 @@ LL | fn lit1() { let _: impl Iterator = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:92:46 + --> $DIR/duplicate.rs:91:46 | LL | fn lit2() { let _: impl Iterator = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -311,7 +311,7 @@ LL | fn lit2() { let _: impl Iterator = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:94:49 + --> $DIR/duplicate.rs:93:49 | LL | fn lit3() { let _: impl Iterator = iter::empty(); } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -319,7 +319,7 @@ LL | fn lit3() { let _: impl Iterator = iter::empt | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:97:35 + --> $DIR/duplicate.rs:96:35 | LL | type TAI1> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -327,7 +327,7 @@ LL | type TAI1> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:99:35 + --> $DIR/duplicate.rs:98:35 | LL | type TAI2> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -335,7 +335,7 @@ LL | type TAI2> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:101:38 + --> $DIR/duplicate.rs:100:38 | LL | type TAI3> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -343,7 +343,7 @@ LL | type TAI3> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:103:44 + --> $DIR/duplicate.rs:102:44 | LL | type TAW1 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -351,7 +351,7 @@ LL | type TAW1 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:105:44 + --> $DIR/duplicate.rs:104:44 | LL | type TAW2 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -359,7 +359,7 @@ LL | type TAW2 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:107:47 + --> $DIR/duplicate.rs:106:47 | LL | type TAW3 where T: Iterator = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -367,13 +367,13 @@ LL | type TAW3 where T: Iterator = T; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:110:1 + --> $DIR/duplicate.rs:109:1 | LL | type ETAI1> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:110:36 + --> $DIR/duplicate.rs:109:36 | LL | type ETAI1> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -381,13 +381,13 @@ LL | type ETAI1> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:112:1 + --> $DIR/duplicate.rs:114:1 | LL | type ETAI2> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:112:36 + --> $DIR/duplicate.rs:114:36 | LL | type ETAI2> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -395,13 +395,13 @@ LL | type ETAI2> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:114:1 + --> $DIR/duplicate.rs:119:1 | LL | type ETAI3> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:114:39 + --> $DIR/duplicate.rs:119:39 | LL | type ETAI3> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -409,13 +409,13 @@ LL | type ETAI3> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:116:1 + --> $DIR/duplicate.rs:124:1 | LL | type ETAI4 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:116:40 + --> $DIR/duplicate.rs:124:40 | LL | type ETAI4 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -423,13 +423,13 @@ LL | type ETAI4 = impl Iterator; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:118:1 + --> $DIR/duplicate.rs:129:1 | LL | type ETAI5 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:118:40 + --> $DIR/duplicate.rs:129:40 | LL | type ETAI5 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -437,13 +437,13 @@ LL | type ETAI5 = impl Iterator; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:120:1 + --> $DIR/duplicate.rs:134:1 | LL | type ETAI6 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:120:43 + --> $DIR/duplicate.rs:134:43 | LL | type ETAI6 = impl Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -451,7 +451,7 @@ LL | type ETAI6 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:123:36 + --> $DIR/duplicate.rs:140:36 | LL | trait TRI1> {} | ---------- ^^^^^^^^^^ re-bound here @@ -459,7 +459,7 @@ LL | trait TRI1> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:125:36 + --> $DIR/duplicate.rs:142:36 | LL | trait TRI2> {} | ---------- ^^^^^^^^^^ re-bound here @@ -467,7 +467,7 @@ LL | trait TRI2> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:127:39 + --> $DIR/duplicate.rs:144:39 | LL | trait TRI3> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -475,7 +475,7 @@ LL | trait TRI3> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:129:34 + --> $DIR/duplicate.rs:146:34 | LL | trait TRS1: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -483,7 +483,7 @@ LL | trait TRS1: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:131:34 + --> $DIR/duplicate.rs:148:34 | LL | trait TRS2: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -491,7 +491,7 @@ LL | trait TRS2: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:133:37 + --> $DIR/duplicate.rs:150:37 | LL | trait TRS3: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -499,7 +499,7 @@ LL | trait TRS3: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:135:45 + --> $DIR/duplicate.rs:152:45 | LL | trait TRW1 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -507,7 +507,7 @@ LL | trait TRW1 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:137:45 + --> $DIR/duplicate.rs:154:45 | LL | trait TRW2 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -515,7 +515,7 @@ LL | trait TRW2 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:139:48 + --> $DIR/duplicate.rs:156:48 | LL | trait TRW3 where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -523,7 +523,7 @@ LL | trait TRW3 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:141:46 + --> $DIR/duplicate.rs:158:46 | LL | trait TRSW1 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -531,7 +531,7 @@ LL | trait TRSW1 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:143:46 + --> $DIR/duplicate.rs:160:46 | LL | trait TRSW2 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -539,7 +539,7 @@ LL | trait TRSW2 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:145:49 + --> $DIR/duplicate.rs:162:49 | LL | trait TRSW3 where Self: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -547,7 +547,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:147:43 + --> $DIR/duplicate.rs:164:43 | LL | trait TRA1 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -555,7 +555,7 @@ LL | trait TRA1 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:149:43 + --> $DIR/duplicate.rs:166:43 | LL | trait TRA2 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -563,7 +563,7 @@ LL | trait TRA2 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:151:46 + --> $DIR/duplicate.rs:168:46 | LL | trait TRA3 { type A: Iterator; } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -571,7 +571,7 @@ LL | trait TRA3 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:154:40 + --> $DIR/duplicate.rs:171:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -579,7 +579,7 @@ LL | type TADyn1 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:156:44 + --> $DIR/duplicate.rs:175:44 | LL | type TADyn2 = Box>; | ---------- ^^^^^^^^^^ re-bound here @@ -587,7 +587,7 @@ LL | type TADyn2 = Box>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:158:43 + --> $DIR/duplicate.rs:179:43 | LL | type TADyn3 = dyn Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -595,40 +595,112 @@ LL | type TADyn3 = dyn Iterator; | `Item` bound here first error: could not find defining uses + --> $DIR/duplicate.rs:109:24 + | +LL | type ETAI1> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:109:36 + | +LL | type ETAI1> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:114:24 + | +LL | type ETAI2> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:114:36 + | +LL | type ETAI2> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:119:24 + | +LL | type ETAI3> = impl Copy; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:119:39 + | +LL | type ETAI3> = impl Copy; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:124:28 + | +LL | type ETAI4 = impl Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:124:40 + | +LL | type ETAI4 = impl Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:129:28 + | +LL | type ETAI5 = impl Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:129:40 + | +LL | type ETAI5 = impl Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:134:28 + | +LL | type ETAI6 = impl Iterator; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:134:43 + | +LL | type ETAI6 = impl Iterator; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:171:28 + | +LL | type TADyn1 = dyn Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:171:40 + | +LL | type TADyn1 = dyn Iterator; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:175:32 + | +LL | type TADyn2 = Box>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:175:44 + | +LL | type TADyn2 = Box>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:179:28 + | +LL | type TADyn3 = dyn Iterator; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:179:43 + | +LL | type TADyn3 = dyn Iterator; + | ^^^^^^^^^^^^^ error: aborting due to 93 previous errors diff --git a/src/test/ui/associated-type-bounds/fn-apit.rs b/src/test/ui/associated-type-bounds/fn-apit.rs index 7e208b4e70..3c9f511338 100644 --- a/src/test/ui/associated-type-bounds/fn-apit.rs +++ b/src/test/ui/associated-type-bounds/fn-apit.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:fn-aux.rs +#![allow(unused)] #![feature(associated_type_bounds)] extern crate fn_aux; diff --git a/src/test/ui/associated-type-bounds/fn-dyn-apit.rs b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs index 9ff4a50e1e..c4e8092c21 100644 --- a/src/test/ui/associated-type-bounds/fn-dyn-apit.rs +++ b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:fn-dyn-aux.rs +#![allow(unused)] #![feature(associated_type_bounds)] extern crate fn_dyn_aux; diff --git a/src/test/ui/associated-type-bounds/fn-inline.rs b/src/test/ui/associated-type-bounds/fn-inline.rs index 7b188763b7..8fa7212d62 100644 --- a/src/test/ui/associated-type-bounds/fn-inline.rs +++ b/src/test/ui/associated-type-bounds/fn-inline.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:fn-aux.rs +#![allow(unused)] #![feature(associated_type_bounds)] extern crate fn_aux; diff --git a/src/test/ui/associated-type-bounds/fn-where.rs b/src/test/ui/associated-type-bounds/fn-where.rs index 60d7149a56..9c4f82ac99 100644 --- a/src/test/ui/associated-type-bounds/fn-where.rs +++ b/src/test/ui/associated-type-bounds/fn-where.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:fn-aux.rs +#![allow(unused)] #![feature(associated_type_bounds)] extern crate fn_aux; diff --git a/src/test/ui/associated-type-bounds/fn-wrap-apit.rs b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs index 23790d416e..96df13e372 100644 --- a/src/test/ui/associated-type-bounds/fn-wrap-apit.rs +++ b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs @@ -2,6 +2,7 @@ // aux-build:fn-aux.rs #![feature(associated_type_bounds)] +#![allow(dead_code)] extern crate fn_aux; diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs index 1257dc6e94..59ce9496d2 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.rs +++ b/src/test/ui/associated-type-bounds/inside-adt.rs @@ -1,36 +1,35 @@ // compile-fail -// ignore-tidy-linelength -// error-pattern:could not find defining uses - #![feature(associated_type_bounds)] #![feature(untagged_unions)] struct S1 { f: dyn Iterator } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses struct S2 { f: Box> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses struct S3 { f: dyn Iterator } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E1 { V(dyn Iterator) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E2 { V(Box>) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E3 { V(dyn Iterator) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U1 { f: dyn Iterator } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U2 { f: Box> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U3 { f: dyn Iterator } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr index 7bdd71b829..9c4d03e900 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.stderr +++ b/src/test/ui/associated-type-bounds/inside-adt.stderr @@ -1,79 +1,110 @@ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:8:29 + --> $DIR/inside-adt.rs:5:29 | LL | struct S1 { f: dyn Iterator } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:11:33 + --> $DIR/inside-adt.rs:8:33 | LL | struct S2 { f: Box> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:14:29 + --> $DIR/inside-adt.rs:11:29 | LL | struct S3 { f: dyn Iterator } | ^^^^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:18:26 + --> $DIR/inside-adt.rs:15:26 | LL | enum E1 { V(dyn Iterator) } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:21:30 + --> $DIR/inside-adt.rs:18:30 | LL | enum E2 { V(Box>) } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:24:26 + --> $DIR/inside-adt.rs:21:26 | LL | enum E3 { V(dyn Iterator) } | ^^^^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:28:28 + --> $DIR/inside-adt.rs:25:28 | LL | union U1 { f: dyn Iterator } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:31:32 + --> $DIR/inside-adt.rs:28:32 | LL | union U2 { f: Box> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:34:28 + --> $DIR/inside-adt.rs:31:28 | LL | union U3 { f: dyn Iterator } | ^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `inside_adt` - | - = note: consider adding a `main` function to `$DIR/inside-adt.rs` - error: could not find defining uses + --> $DIR/inside-adt.rs:5:29 + | +LL | struct S1 { f: dyn Iterator } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:8:33 + | +LL | struct S2 { f: Box> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:11:29 + | +LL | struct S3 { f: dyn Iterator } + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:15:26 + | +LL | enum E1 { V(dyn Iterator) } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:18:30 + | +LL | enum E2 { V(Box>) } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:21:26 + | +LL | enum E3 { V(dyn Iterator) } + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:25:28 + | +LL | union U1 { f: dyn Iterator } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:28:32 + | +LL | union U2 { f: Box> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:31:28 + | +LL | union U3 { f: dyn Iterator } + | ^^^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/associated-type-bounds/struct-bounds.rs b/src/test/ui/associated-type-bounds/struct-bounds.rs index 2d189cd667..2c1ce1c378 100644 --- a/src/test/ui/associated-type-bounds/struct-bounds.rs +++ b/src/test/ui/associated-type-bounds/struct-bounds.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(unused)] #![feature(associated_type_bounds)] trait Tr1 { type As1; } diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs index 06dfe490b8..7e05bcd309 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs @@ -12,30 +12,22 @@ pub trait Car : Vehicle { fn chip_paint(&self, c: Self::Color) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn dent(c: C, color: C::Color) { c.chip_paint(color) } fn a() { dent(ModelT, Black); } fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types fn c() { dent(ModelU, Black); } //~ ERROR mismatched types fn d() { dent(ModelU, Blue); } -/////////////////////////////////////////////////////////////////////////// - fn e() { ModelT.chip_paint(Black); } fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr index 06f1a1cc64..4ba4925ef1 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:33:23 + --> $DIR/associated-type-projection-from-supertrait.rs:27:23 | LL | fn b() { dent(ModelT, Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -8,7 +8,7 @@ LL | fn b() { dent(ModelT, Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:34:23 + --> $DIR/associated-type-projection-from-supertrait.rs:28:23 | LL | fn c() { dent(ModelU, Black); } | ^^^^^ expected struct `Blue`, found struct `Black` @@ -17,7 +17,7 @@ LL | fn c() { dent(ModelU, Black); } found type `Black` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:40:28 + --> $DIR/associated-type-projection-from-supertrait.rs:32:28 | LL | fn f() { ModelT.chip_paint(Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -26,7 +26,7 @@ LL | fn f() { ModelT.chip_paint(Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:41:28 + --> $DIR/associated-type-projection-from-supertrait.rs:33:28 | LL | fn g() { ModelU.chip_paint(Black); } | ^^^^^ expected struct `Blue`, found struct `Black` diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs index 653130843c..6b2bbbe2e4 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs @@ -11,22 +11,16 @@ pub trait Car : Vehicle { fn honk(&self) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn black_car>(c: C) { } diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 4b54860498..6a2135ca46 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -1,30 +1,26 @@ error[E0271]: type mismatch resolving `::Color == Blue` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:37:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10 | +LL | fn blue_car>(c: C) { + | -------- ---------- required by this bound in `blue_car` +... LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ expected struct `Black`, found struct `Blue` | = note: expected type `Black` found type `Blue` -note: required by `blue_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:33:1 - | -LL | fn blue_car>(c: C) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::Color == Black` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:38:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10 | +LL | fn black_car>(c: C) { + | --------- ----------- required by this bound in `black_car` +... LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ expected struct `Blue`, found struct `Black` | = note: expected type `Blue` found type `Black` -note: required by `black_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:30:1 - | -LL | fn black_car>(c: C) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index 502fb4f1c3..85acf134d5 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied - --> $DIR/associated-types-bound-failure.rs:17:5 + --> $DIR/associated-types-bound-failure.rs:17:19 | +LL | fn to_int(&self) -> isize; + | -------------------------- required by `ToInt::to_int` +... LL | ToInt::to_int(&g.get()) - | ^^^^^^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` | = help: consider adding a `where ::R: ToInt` bound -note: required by `ToInt::to_int` - --> $DIR/associated-types-bound-failure.rs:4:5 - | -LL | fn to_int(&self) -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 66fa4c288c..83d8992494 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -6,20 +6,20 @@ LL | let _: Bar = x.boo(); | = note: expected type `Bar` found type `::A` + = note: consider constraining the associated type `::A` to `Bar` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `::A == Bar` --> $DIR/associated-types-eq-3.rs:38:5 | +LL | fn foo1>(x: I) { + | ---- ----- required by this bound in `foo1` +... LL | foo1(a); | ^^^^ expected usize, found struct `Bar` | = note: expected type `usize` found type `Bar` -note: required by `foo1` - --> $DIR/associated-types-eq-3.rs:18:1 - | -LL | fn foo1>(x: I) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::A == Bar` --> $DIR/associated-types-eq-3.rs:41:9 diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 353829c2f7..45b6cc9ba5 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -1,124 +1,94 @@ error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` --> $DIR/associated-types-eq-hr.rs:82:5 | +LL | fn foo() + | --- +LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize> + | ------------- required by this bound in `foo` +... LL | foo::(); | ^^^^^^^^^^^^^^^^^ expected usize, found isize | = note: expected type `&usize` found type `&isize` -note: required by `foo` - --> $DIR/associated-types-eq-hr.rs:44:1 - | -LL | / fn foo() -LL | | where T : for<'x> TheTrait<&'x isize, A = &'x isize> -LL | | { -LL | | // ok for IntStruct, but not UintStruct -LL | | } - | |_^ error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` --> $DIR/associated-types-eq-hr.rs:86:5 | +LL | fn bar() + | --- +LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize> + | ------------- required by this bound in `bar` +... LL | bar::(); | ^^^^^^^^^^^^^^^^ expected isize, found usize | = note: expected type `&isize` found type `&usize` -note: required by `bar` - --> $DIR/associated-types-eq-hr.rs:50:1 - | -LL | / fn bar() -LL | | where T : for<'x> TheTrait<&'x isize, A = &'x usize> -LL | | { -LL | | // ok for UintStruct, but not IntStruct -LL | | } - | |_^ error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:91:5 + --> $DIR/associated-types-eq-hr.rs:91:17 | +LL | fn tuple_one() + | --------- +LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> + | ---------------------------------------------------------- required by this bound in `tuple_one` +... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` | = help: the following implementations were found: > -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | -LL | / fn tuple_one() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` --> $DIR/associated-types-eq-hr.rs:91:5 | +LL | fn tuple_one() + | --------- +LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> + | ------------- required by this bound in `tuple_one` +... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | -LL | / fn tuple_one() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:5 + --> $DIR/associated-types-eq-hr.rs:97:17 | +LL | fn tuple_two() + | --------- +LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> + | ---------------------------------------------------------- required by this bound in `tuple_two` +... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` | = help: the following implementations were found: > -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 - | -LL | / fn tuple_two() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` --> $DIR/associated-types-eq-hr.rs:97:5 | +LL | fn tuple_two() + | --------- +LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> + | ------------- required by this bound in `tuple_two` +... LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 - | -LL | / fn tuple_two() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:107:5 + --> $DIR/associated-types-eq-hr.rs:107:18 | +LL | fn tuple_four() + | ---------- +LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> + | ------------------------------------------- required by this bound in `tuple_four` +... LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` | = help: the following implementations were found: > -note: required by `tuple_four` - --> $DIR/associated-types-eq-hr.rs:74:1 - | -LL | / fn tuple_four() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> -LL | | { -LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant -LL | | } - | |_^ error: aborting due to 7 previous errors diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 7d5b16c6e6..c8f8725afc 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -1,16 +1,16 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == std::option::Option` --> $DIR/associated-types-issue-20346.rs:34:5 | +LL | fn is_iterator_of>(_: &I) {} + | -------------- ------ required by this bound in `is_iterator_of` +... LL | is_iterator_of::, _>(&adapter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option` | = note: expected type `T` found type `std::option::Option` -note: required by `is_iterator_of` - --> $DIR/associated-types-issue-20346.rs:15:1 - | -LL | fn is_iterator_of>(_: &I) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index 2926bdae05..c7de186c1d 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -3,28 +3,28 @@ error[E0271]: type mismatch resolving `::Y == i32` | LL | want_y(t); | ^^^^^^ expected associated type, found i32 +... +LL | fn want_y>(t: &T) { } + | ------ ----- required by this bound in `want_y` | = note: expected type `::Y` found type `i32` -note: required by `want_y` - --> $DIR/associated-types-multiple-types-one-trait.rs:44:1 - | -LL | fn want_y>(t: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: consider constraining the associated type `::Y` to `i32` or calling a method that returns `::Y` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `::X == u32` --> $DIR/associated-types-multiple-types-one-trait.rs:18:5 | LL | want_x(t); | ^^^^^^ expected associated type, found u32 +... +LL | fn want_x>(t: &T) { } + | ------ ----- required by this bound in `want_x` | = note: expected type `::X` found type `u32` -note: required by `want_x` - --> $DIR/associated-types-multiple-types-one-trait.rs:42:1 - | -LL | fn want_x>(t: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: consider constraining the associated type `::X` to `u32` or calling a method that returns `::X` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index a26ee23894..a7238541cd 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -1,14 +1,10 @@ error[E0284]: type annotations required: cannot resolve `::Item == i32` --> $DIR/associated-types-overridden-binding.rs:4:1 | +LL | trait Foo: Iterator {} + | ------------------------------- required by `Foo` LL | trait Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by `Foo` - --> $DIR/associated-types-overridden-binding.rs:3:1 - | -LL | trait Foo: Iterator {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index 1405cb1b47..bb2e725184 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -11,14 +11,11 @@ LL | f1(2i32, 4u32); error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:5 | +LL | pub fn f1(a: T, x: T::A) {} + | -- --- required by this bound in `f1` +... LL | f1(2u32, 4u32); | ^^ the trait `Foo` is not implemented for `u32` - | -note: required by `f1` - --> $DIR/associated-types-path-2.rs:13:1 - | -LL | pub fn f1(a: T, x: T::A) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:5 @@ -29,14 +26,11 @@ LL | f1(2u32, 4u32); error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:5 | +LL | pub fn f1(a: T, x: T::A) {} + | -- --- required by this bound in `f1` +... LL | f1(2u32, 4i32); | ^^ the trait `Foo` is not implemented for `u32` - | -note: required by `f1` - --> $DIR/associated-types-path-2.rs:13:1 - | -LL | pub fn f1(a: T, x: T::A) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:5 diff --git a/src/test/ui/associated-types/associated-types-ref-from-struct.rs b/src/test/ui/associated-types/associated-types-ref-from-struct.rs index 3ccba289e4..c89f6046e6 100644 --- a/src/test/ui/associated-types/associated-types-ref-from-struct.rs +++ b/src/test/ui/associated-types/associated-types-ref-from-struct.rs @@ -9,8 +9,6 @@ trait Test { fn test(&self, value: &Self::V) -> bool; } -/////////////////////////////////////////////////////////////////////////// - struct TesterPair { tester: T, value: T::V, @@ -26,8 +24,6 @@ impl TesterPair { } } -/////////////////////////////////////////////////////////////////////////// - struct EqU32(u32); impl Test for EqU32 { type V = u32; diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index cc69e849fe..74c9ad2c39 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,16 +1,13 @@ error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` --> $DIR/higher-ranked-projection.rs:25:5 | +LL | fn foo(_t: T) + | --- +LL | where for<'a> &'a T: Mirror + | ------- required by this bound in `foo` +... LL | foo(()); | ^^^ expected bound lifetime parameter 'a, found concrete lifetime - | -note: required by `foo` - --> $DIR/higher-ranked-projection.rs:14:1 - | -LL | / fn foo(_t: T) -LL | | where for<'a> &'a T: Mirror -LL | | {} - | |__^ error: aborting due to previous error diff --git a/src/test/ui/ast-json/ast-json-ice.rs b/src/test/ui/ast-json/ast-json-ice.rs new file mode 100644 index 0000000000..e8a622e1b8 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-ice.rs @@ -0,0 +1,41 @@ +// Test that AST json serialization doesn't ICE (#63728). + +// revisions: expand noexpand + +//[expand] compile-flags: -Zast-json +//[noexpand] compile-flags: -Zast-json-noexpand + +// check-pass +// dont-check-compiler-stdout - don't check for any AST change. + +#![feature(asm)] + +enum V { + A(i32), + B { f: [i64; 3 + 4] } +} + +trait X { + type Output; + fn read(&self) -> Self::Output; + fn write(&mut self, _: Self::Output); +} + +macro_rules! call_println { + ($y:ident) => { println!("{}", $y) } +} + +fn main() { + #[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm", + target_arch = "aarch64"))] + unsafe { asm!(""::::); } + + let x: (i32) = 35; + let y = x as i64<> + 5; + + call_println!(y); + + struct A; +} diff --git a/src/test/ui/ast-json/ast-json-output.rs b/src/test/ui/ast-json/ast-json-output.rs new file mode 100644 index 0000000000..e444a07460 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-output.rs @@ -0,0 +1,9 @@ +// Check that AST json printing works. + +// check-pass +// compile-flags: -Zast-json-noexpand +// normalize-stdout-test ":\d+" -> ":0" + +// Only include a single item to reduce how often the test output needs +// updating. +extern crate core; diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout new file mode 100644 index 0000000000..d23cbe0240 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -0,0 +1 @@ +{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"node":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]}]}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} diff --git a/src/test/ui/async-await/argument-patterns.rs b/src/test/ui/async-await/argument-patterns.rs index 3750c2bcb7..b9fc1a88ce 100644 --- a/src/test/ui/async-await/argument-patterns.rs +++ b/src/test/ui/async-await/argument-patterns.rs @@ -1,9 +1,7 @@ // edition:2018 -// run-pass +// check-pass -#![allow(unused_variables)] #![deny(unused_mut)] -#![feature(async_await)] type A = Vec; diff --git a/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs b/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs new file mode 100644 index 0000000000..8e08b82b9d --- /dev/null +++ b/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs @@ -0,0 +1,23 @@ +// check-pass +// Check that the anonymous lifetimes used here aren't considered to shadow one +// another. Note that `async fn` is different to `fn` here because the lifetimes +// are numbered by HIR lowering, rather than lifetime resolution. + +// edition:2018 + +struct A<'a, 'b>(&'a &'b i32); +struct B<'a>(&'a i32); + +impl A<'_, '_> { + async fn assoc(x: &u32, y: B<'_>) { + async fn nested(x: &u32, y: A<'_, '_>) {} + } + + async fn assoc2(x: &u32, y: A<'_, '_>) { + impl A<'_, '_> { + async fn nested_assoc(x: &u32, y: B<'_>) {} + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs index 8a15eb8c57..1dc7315e88 100644 --- a/src/test/ui/async-await/async-await.rs +++ b/src/test/ui/async-await/async-await.rs @@ -1,10 +1,10 @@ // run-pass +#![allow(unused)] + // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await)] - extern crate arc_wake; use std::pin::Pin; diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 6a766ede0e..753a4e4915 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs @@ -6,8 +6,6 @@ // edition:2018 // ignore-tidy-linelength -#![feature(async_await)] - fn main() {} use core::future::Future; @@ -32,15 +30,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 { fn no_break_in_async_block() { async { - break 0u8; //~ ERROR `break` inside of a closure - // FIXME: This diagnostic is pretty bad. + break 0u8; //~ ERROR `break` inside of an `async` block }; } fn no_break_in_async_block_even_with_outer_loop() { loop { async { - break 0u8; //~ ERROR `break` inside of a closure + break 0u8; //~ ERROR `break` inside of an `async` block }; } } diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index f3f2d14584..c36caa5586 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -1,17 +1,25 @@ -error[E0267]: `break` inside of a closure - --> $DIR/async-block-control-flow-static-semantics.rs:35:9 +error[E0267]: `break` inside of an `async` block + --> $DIR/async-block-control-flow-static-semantics.rs:33:9 | -LL | break 0u8; - | ^^^^^^^^^ cannot break inside of a closure +LL | async { + | ___________- +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_____- enclosing `async` block -error[E0267]: `break` inside of a closure - --> $DIR/async-block-control-flow-static-semantics.rs:43:13 +error[E0267]: `break` inside of an `async` block + --> $DIR/async-block-control-flow-static-semantics.rs:40:13 | -LL | break 0u8; - | ^^^^^^^^^ cannot break inside of a closure +LL | async { + | _______________- +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_________- enclosing `async` block error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:15:43 + --> $DIR/async-block-control-flow-static-semantics.rs:13:43 | LL | fn return_targets_async_block_not_fn() -> u8 { | --------------------------------- ^^ expected u8, found () @@ -22,7 +30,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 { found type `()` error[E0271]: type mismatch resolving `::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:20:39 + --> $DIR/async-block-control-flow-static-semantics.rs:18:39 | LL | let _: &dyn Future = █ | ^^^^^^ expected u8, found () @@ -32,7 +40,7 @@ LL | let _: &dyn Future = █ = note: required for the cast to the object type `dyn std::future::Future` error[E0271]: type mismatch resolving `::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:29:39 + --> $DIR/async-block-control-flow-static-semantics.rs:27:39 | LL | let _: &dyn Future = █ | ^^^^^^ expected u8, found () @@ -42,7 +50,7 @@ LL | let _: &dyn Future = █ = note: required for the cast to the object type `dyn std::future::Future` error[E0271]: type mismatch resolving `::Output == u8` - --> $DIR/async-block-control-flow-static-semantics.rs:24:55 + --> $DIR/async-block-control-flow-static-semantics.rs:22:55 | LL | async fn return_targets_async_block_not_async_fn() -> u8 { | ^^ expected (), found u8 @@ -52,7 +60,7 @@ LL | async fn return_targets_async_block_not_async_fn() -> u8 { = note: the return type of a function must have a statically known size error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:51:44 + --> $DIR/async-block-control-flow-static-semantics.rs:48:44 | LL | fn rethrow_targets_async_block_not_fn() -> Result { | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () @@ -63,7 +71,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result { found type `()` error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:60:50 + --> $DIR/async-block-control-flow-static-semantics.rs:57:50 | LL | fn rethrow_targets_async_block_not_async_fn() -> Result { | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr new file mode 100644 index 0000000000..5f20367b6a --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr @@ -0,0 +1,16 @@ +error[E0597]: `x` does not live long enough + --> $DIR/async-borrowck-escaping-closure-error.rs:5:24 + | +LL | Box::new((async || x)()) + | -------------------^---- + | | | | + | | | borrowed value does not live long enough + | | value captured here + | borrow later used here +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs b/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs new file mode 100644 index 0000000000..d2fa5d0a3d --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -0,0 +1,10 @@ +// edition:2018 +#![feature(async_closure,async_await)] +fn foo() -> Box> { + let x = 0u32; + Box::new((async || x)()) + //~^ ERROR E0373 +} + +fn main() { +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr new file mode 100644 index 0000000000..8bcfcf9892 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-closure-error.rs:5:15 + | +LL | Box::new((async || x)()) + | ^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/async-borrowck-escaping-closure-error.rs:5:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new((async move || x)()) + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/async-await/async-closure-matches-expr.rs b/src/test/ui/async-await/async-closure-matches-expr.rs index 1c192a4d1d..d82fbcdc55 100644 --- a/src/test/ui/async-await/async-closure-matches-expr.rs +++ b/src/test/ui/async-await/async-closure-matches-expr.rs @@ -1,7 +1,7 @@ // build-pass // edition:2018 -#![feature(async_await, async_closure)] +#![feature(async_closure)] macro_rules! match_expr { ($x:expr) => {} diff --git a/src/test/ui/async-await/async-closure.rs b/src/test/ui/async-await/async-closure.rs index 925b54b398..9a24bd8c95 100644 --- a/src/test/ui/async-await/async-closure.rs +++ b/src/test/ui/async-await/async-closure.rs @@ -3,7 +3,7 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await, async_closure)] +#![feature(async_closure)] extern crate arc_wake; diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index d362348a3f..dec3ac0f68 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -1,7 +1,6 @@ // edition:2018 -#![feature(async_await)] -// Regression test for issue #62382 +// Regression test for issue #62382. use std::future::Future; diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index bd8966b9c7..47441f5e4e 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -1,11 +1,11 @@ error[E0698]: type inside `async` object must be known in this context - --> $DIR/async-error-span.rs:13:9 + --> $DIR/async-error-span.rs:12:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async` object because of this `await` - --> $DIR/async-error-span.rs:14:5 + --> $DIR/async-error-span.rs:13:5 | LL | get_future().await; | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs new file mode 100644 index 0000000000..1c369fd741 --- /dev/null +++ b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs @@ -0,0 +1,15 @@ +// Check that `async fn` inside of an impl with `'_` +// in the header compiles correctly. +// +// Regression test for #63500. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a u8); + +impl Foo<'_> { + async fn bar() {} +} + +fn main() { } diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs index 612c1e29d8..1f1bf4250e 100644 --- a/src/test/ui/async-await/async-fn-nonsend.rs +++ b/src/test/ui/async-await/async-fn-nonsend.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::{ cell::RefCell, fmt::Debug, diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 7776a36a28..696bd5c39d 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,44 +1,43 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:52:5 + --> $DIR/async-fn-nonsend.rs:50:5 | +LL | fn assert_send(_: impl Send) {} + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send(local_dropped_before_await()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` + = note: required because it appears within the type `{impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:54:5 + --> $DIR/async-fn-nonsend.rs:52:5 | +LL | fn assert_send(_: impl Send) {} + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, impl std::future::Future, ()}]>` + = note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:56:5 + --> $DIR/async-fn-nonsend.rs:54:5 | +LL | fn assert_send(_: impl Send) {} + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely | @@ -46,20 +45,18 @@ LL | assert_send(non_sync_with_method_call()); = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` = note: required because it appears within the type `std::fmt::Formatter<'_>` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely - --> $DIR/async-fn-nonsend.rs:56:5 + --> $DIR/async-fn-nonsend.rs:54:5 | +LL | fn assert_send(_: impl Send) {} + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -71,16 +68,11 @@ LL | assert_send(non_sync_with_method_call()); = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` = note: required because it appears within the type `std::fmt::Formatter<'_>` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/async-fn-path-elision.rs b/src/test/ui/async-await/async-fn-path-elision.rs index 447e40dddd..3f1f51c20c 100644 --- a/src/test/ui/async-await/async-fn-path-elision.rs +++ b/src/test/ui/async-await/async-fn-path-elision.rs @@ -1,8 +1,5 @@ // edition:2018 -#![feature(async_await)] -#![allow(dead_code)] - struct HasLifetime<'a>(&'a bool); async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here diff --git a/src/test/ui/async-await/async-fn-path-elision.stderr b/src/test/ui/async-await/async-fn-path-elision.stderr index 3b311baba0..9694742200 100644 --- a/src/test/ui/async-await/async-fn-path-elision.stderr +++ b/src/test/ui/async-await/async-fn-path-elision.stderr @@ -1,5 +1,5 @@ error[E0726]: implicit elided lifetime not allowed here - --> $DIR/async-fn-path-elision.rs:8:20 + --> $DIR/async-fn-path-elision.rs:5:20 | LL | async fn error(lt: HasLifetime) { | ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` diff --git a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs index 5e1b8c6280..35d9cb1554 100644 --- a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs +++ b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::{ cell::RefCell, fmt::Debug, diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 30b59d037d..3ffcbb5859 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -12,8 +12,6 @@ // edition:2018 -#![feature(async_await)] - use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index c6b2ed13b0..b5c94ecb71 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -2,8 +2,6 @@ // aux-build:arc_wake.rs // edition:2018 -#![feature(async_await)] - extern crate arc_wake; use std::pin::Pin; diff --git a/src/test/ui/async-await/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs index a6f0211e41..299faa0587 100644 --- a/src/test/ui/async-await/async-matches-expr.rs +++ b/src/test/ui/async-await/async-matches-expr.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - macro_rules! match_expr { ($x:expr) => {} } diff --git a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs index cb9156dcc6..ccc1b8553f 100644 --- a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs +++ b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - struct S; impl S { diff --git a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr index d22413beec..c95fe17348 100644 --- a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr +++ b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:12:5 | LL | S::f(); | ^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | S::f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:15:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:13:5 | LL | f(); | ^^^ call to unsafe function @@ -15,7 +15,7 @@ LL | f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:19:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5 | LL | S::f(); | ^^^^^^ call to unsafe function @@ -23,7 +23,7 @@ LL | S::f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:20:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:18:5 | LL | f(); | ^^^ call to unsafe function diff --git a/src/test/ui/async-await/async-with-closure.rs b/src/test/ui/async-await/async-with-closure.rs index f7dc874aff..0b22552667 100644 --- a/src/test/ui/async-await/async-with-closure.rs +++ b/src/test/ui/async-await/async-with-closure.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - trait MyClosure { type Args; } diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs index 422a5a6394..a3a20cb97e 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs +++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs @@ -1,4 +1,3 @@ -#![feature(async_await)] #![allow(non_camel_case_types)] #![deny(keyword_idents)] diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr index 8af0110169..f1a22cda51 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr +++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr @@ -1,11 +1,11 @@ error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:6:13 + --> $DIR/2015-edition-error-various-positions.rs:5:13 | LL | pub mod await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | note: lint level defined here - --> $DIR/2015-edition-error-various-positions.rs:3:9 + --> $DIR/2015-edition-error-various-positions.rs:2:9 | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #![deny(keyword_idents)] = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:8:20 + --> $DIR/2015-edition-error-various-positions.rs:7:20 | LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -22,7 +22,7 @@ LL | pub struct await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:12:16 + --> $DIR/2015-edition-error-various-positions.rs:11:16 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -31,7 +31,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:12:23 + --> $DIR/2015-edition-error-various-positions.rs:11:23 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -40,7 +40,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:17:14 + --> $DIR/2015-edition-error-various-positions.rs:16:14 | LL | struct Foo { await: () } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -49,7 +49,7 @@ LL | struct Foo { await: () } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:21:15 + --> $DIR/2015-edition-error-various-positions.rs:20:15 | LL | impl Foo { fn await() {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -58,7 +58,7 @@ LL | impl Foo { fn await() {} } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:25:14 + --> $DIR/2015-edition-error-various-positions.rs:24:14 | LL | macro_rules! await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -67,7 +67,7 @@ LL | macro_rules! await { = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:32:5 + --> $DIR/2015-edition-error-various-positions.rs:31:5 | LL | await!(); | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -76,7 +76,7 @@ LL | await!(); = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:35:11 + --> $DIR/2015-edition-error-various-positions.rs:34:11 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -85,7 +85,7 @@ LL | match await { await => {} } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:35:19 + --> $DIR/2015-edition-error-various-positions.rs:34:19 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs index 92f3210ac8..9e78f7c512 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs +++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -1,24 +1,23 @@ // edition:2018 #![allow(non_camel_case_types)] -#![feature(async_await)] mod outer_mod { - pub mod await { //~ ERROR expected identifier, found reserved keyword `await` - pub struct await; //~ ERROR expected identifier, found reserved keyword `await` + pub mod await { //~ ERROR expected identifier, found keyword `await` + pub struct await; //~ ERROR expected identifier, found keyword `await` } } -use self::outer_mod::await::await; //~ ERROR expected identifier, found reserved keyword `await` -//~^ ERROR expected identifier, found reserved keyword `await` +use self::outer_mod::await::await; //~ ERROR expected identifier, found keyword `await` +//~^ ERROR expected identifier, found keyword `await` struct Foo { await: () } -//~^ ERROR expected identifier, found reserved keyword `await` +//~^ ERROR expected identifier, found keyword `await` impl Foo { fn await() {} } -//~^ ERROR expected identifier, found reserved keyword `await` +//~^ ERROR expected identifier, found keyword `await` macro_rules! await { -//~^ ERROR expected identifier, found reserved keyword `await` +//~^ ERROR expected identifier, found keyword `await` () => {} } diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr index c4b82b29f0..0e85946632 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr +++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -1,68 +1,68 @@ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:7:13 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:6:13 | LL | pub mod await { - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | pub mod r#await { | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:8:20 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:7:20 | LL | pub struct await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | pub struct r#await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:11:22 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:22 | LL | use self::outer_mod::await::await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | use self::outer_mod::r#await::await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:11:29 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:29 | LL | use self::outer_mod::await::await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | use self::outer_mod::await::r#await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:14:14 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14 | LL | struct Foo { await: () } - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | struct Foo { r#await: () } | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:17:15 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:16:15 | LL | impl Foo { fn await() {} } - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | impl Foo { fn r#await() {} } | ^^^^^^^ -error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:20:14 +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:19:14 | LL | macro_rules! await { - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | macro_rules! r#await { diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error.rs b/src/test/ui/async-await/await-keyword/2018-edition-error.rs index e620c27f9e..7ce52259ac 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error.rs +++ b/src/test/ui/async-await/await-keyword/2018-edition-error.rs @@ -7,9 +7,9 @@ mod outer_mod { } } use self::outer_mod::await::await; //~ ERROR expected identifier - //~^ ERROR expected identifier, found reserved keyword `await` + //~^ ERROR expected identifier, found keyword `await` -macro_rules! await { () => {}; } //~ ERROR expected identifier, found reserved keyword `await` +macro_rules! await { () => {}; } //~ ERROR expected identifier, found keyword `await` fn main() { await!(); //~ ERROR expected expression, found `)` diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error.stderr index 9304928cfd..71f403f278 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error.stderr +++ b/src/test/ui/async-await/await-keyword/2018-edition-error.stderr @@ -1,48 +1,48 @@ -error: expected identifier, found reserved keyword `await` +error: expected identifier, found keyword `await` --> $DIR/2018-edition-error.rs:5:13 | LL | pub mod await { - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | pub mod r#await { | ^^^^^^^ -error: expected identifier, found reserved keyword `await` +error: expected identifier, found keyword `await` --> $DIR/2018-edition-error.rs:6:20 | LL | pub struct await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | pub struct r#await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` +error: expected identifier, found keyword `await` --> $DIR/2018-edition-error.rs:9:22 | LL | use self::outer_mod::await::await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | use self::outer_mod::r#await::await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` +error: expected identifier, found keyword `await` --> $DIR/2018-edition-error.rs:9:29 | LL | use self::outer_mod::await::await; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | use self::outer_mod::await::r#await; | ^^^^^^^ -error: expected identifier, found reserved keyword `await` +error: expected identifier, found keyword `await` --> $DIR/2018-edition-error.rs:12:14 | LL | macro_rules! await { () => {}; } - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | macro_rules! r#await { () => {}; } diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs index 25da337c58..22bcbb1064 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - async fn bar() -> Result<(), ()> { Ok(()) } diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index db86d3d5d0..7caa9f26bc 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -1,119 +1,119 @@ error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:10:13 + --> $DIR/incorrect-syntax-suggestions.rs:8:13 | LL | let _ = await bar(); | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:14:13 + --> $DIR/incorrect-syntax-suggestions.rs:12:13 | LL | let _ = await? bar(); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:18:13 + --> $DIR/incorrect-syntax-suggestions.rs:16:13 | LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:23:13 + --> $DIR/incorrect-syntax-suggestions.rs:21:13 | LL | let _ = await { bar() }; | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:27:13 + --> $DIR/incorrect-syntax-suggestions.rs:25:13 | LL | let _ = await(bar()); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:31:13 + --> $DIR/incorrect-syntax-suggestions.rs:29:13 | LL | let _ = await { bar() }?; | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:35:14 + --> $DIR/incorrect-syntax-suggestions.rs:33:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:39:24 + --> $DIR/incorrect-syntax-suggestions.rs:37:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:43:24 + --> $DIR/incorrect-syntax-suggestions.rs:41:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:55:13 + --> $DIR/incorrect-syntax-suggestions.rs:53:13 | LL | let _ = await bar(); | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:60:13 + --> $DIR/incorrect-syntax-suggestions.rs:58:13 | LL | let _ = await? bar(); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:65:13 + --> $DIR/incorrect-syntax-suggestions.rs:63:13 | LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:70:14 + --> $DIR/incorrect-syntax-suggestions.rs:68:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:75:24 + --> $DIR/incorrect-syntax-suggestions.rs:73:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:80:24 + --> $DIR/incorrect-syntax-suggestions.rs:78:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:108:13 + --> $DIR/incorrect-syntax-suggestions.rs:106:13 | LL | let _ = await!(bar()); | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:112:13 + --> $DIR/incorrect-syntax-suggestions.rs:110:13 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:117:17 + --> $DIR/incorrect-syntax-suggestions.rs:115:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:125:17 + --> $DIR/incorrect-syntax-suggestions.rs:123:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: expected expression, found `=>` - --> $DIR/incorrect-syntax-suggestions.rs:133:25 + --> $DIR/incorrect-syntax-suggestions.rs:131:25 | LL | match await { await => () } | ----- ^^ expected expression @@ -121,13 +121,13 @@ LL | match await { await => () } | while parsing this incorrect await expression error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:133:11 + --> $DIR/incorrect-syntax-suggestions.rs:131:11 | LL | match await { await => () } | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` error: expected one of `.`, `?`, `{`, or an operator, found `}` - --> $DIR/incorrect-syntax-suggestions.rs:136:1 + --> $DIR/incorrect-syntax-suggestions.rs:134:1 | LL | match await { await => () } | ----- - expected one of `.`, `?`, `{`, or an operator here @@ -138,7 +138,7 @@ LL | } | ^ unexpected token error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:55:13 + --> $DIR/incorrect-syntax-suggestions.rs:53:13 | LL | fn foo9() -> Result<(), ()> { | ---- this is not `async` @@ -146,7 +146,7 @@ LL | let _ = await bar(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:60:13 + --> $DIR/incorrect-syntax-suggestions.rs:58:13 | LL | fn foo10() -> Result<(), ()> { | ----- this is not `async` @@ -154,7 +154,7 @@ LL | let _ = await? bar(); | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:65:13 + --> $DIR/incorrect-syntax-suggestions.rs:63:13 | LL | fn foo11() -> Result<(), ()> { | ----- this is not `async` @@ -162,7 +162,7 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:70:14 + --> $DIR/incorrect-syntax-suggestions.rs:68:14 | LL | fn foo12() -> Result<(), ()> { | ----- this is not `async` @@ -170,7 +170,7 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:75:13 + --> $DIR/incorrect-syntax-suggestions.rs:73:13 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` @@ -178,7 +178,7 @@ LL | let _ = bar().await(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:80:13 + --> $DIR/incorrect-syntax-suggestions.rs:78:13 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` @@ -186,7 +186,7 @@ LL | let _ = bar().await()?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:85:13 + --> $DIR/incorrect-syntax-suggestions.rs:83:13 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` @@ -194,7 +194,7 @@ LL | let _ = bar().await; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:89:13 + --> $DIR/incorrect-syntax-suggestions.rs:87:13 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` @@ -202,7 +202,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:94:17 + --> $DIR/incorrect-syntax-suggestions.rs:92:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -210,7 +210,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:101:17 + --> $DIR/incorrect-syntax-suggestions.rs:99:17 | LL | let foo = || { | -- this is not `async` @@ -218,7 +218,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:117:17 + --> $DIR/incorrect-syntax-suggestions.rs:115:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -226,7 +226,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:125:17 + --> $DIR/incorrect-syntax-suggestions.rs:123:17 | LL | let foo = || { | -- this is not `async` @@ -234,7 +234,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` - --> $DIR/incorrect-syntax-suggestions.rs:18:19 + --> $DIR/incorrect-syntax-suggestions.rs:16:19 | LL | let _ = await bar()?; | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` diff --git a/src/test/ui/async-await/await-unsize.rs b/src/test/ui/async-await/await-unsize.rs index d5e21257f4..aa09d4bdf0 100644 --- a/src/test/ui/async-await/await-unsize.rs +++ b/src/test/ui/async-await/await-unsize.rs @@ -3,8 +3,6 @@ // check-pass // edition:2018 -#![feature(async_await)] - async fn make_boxed_object() -> Box { Box::new(()) as _ } diff --git a/src/test/ui/async-await/bound-normalization.rs b/src/test/ui/async-await/bound-normalization.rs index 8026350aaf..5d260682f1 100644 --- a/src/test/ui/async-await/bound-normalization.rs +++ b/src/test/ui/async-await/bound-normalization.rs @@ -1,8 +1,6 @@ // check-pass // edition:2018 -#![feature(async_await)] - // See issue 60414 trait Trait { diff --git a/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs b/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs index a5947e7f71..56f4cbbd19 100644 --- a/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs +++ b/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn conditional_and_guaranteed_initialization(x: usize) -> usize { let y; if x > 5 { diff --git a/src/test/ui/async-await/dont-print-desugared-async.rs b/src/test/ui/async-await/dont-print-desugared-async.rs index 8150a26086..68341a24c4 100644 --- a/src/test/ui/async-await/dont-print-desugared-async.rs +++ b/src/test/ui/async-await/dont-print-desugared-async.rs @@ -1,7 +1,6 @@ // Test that we don't show variables with from async fn desugaring // edition:2018 -#![feature(async_await)] async fn async_fn(&ref mut s: &[i32]) {} //~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] diff --git a/src/test/ui/async-await/dont-print-desugared-async.stderr b/src/test/ui/async-await/dont-print-desugared-async.stderr index 47726ba65d..2bf1e77f09 100644 --- a/src/test/ui/async-await/dont-print-desugared-async.stderr +++ b/src/test/ui/async-await/dont-print-desugared-async.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/dont-print-desugared-async.rs:6:20 + --> $DIR/dont-print-desugared-async.rs:5:20 | LL | async fn async_fn(&ref mut s: &[i32]) {} | -^^^^^^^^^ diff --git a/src/test/ui/async-await/dont-suggest-missing-await.rs b/src/test/ui/async-await/dont-suggest-missing-await.rs index d551ef5798..a8e5b38ec1 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.rs +++ b/src/test/ui/async-await/dont-suggest-missing-await.rs @@ -2,8 +2,6 @@ // This test ensures we don't make the suggestion in bodies that aren't `async`. -#![feature(async_await)] - fn take_u32(x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index c60b0d1f30..c87e0bc221 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/dont-suggest-missing-await.rs:16:18 + --> $DIR/dont-suggest-missing-await.rs:14:18 | LL | take_u32(x) | ^ expected u32, found opaque type diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs index dfd8b2e361..9817d377a7 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -3,7 +3,6 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs index 2a74485afb..00072786a5 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs @@ -3,7 +3,6 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs index db396d3957..15cc9fbc81 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs @@ -2,9 +2,10 @@ // edition:2018 // run-pass -#![allow(unused_variables)] #![deny(dead_code)] -#![feature(async_await)] +#![allow(unused_variables)] +#![allow(unused_must_use)] +#![allow(path_statements)] // Test that the drop order for locals in a fn and async fn matches up. extern crate arc_wake; @@ -12,7 +13,6 @@ extern crate arc_wake; use arc_wake::ArcWake; use std::cell::RefCell; use std::future::Future; -use std::marker::PhantomData; use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; @@ -44,7 +44,7 @@ struct NeverReady; impl Future for NeverReady { type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { Poll::Pending } } diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs new file mode 100644 index 0000000000..e40acff6dc --- /dev/null +++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs @@ -0,0 +1,95 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![allow(unused_variables)] + +// Test the drop order for parameters relative to local variables and +// temporaries created in the tail return expression of the function +// body. In particular, check that this drop order is the same between +// a `async fn` and an ordinary `fn`. See #64512. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`. +/// +/// Expected order: +/// - `z` +/// - temp +/// - `y` +/// - `x` +async fn foo_async(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_async(&D("temp", l)).await +} + +async fn helper_async(v: &D) { } + +fn foo_sync(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_sync(&D("temp", l)) +} + +fn helper_sync(v: &D) { } + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let r = fut.as_mut().poll(&mut cx); + + assert!(match r { + std::task::Poll::Ready(()) => true, + _ => false, + }); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); +} diff --git a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs index bcdb8878eb..79dedb1ba2 100644 --- a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs +++ b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs @@ -1,8 +1,5 @@ // edition:2018 -#![allow(unused_variables)] -#![feature(async_await)] - async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) { assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425] assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425] diff --git a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr index 484e1f4f42..aa04a613f4 100644 --- a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr +++ b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr @@ -1,23 +1,23 @@ error[E0425]: cannot find value `__arg1` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:7:16 + --> $DIR/drop-order-locals-are-hidden.rs:4:16 | LL | assert_eq!(__arg1, (1, 2, 3)); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg2` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:8:16 + --> $DIR/drop-order-locals-are-hidden.rs:5:16 | LL | assert_eq!(__arg2, 4); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg0` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:12:16 + --> $DIR/drop-order-locals-are-hidden.rs:9:16 | LL | assert_eq!(__arg0, 1); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg1` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:13:16 + --> $DIR/drop-order-locals-are-hidden.rs:10:16 | LL | assert_eq!(__arg1, 2); | ^^^^^^ not found in this scope diff --git a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs index 410a623681..9e8304935b 100644 --- a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs +++ b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs @@ -2,13 +2,12 @@ // edition:2018 // run-pass -#![allow(unused_variables)] -#![feature(async_await)] - // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn is cancelled. // This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs +#![allow(unused_variables)] + extern crate arc_wake; use arc_wake::ArcWake; @@ -46,7 +45,7 @@ struct NeverReady; impl Future for NeverReady { type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { Poll::Pending } } diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index a5bc181015..c85896150c 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -1,7 +1,5 @@ // edition:2015 -#![feature(async_await)] - async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index efb4462095..d3f88af09d 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -1,59 +1,59 @@ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:5:1 + --> $DIR/edition-deny-async-fns-2015.rs:3:1 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:7:12 + --> $DIR/edition-deny-async-fns-2015.rs:5:12 | LL | fn baz() { async fn foo() {} } | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:10:5 + --> $DIR/edition-deny-async-fns-2015.rs:8:5 | LL | async fn bar() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:9:1 + --> $DIR/edition-deny-async-fns-2015.rs:7:1 | LL | async fn async_baz() { | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:16:5 + --> $DIR/edition-deny-async-fns-2015.rs:14:5 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:20:5 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:38:9 + --> $DIR/edition-deny-async-fns-2015.rs:36:9 | LL | async fn bar() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:28:9 + --> $DIR/edition-deny-async-fns-2015.rs:26:9 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:33:13 + --> $DIR/edition-deny-async-fns-2015.rs:31:13 | LL | async fn bar() {} | ^^^^^ error[E0706]: trait fns cannot be declared `async` - --> $DIR/edition-deny-async-fns-2015.rs:20:5 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs index 8b60f2f82f..963b19b34a 100644 --- a/src/test/ui/async-await/generics-and-bounds.rs +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::future::Future; pub async fn simple_generic() {} diff --git a/src/test/ui/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs index ad0b49fa4a..9ee419c4a5 100644 --- a/src/test/ui/async-await/issue-60709.rs +++ b/src/test/ui/async-await/issue-60709.rs @@ -4,9 +4,6 @@ // run-pass -#![feature(async_await)] -#![allow(unused)] - use std::future::Future; use std::task::Poll; use std::task::Context; diff --git a/src/test/ui/async-await/issue-61452.rs b/src/test/ui/async-await/issue-61452.rs index 20b9b645da..9381251ad6 100644 --- a/src/test/ui/async-await/issue-61452.rs +++ b/src/test/ui/async-await/issue-61452.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(async_await)] pub async fn f(x: Option) { x.take(); diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index 742490d8de..5eb4b54871 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/issue-61452.rs:5:5 + --> $DIR/issue-61452.rs:4:5 | LL | pub async fn f(x: Option) { | - help: consider changing this to be mutable: `mut x` @@ -7,7 +7,7 @@ LL | x.take(); | ^ cannot borrow as mutable error[E0384]: cannot assign twice to immutable variable `x` - --> $DIR/issue-61452.rs:10:5 + --> $DIR/issue-61452.rs:9:5 | LL | pub async fn g(x: usize) { | - diff --git a/src/test/ui/async-await/issue-61793.rs b/src/test/ui/async-await/issue-61793.rs index a18fad8bb9..f6084be916 100644 --- a/src/test/ui/async-await/issue-61793.rs +++ b/src/test/ui/async-await/issue-61793.rs @@ -6,9 +6,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] -#![allow(unused)] - async fn foo(_: &(), _: F) {} fn main() { diff --git a/src/test/ui/async-await/issue-61949-self-return-type.rs b/src/test/ui/async-await/issue-61949-self-return-type.rs new file mode 100644 index 0000000000..6a28c69193 --- /dev/null +++ b/src/test/ui/async-await/issue-61949-self-return-type.rs @@ -0,0 +1,27 @@ +// ignore-tidy-linelength +// edition:2018 + +// This test checks that `Self` is prohibited as a return type. See #61949 for context. + +pub struct Foo<'a> { + pub bar: &'a i32, +} + +impl<'a> Foo<'a> { + pub async fn new(_bar: &'a i32) -> Self { + //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + Foo { + bar: &22 + } + } +} + +async fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).await + }; + drop(x); +} + +fn main() { } diff --git a/src/test/ui/async-await/issue-61949-self-return-type.stderr b/src/test/ui/async-await/issue-61949-self-return-type.stderr new file mode 100644 index 0000000000..12fb77d8dd --- /dev/null +++ b/src/test/ui/async-await/issue-61949-self-return-type.stderr @@ -0,0 +1,8 @@ +error: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/issue-61949-self-return-type.rs:11:40 + | +LL | pub async fn new(_bar: &'a i32) -> Self { + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issue-62658.rs b/src/test/ui/async-await/issue-62658.rs index 90fbb47bff..d0af01e0c0 100644 --- a/src/test/ui/async-await/issue-62658.rs +++ b/src/test/ui/async-await/issue-62658.rs @@ -4,8 +4,6 @@ // build-pass // edition:2018 -#![feature(async_await)] - async fn noop() {} async fn foo() { diff --git a/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs new file mode 100644 index 0000000000..54059b29f7 --- /dev/null +++ b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs @@ -0,0 +1,19 @@ +// check-pass +// edition:2018 + +struct Test(String); + +impl Test { + async fn borrow_async(&self) {} + + fn with(&mut self, s: &str) -> &mut Self { + self.0 = s.into(); + self + } +} + +async fn test() { + Test("".to_string()).with("123").borrow_async().await; +} + +fn main() { } diff --git a/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs new file mode 100644 index 0000000000..c5ea2b821a --- /dev/null +++ b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs @@ -0,0 +1,12 @@ +// check-pass +// edition:2018 + +async fn foo(x: &[Vec]) -> u32 { + 0 +} + +async fn bar() { + foo(&[vec![123]]).await; +} + +fn main() { } diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs new file mode 100644 index 0000000000..1936d1a2ed --- /dev/null +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs @@ -0,0 +1,25 @@ +// edition:2018 + +use std::sync::Mutex; + +fn is_send(t: T) { + +} + +async fn foo() { + bar(&Mutex::new(22)).await; +} + +async fn bar(x: &Mutex) { + let g = x.lock().unwrap(); + baz().await; +} + +async fn baz() { + +} + +fn main() { + is_send(foo()); + //~^ ERROR `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely [E0277] +} diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr new file mode 100644 index 0000000000..9e9fc52e30 --- /dev/null +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -0,0 +1,23 @@ +error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely + --> $DIR/issue-64130-non-send-future-diags.rs:23:5 + | +LL | fn is_send(t: T) { + | ------- ---- required by this bound in `is_send` +... +LL | is_send(foo()); + | ^^^^^^^ `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, u32>` +note: future does not implement `std::marker::Send` as this value is used across an await + --> $DIR/issue-64130-non-send-future-diags.rs:15:5 + | +LL | let g = x.lock().unwrap(); + | - has type `std::sync::MutexGuard<'_, u32>` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `g` maybe used later +LL | } + | - `g` is later dropped here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs new file mode 100644 index 0000000000..c6faad3aad --- /dev/null +++ b/src/test/ui/async-await/issue-64391.rs @@ -0,0 +1,14 @@ +// Regression test for Issue #64391. The goal here is that this +// function compiles. In the past, due to incorrect drop order for +// temporaries in the tail expression, we failed to compile this +// example. The drop order itself is directly tested in +// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`. +// +// check-pass +// edition:2018 + +async fn add(x: u32, y: u32) -> u32 { + async { x + y }.await +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-51719.rs b/src/test/ui/async-await/issues/issue-51719.rs index 361a49c277..09241f982a 100644 --- a/src/test/ui/async-await/issues/issue-51719.rs +++ b/src/test/ui/async-await/issues/issue-51719.rs @@ -2,8 +2,6 @@ // // Tests that the .await syntax can't be used to make a generator -#![feature(async_await)] - async fn foo() {} fn make_generator() { diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 2a9fb6cf0d..6c3c8889da 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51719.rs:10:19 + --> $DIR/issue-51719.rs:8:19 | LL | let _gen = || foo().await; | -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks diff --git a/src/test/ui/async-await/issues/issue-51751.rs b/src/test/ui/async-await/issues/issue-51751.rs index 7afd7ecc82..bc85a96cea 100644 --- a/src/test/ui/async-await/issues/issue-51751.rs +++ b/src/test/ui/async-await/issues/issue-51751.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - async fn inc(limit: i64) -> i64 { limit + 1 } diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index 97b63d1590..e50c78534f 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51751.rs:11:20 + --> $DIR/issue-51751.rs:9:20 | LL | fn main() { | ---- this is not `async` diff --git a/src/test/ui/async-await/issues/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs index c57dc6b0ef..5cae070444 100644 --- a/src/test/ui/async-await/issues/issue-53249.rs +++ b/src/test/ui/async-await/issues/issue-53249.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(arbitrary_self_types, async_await)] +#![feature(arbitrary_self_types)] use std::task::{self, Poll}; use std::future::Future; diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.rs b/src/test/ui/async-await/issues/issue-54752-async-block.rs index 0036de90b2..64f260cfe0 100644 --- a/src/test/ui/async-await/issues/issue-54752-async-block.rs +++ b/src/test/ui/async-await/issues/issue-54752-async-block.rs @@ -3,7 +3,4 @@ // edition:2018 // pp-exact -#![feature(async_await)] -#![allow(unused_parens)] - fn main() { let _a = (async { }); } diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.stderr b/src/test/ui/async-await/issues/issue-54752-async-block.stderr new file mode 100644 index 0000000000..c3b3392cfc --- /dev/null +++ b/src/test/ui/async-await/issues/issue-54752-async-block.stderr @@ -0,0 +1,8 @@ +warning: unnecessary parentheses around assigned value + --> $DIR/issue-54752-async-block.rs:6:22 + | +LL | fn main() { let _a = (async { }); } + | ^^^^^^^^^^^^ help: remove these parentheses + | + = note: `#[warn(unused_parens)]` on by default + diff --git a/src/test/ui/async-await/issues/issue-54974.rs b/src/test/ui/async-await/issues/issue-54974.rs index 040989b33f..9adc0a8232 100644 --- a/src/test/ui/async-await/issues/issue-54974.rs +++ b/src/test/ui/async-await/issues/issue-54974.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::sync::Arc; trait SomeTrait: Send + Sync + 'static { diff --git a/src/test/ui/async-await/issues/issue-55324.rs b/src/test/ui/async-await/issues/issue-55324.rs index 4f383a51a8..1d77d42012 100644 --- a/src/test/ui/async-await/issues/issue-55324.rs +++ b/src/test/ui/async-await/issues/issue-55324.rs @@ -1,11 +1,8 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::future::Future; -#[allow(unused)] async fn foo>(x: &i32, future: F) -> i32 { let y = future.await; *x + y diff --git a/src/test/ui/async-await/issues/issue-55809.rs b/src/test/ui/async-await/issues/issue-55809.rs index b7e60b773b..3b271775a3 100644 --- a/src/test/ui/async-await/issues/issue-55809.rs +++ b/src/test/ui/async-await/issues/issue-55809.rs @@ -1,8 +1,6 @@ // edition:2018 // run-pass -#![feature(async_await)] - trait Foo { } impl Foo for () { } diff --git a/src/test/ui/async-await/issues/issue-58885.rs b/src/test/ui/async-await/issues/issue-58885.rs index 47744aeea6..72a45b5007 100644 --- a/src/test/ui/async-await/issues/issue-58885.rs +++ b/src/test/ui/async-await/issues/issue-58885.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - struct Xyz { a: u64, } diff --git a/src/test/ui/async-await/issues/issue-59001.rs b/src/test/ui/async-await/issues/issue-59001.rs index 9334ddb0af..ea780d9f62 100644 --- a/src/test/ui/async-await/issues/issue-59001.rs +++ b/src/test/ui/async-await/issues/issue-59001.rs @@ -1,11 +1,8 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::future::Future; -#[allow(unused)] async fn enter<'a, F, R>(mut callback: F) where F: FnMut(&'a mut i32) -> R, diff --git a/src/test/ui/async-await/issues/issue-59972.rs b/src/test/ui/async-await/issues/issue-59972.rs index 8f4254b10c..c2e24a96b1 100644 --- a/src/test/ui/async-await/issues/issue-59972.rs +++ b/src/test/ui/async-await/issues/issue-59972.rs @@ -4,9 +4,7 @@ // run-pass -// compile-flags: --edition=2018 - -#![feature(async_await)] +// compile-flags: --edition=2018 -Aunused pub enum Uninhabited { } @@ -16,14 +14,12 @@ fn uninhabited_async() -> Uninhabited { async fn noop() { } -#[allow(unused)] async fn contains_never() { let error = uninhabited_async(); noop().await; let error2 = error; } -#[allow(unused)] async fn overlap_never() { let error1 = uninhabited_async(); noop().await; @@ -35,6 +31,4 @@ async fn overlap_never() { #[allow(unused_must_use)] fn main() { - contains_never(); - overlap_never(); } diff --git a/src/test/ui/async-await/issues/issue-60518.rs b/src/test/ui/async-await/issues/issue-60518.rs index e4bdc96511..1ca0516075 100644 --- a/src/test/ui/async-await/issues/issue-60518.rs +++ b/src/test/ui/async-await/issues/issue-60518.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - // This is a regression test to ensure that simple bindings (where replacement arguments aren't // created during async fn lowering) that have their DefId used during HIR lowering (such as impl // trait) are visited during def collection and thus have a DefId. diff --git a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs index 99213e64d1..0d015e54f8 100644 --- a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs +++ b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs @@ -3,7 +3,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] #![feature(type_alias_impl_trait)] use std::future::Future; diff --git a/src/test/ui/async-await/issues/issue-60674.rs b/src/test/ui/async-await/issues/issue-60674.rs index 99cdcbafc7..c0e34a8df7 100644 --- a/src/test/ui/async-await/issues/issue-60674.rs +++ b/src/test/ui/async-await/issues/issue-60674.rs @@ -1,7 +1,6 @@ // aux-build:issue-60674.rs // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] // This is a regression test that ensures that `mut` patterns are not lost when provided as input // to a proc macro. diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs index 8b939b43b8..8585a42511 100644 --- a/src/test/ui/async-await/issues/issue-61187.rs +++ b/src/test/ui/async-await/issues/issue-61187.rs @@ -1,8 +1,6 @@ // edition:2018 -#![feature(async_await)] -fn main() { -} +fn main() {} async fn response(data: Vec) { data.reverse(); //~ ERROR E0596 diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr index a031422632..4d361c824d 100644 --- a/src/test/ui/async-await/issues/issue-61187.stderr +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable - --> $DIR/issue-61187.rs:8:5 + --> $DIR/issue-61187.rs:6:5 | LL | async fn response(data: Vec) { | ---- help: consider changing this to be mutable: `mut data` diff --git a/src/test/ui/async-await/issues/issue-61986.rs b/src/test/ui/async-await/issues/issue-61986.rs index 77ecc47dfe..879bc6912f 100644 --- a/src/test/ui/async-await/issues/issue-61986.rs +++ b/src/test/ui/async-await/issues/issue-61986.rs @@ -4,8 +4,6 @@ // Tests that we properly handle StorageDead/StorageLives for temporaries // created in async loop bodies. -#![feature(async_await)] - async fn bar() -> Option<()> { Some(()) } diff --git a/src/test/ui/async-await/issues/issue-62009-1.rs b/src/test/ui/async-await/issues/issue-62009-1.rs index ac6605bcef..788474365c 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.rs +++ b/src/test/ui/async-await/issues/issue-62009-1.rs @@ -1,6 +1,6 @@ // edition:2018 - -#![feature(async_await)] +// ignore-x86 +// ^ due to stderr output differences async fn print_dur() {} diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index 2bbb6d079e..f63eaa4c48 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -32,8 +32,11 @@ error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std: | LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]` + | + ::: $SRC_DIR/libstd/future.rs:LL:COL | - = note: required by `std::future::poll_with_tls_context` +LL | F: Future + | ------ required by this bound in `std::future::poll_with_tls_context` error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issues/issue-62009-2.rs b/src/test/ui/async-await/issues/issue-62009-2.rs index 52b62eaa9e..cb7336e613 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.rs +++ b/src/test/ui/async-await/issues/issue-62009-2.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, async_closure)] +#![feature(async_closure)] async fn print_dur() {} diff --git a/src/test/ui/async-await/issues/issue-62517-1.rs b/src/test/ui/async-await/issues/issue-62517-1.rs new file mode 100644 index 0000000000..4689ce36a7 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62517-1.rs @@ -0,0 +1,21 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait FirstTrait {} +trait SecondTrait { + type Item: ?Sized; +} + +async fn foo(x: &str) -> impl SecondTrait { +} + + +impl SecondTrait for T { + type Item = dyn FirstTrait; +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-62517-2.rs b/src/test/ui/async-await/issues/issue-62517-2.rs new file mode 100644 index 0000000000..aaf28d6c13 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62517-2.rs @@ -0,0 +1,16 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait Object {} + +trait Alpha {} + +async fn foo<'a>(_: &'a ()) -> impl Alpha {} + +impl Alpha for T { } + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr new file mode 100644 index 0000000000..22610fe54a --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr @@ -0,0 +1,24 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-63388-1.rs:12:10 + | +LL | ) -> &dyn Foo + | ^^^^^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#22r + +error: lifetime may not live long enough + --> $DIR/issue-63388-1.rs:13:5 + | +LL | async fn do_sth<'a>( + | -- lifetime `'a` defined here +LL | &'a self, foo: &dyn Foo + | - lifetime `'_` defined here +LL | ) -> &dyn Foo +LL | / { +LL | | foo +LL | | } + | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'_` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/async-await/issues/issue-63388-1.rs b/src/test/ui/async-await/issues/issue-63388-1.rs new file mode 100644 index 0000000000..3cde5de219 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.rs @@ -0,0 +1,18 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + &'a self, foo: &dyn Foo + ) -> &dyn Foo //~ ERROR lifetime mismatch + { + foo + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr new file mode 100644 index 0000000000..a54cadb0cd --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/issue-63388-1.rs:12:10 + | +LL | &'a self, foo: &dyn Foo + | -------- this parameter and the return type are declared with different lifetimes... +LL | ) -> &dyn Foo + | ^^^^^^^^ + | | + | ...but data from `foo` is returned here + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr new file mode 100644 index 0000000000..7781af89de --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr @@ -0,0 +1,11 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-63388-2.rs:12:10 + | +LL | ) -> &dyn Foo + | ^ help: consider using the named lifetime: `&'a` + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs new file mode 100644 index 0000000000..73e7f25f97 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.rs @@ -0,0 +1,18 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer + ) -> &dyn Foo //~ ERROR missing lifetime specifier + { + foo + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr new file mode 100644 index 0000000000..1edeb3d549 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -0,0 +1,29 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-63388-2.rs:12:10 + | +LL | ) -> &dyn Foo + | ^ help: consider using the named lifetime: `&'a` + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` + +error: cannot infer an appropriate lifetime + --> $DIR/issue-63388-2.rs:11:9 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | ^^^ ...but this borrow... +LL | ) -> &dyn Foo + | -------- this return type evaluates to the `'static` lifetime... + | +note: ...can't outlive the lifetime '_ as defined on the method body at 11:14 + --> $DIR/issue-63388-2.rs:11:14 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | ^ +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 11:14 + | +LL | ) -> &dyn Foo + '_ + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-3.rs b/src/test/ui/async-await/issues/issue-63388-3.rs new file mode 100644 index 0000000000..1a9822e02f --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-3.rs @@ -0,0 +1,17 @@ +// edition:2018 +// check-pass + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth( + &self, foo: &dyn Foo + ) { + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-4.rs b/src/test/ui/async-await/issues/issue-63388-4.rs new file mode 100644 index 0000000000..58f9dacb3b --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-4.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +struct A; + +impl A { + async fn foo(&self, f: &u32) -> &A { self } +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-64391-2.rs b/src/test/ui/async-await/issues/issue-64391-2.rs new file mode 100644 index 0000000000..eef2c1fb20 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-64391-2.rs @@ -0,0 +1,20 @@ +// Regression test for #64391 +// +// As described on the issue, the (spurious) `DROP` inserted for the +// `"".to_string()` value was causing a (spurious) unwind path that +// led us to believe that the future might be dropped after `config` +// had been dropped. This cannot, in fact, happen. +// +// check-pass +// edition:2018 + +async fn connect() { + let config = 666; + connect2(&config, "".to_string()).await +} + +async fn connect2(_config: &u32, _tls: String) { + unimplemented!() +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-64433.rs b/src/test/ui/async-await/issues/issue-64433.rs new file mode 100644 index 0000000000..802e09c8a1 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-64433.rs @@ -0,0 +1,30 @@ +// Regression test for issue #64433. +// +// See issue-64391-2.rs for more details, as that was fixed by the +// same PR. +// +// check-pass +// edition:2018 + +#[derive(Debug)] +struct A<'a> { + inner: Vec<&'a str>, +} + +struct B {} + +impl B { + async fn something_with_a(&mut self, a: A<'_>) -> Result<(), String> { + println!("{:?}", a); + Ok(()) + } +} + +async fn can_error(some_string: &str) -> Result<(), String> { + let a = A { inner: vec![some_string, "foo"] }; + let mut b = B {}; + Ok(b.something_with_a(a).await.map(|_| ())?) +} + +fn main() { +} diff --git a/src/test/ui/async-await/issues/issue-64477.rs b/src/test/ui/async-await/issues/issue-64477.rs new file mode 100644 index 0000000000..5bd52d44a5 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-64477.rs @@ -0,0 +1,20 @@ +// Regression test for #64477. +// +// We were incorrectly claiming that the `f(x).await` future captured +// a value of type `T`, and hence that `T: Send` would have to hold. +// +// check-pass +// edition:2018 + +use std::future::Future; +use std::pin::Pin; + +fn f(_: &T) -> Pin + Send>> { + unimplemented!() +} + +pub fn g(x: &'static T) -> impl Future + Send { + async move { f(x).await } +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-64964.rs b/src/test/ui/async-await/issues/issue-64964.rs new file mode 100644 index 0000000000..11f6cb6af9 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-64964.rs @@ -0,0 +1,22 @@ +// check-pass +// compile-flags: -Z query-dep-graph +// edition:2018 + +// Regression test for ICE related to `await`ing in a method + incr. comp. (#64964) + +struct Body; +impl Body { + async fn next(&mut self) { + async {}.await + } +} + +// Another reproduction: `await`ing with a variable from for-loop. + +async fn bar() { + for x in 0..10 { + async { Some(x) }.await.unwrap(); + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.rs b/src/test/ui/async-await/issues/non-async-enclosing-span.rs new file mode 100644 index 0000000000..d47c213772 --- /dev/null +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.rs @@ -0,0 +1,11 @@ +// edition:2018 + +async fn do_the_thing() -> u8 { + 8 +} +// #63398: point at the enclosing scope and not the previously seen closure +fn main() { //~ NOTE this is not `async` + let x = move || {}; + let y = do_the_thing().await; //~ ERROR `await` is only allowed inside `async` functions + //~^ NOTE only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr new file mode 100644 index 0000000000..49ebf414c5 --- /dev/null +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -0,0 +1,11 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/non-async-enclosing-span.rs:9:13 + | +LL | fn main() { + | ---- this is not `async` +LL | let x = move || {}; +LL | let y = do_the_thing().await; + | ^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/move-part-await-return-rest-struct.rs b/src/test/ui/async-await/move-part-await-return-rest-struct.rs index 9bd7a515cb..39ea2aae56 100644 --- a/src/test/ui/async-await/move-part-await-return-rest-struct.rs +++ b/src/test/ui/async-await/move-part-await-return-rest-struct.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - struct Small { x: Vec, y: Vec, diff --git a/src/test/ui/async-await/move-part-await-return-rest-tuple.rs b/src/test/ui/async-await/move-part-await-return-rest-tuple.rs index 69eee855e7..7b958b98b4 100644 --- a/src/test/ui/async-await/move-part-await-return-rest-tuple.rs +++ b/src/test/ui/async-await/move-part-await-return-rest-tuple.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn move_part_await_return_rest_tuple() -> Vec { let x = (vec![3], vec![4, 4]); drop(x.1); diff --git a/src/test/ui/async-await/multiple-lifetimes/elided.rs b/src/test/ui/async-await/multiple-lifetimes/elided.rs index 45f3170d4c..8258e2eff5 100644 --- a/src/test/ui/async-await/multiple-lifetimes/elided.rs +++ b/src/test/ui/async-await/multiple-lifetimes/elided.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_elided_lifetimes(_: &u8, _: &u8) {} fn main() { diff --git a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs index a7254cee75..3912b85474 100644 --- a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs +++ b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {} fn gimme(_: &u8) { } diff --git a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs index 589e260d08..e788ca5ff4 100644 --- a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs +++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs @@ -1,11 +1,8 @@ // edition:2018 -// run-pass +// check-pass // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] -#![allow(dead_code)] - use std::ops::Add; async fn multiple_hrtb_and_single_named_lifetime_ok<'c>( diff --git a/src/test/ui/async-await/multiple-lifetimes/named.rs b/src/test/ui/async-await/multiple-lifetimes/named.rs index cd479e256b..e8eb98102f 100644 --- a/src/test/ui/async-await/multiple-lifetimes/named.rs +++ b/src/test/ui/async-await/multiple-lifetimes/named.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {} fn main() { diff --git a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs index 903c43950a..02b105999f 100644 --- a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs +++ b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs @@ -1,8 +1,6 @@ // edition:2018 // run-pass -#![feature(async_await)] - async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32) where 'b: 'a { diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs index 08622311f7..b901b61aa1 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs @@ -4,7 +4,7 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await, member_constraints)] +#![feature(member_constraints)] trait Trait<'a, 'b> { } impl Trait<'_, '_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs index 08ecea4cc8..2c7a5cd378 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs @@ -3,8 +3,6 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await)] - trait Trait<'a, 'b> { } impl Trait<'_, '_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr index de2c85d772..59d7728d41 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr @@ -1,5 +1,5 @@ error: ambiguous lifetime bound in `impl Trait` - --> $DIR/ret-impl-trait-no-fg.rs:11:64 + --> $DIR/ret-impl-trait-no-fg.rs:9:64 | LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { | ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs index e1b7146527..babc90a5e9 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs @@ -3,7 +3,7 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await, member_constraints)] +#![feature(member_constraints)] trait Trait<'a> { } impl Trait<'_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs index 98da90161e..149c020f9c 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs @@ -4,8 +4,6 @@ // function (which takes multiple lifetimes) only returns data from // one of them. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 { a } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr index fe70d35942..d86e84033b 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `a` because it is borrowed - --> $DIR/ret-ref.rs:18:5 + --> $DIR/ret-ref.rs:16:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `a` occurs here @@ -10,7 +10,7 @@ LL | let p = future.await; | ------ borrow later used here error[E0506]: cannot assign to `b` because it is borrowed - --> $DIR/ret-ref.rs:19:5 + --> $DIR/ret-ref.rs:17:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `b` occurs here @@ -21,7 +21,7 @@ LL | let p = future.await; | ------ borrow later used here error[E0506]: cannot assign to `a` because it is borrowed - --> $DIR/ret-ref.rs:30:5 + --> $DIR/ret-ref.rs:28:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `a` occurs here diff --git a/src/test/ui/async-await/multiple-lifetimes/variance.rs b/src/test/ui/async-await/multiple-lifetimes/variance.rs index b52ad17d56..6ed8bef956 100644 --- a/src/test/ui/async-await/multiple-lifetimes/variance.rs +++ b/src/test/ui/async-await/multiple-lifetimes/variance.rs @@ -4,9 +4,6 @@ // Test for async fn where the parameters have distinct lifetime // parameters that appear in all possible variances. -#![feature(async_await)] - -#[allow(dead_code)] async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { } fn take_any(_: &u8) { } diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs new file mode 100644 index 0000000000..bb2a61f03c --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs @@ -0,0 +1,13 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +async fn rec_1() { //~ ERROR recursion in an `async fn` + rec_2().await; +} + +async fn rec_2() { //~ ERROR recursion in an `async fn` + rec_1().await; +} + +fn main() {} diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr new file mode 100644 index 0000000000..9249308936 --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr @@ -0,0 +1,19 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18 + | +LL | async fn rec_1() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 + | +LL | async fn rec_2() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/src/test/ui/async-await/nested-in-impl.rs b/src/test/ui/async-await/nested-in-impl.rs new file mode 100644 index 0000000000..76ed827d59 --- /dev/null +++ b/src/test/ui/async-await/nested-in-impl.rs @@ -0,0 +1,15 @@ +// Test that async fn works when nested inside of +// impls with lifetime parameters. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn test() { + async fn test() {} + } +} + +fn main() { } diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs deleted file mode 100644 index 62d4b3fb6f..0000000000 --- a/src/test/ui/async-await/no-args-non-move-async-closure.rs +++ /dev/null @@ -1,8 +0,0 @@ -// edition:2018 - -#![feature(async_await, async_closure)] - -fn main() { - let _ = async |x: u8| {}; - //~^ ERROR `async` non-`move` closures with arguments are not currently supported -} diff --git a/src/test/ui/async-await/no-async-const.rs b/src/test/ui/async-await/no-async-const.rs index 1db314a5aa..7a6eb498b2 100644 --- a/src/test/ui/async-await/no-async-const.rs +++ b/src/test/ui/async-await/no-async-const.rs @@ -2,7 +2,5 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - pub async const fn x() {} //~^ ERROR expected one of `fn` or `unsafe`, found `const` diff --git a/src/test/ui/async-await/no-async-const.stderr b/src/test/ui/async-await/no-async-const.stderr index cdb1c6e2d7..edbdfb5652 100644 --- a/src/test/ui/async-await/no-async-const.stderr +++ b/src/test/ui/async-await/no-async-const.stderr @@ -1,5 +1,5 @@ error: expected one of `fn` or `unsafe`, found `const` - --> $DIR/no-async-const.rs:7:11 + --> $DIR/no-async-const.rs:5:11 | LL | pub async const fn x() {} | ^^^^^ expected one of `fn` or `unsafe` here diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index 9f09d2188c..ef7edf8504 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - pub const async fn x() {} -//~^ ERROR expected identifier, found reserved keyword `async` +//~^ ERROR expected identifier, found keyword `async` //~^^ expected `:`, found keyword `fn` diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 693fbf186f..fe05914578 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -1,15 +1,15 @@ -error: expected identifier, found reserved keyword `async` - --> $DIR/no-const-async.rs:7:11 +error: expected identifier, found keyword `async` + --> $DIR/no-const-async.rs:5:11 | LL | pub const async fn x() {} - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | pub const r#async fn x() {} | ^^^^^^^ error: expected `:`, found keyword `fn` - --> $DIR/no-const-async.rs:7:17 + --> $DIR/no-const-async.rs:5:17 | LL | pub const async fn x() {} | ^^ expected `:` diff --git a/src/test/ui/async-await/no-move-across-await-struct.rs b/src/test/ui/async-await/no-move-across-await-struct.rs index 58e0947089..bef477bd25 100644 --- a/src/test/ui/async-await/no-move-across-await-struct.rs +++ b/src/test/ui/async-await/no-move-across-await-struct.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_move_across_await_struct() -> Vec { let s = Small { x: vec![31], y: vec![19, 1441] }; needs_vec(s.x).await; diff --git a/src/test/ui/async-await/no-move-across-await-struct.stderr b/src/test/ui/async-await/no-move-across-await-struct.stderr index 121c7791bd..88f147b8d9 100644 --- a/src/test/ui/async-await/no-move-across-await-struct.stderr +++ b/src/test/ui/async-await/no-move-across-await-struct.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s.x` - --> $DIR/no-move-across-await-struct.rs:10:5 + --> $DIR/no-move-across-await-struct.rs:8:5 | LL | needs_vec(s.x).await; | --- value moved here diff --git a/src/test/ui/async-await/no-move-across-await-tuple.rs b/src/test/ui/async-await/no-move-across-await-tuple.rs index 5d3ed3da1e..565cbd7d5f 100644 --- a/src/test/ui/async-await/no-move-across-await-tuple.rs +++ b/src/test/ui/async-await/no-move-across-await-tuple.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_move_across_await_tuple() -> Vec { let x = (vec![3], vec![4, 4]); drop(x.1); diff --git a/src/test/ui/async-await/no-move-across-await-tuple.stderr b/src/test/ui/async-await/no-move-across-await-tuple.stderr index 5da037ea5c..fe98ecd599 100644 --- a/src/test/ui/async-await/no-move-across-await-tuple.stderr +++ b/src/test/ui/async-await/no-move-across-await-tuple.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x.1` - --> $DIR/no-move-across-await-tuple.rs:11:5 + --> $DIR/no-move-across-await-tuple.rs:9:5 | LL | drop(x.1); | --- value moved here diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs index a916afb6b0..6a34209d55 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs @@ -2,15 +2,13 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_non_guaranteed_initialization(x: usize) -> usize { let y; if x > 5 { y = echo(10).await; } y - //~^ use of possibly uninitialized variable: `y` + //~^ use of possibly-uninitialized variable: `y` } async fn echo(x: usize) -> usize { x + 1 } diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr index fb94522cac..b9aa9924bb 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `y` - --> $DIR/no-non-guaranteed-initialization.rs:12:5 +error[E0381]: use of possibly-uninitialized variable: `y` + --> $DIR/no-non-guaranteed-initialization.rs:10:5 | LL | y - | ^ use of possibly uninitialized `y` + | ^ use of possibly-uninitialized `y` error: aborting due to previous error diff --git a/src/test/ui/async-await/no-params-non-move-async-closure.rs b/src/test/ui/async-await/no-params-non-move-async-closure.rs new file mode 100644 index 0000000000..3b15f35c26 --- /dev/null +++ b/src/test/ui/async-await/no-params-non-move-async-closure.rs @@ -0,0 +1,8 @@ +// edition:2018 + +#![feature(async_closure)] + +fn main() { + let _ = async |x: u8| {}; + //~^ ERROR `async` non-`move` closures with parameters are not currently supported +} diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.stderr b/src/test/ui/async-await/no-params-non-move-async-closure.stderr similarity index 63% rename from src/test/ui/async-await/no-args-non-move-async-closure.stderr rename to src/test/ui/async-await/no-params-non-move-async-closure.stderr index 1b4b86210f..04c8c325fe 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.stderr +++ b/src/test/ui/async-await/no-params-non-move-async-closure.stderr @@ -1,5 +1,5 @@ -error[E0708]: `async` non-`move` closures with arguments are not currently supported - --> $DIR/no-args-non-move-async-closure.rs:6:13 +error[E0708]: `async` non-`move` closures with parameters are not currently supported + --> $DIR/no-params-non-move-async-closure.rs:6:13 | LL | let _ = async |x: u8| {}; | ^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs index 40f9f5202e..8a98a4b0f6 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.rs +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -3,8 +3,6 @@ // edition:2018 -#![feature(async_await)] - struct S { x: i32, y: i32 } struct T(i32, i32); @@ -13,7 +11,7 @@ async fn noop() {} async fn test_tuple() { let mut t: (i32, i32); t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.1 = 88; let _ = t; @@ -22,7 +20,7 @@ async fn test_tuple() { async fn test_tuple_struct() { let mut t: T; t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.1 = 88; let _ = t; @@ -31,7 +29,7 @@ async fn test_tuple_struct() { async fn test_struct() { let mut t: S; t.x = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.y = 88; let _ = t; diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr index fe79eb08be..9a510c22c4 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.stderr +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:15:5 +error[E0381]: assign to part of possibly-uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:13:5 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:24:5 +error[E0381]: assign to part of possibly-uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:22:5 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:33:5 +error[E0381]: assign to part of possibly-uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:31:5 | LL | t.x = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 3 previous errors diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs index 54f3339870..aa77331945 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs @@ -2,8 +2,6 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. -#![feature(async_await)] - async fn recursive_async_function() -> () { //~ ERROR recursive_async_function().await; } diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr index 64f6eccd54..9ee0140218 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr @@ -1,10 +1,10 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/recursive-async-impl-trait-type.rs:7:40 + --> $DIR/recursive-async-impl-trait-type.rs:5:40 | LL | async fn recursive_async_function() -> () { - | ^^ an `async fn` cannot invoke itself directly + | ^^ recursive `async fn` | - = note: a recursive `async fn` must be rewritten to return a boxed future. + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. error: aborting due to previous error diff --git a/src/test/ui/async-await/suggest-missing-await-closure.fixed b/src/test/ui/async-await/suggest-missing-await-closure.fixed index 60c9a8581a..37b30ffe68 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.fixed +++ b/src/test/ui/async-await/suggest-missing-await-closure.fixed @@ -1,7 +1,7 @@ // edition:2018 // run-rustfix -#![feature(async_await, async_closure)] +#![feature(async_closure)] fn take_u32(_x: u32) {} diff --git a/src/test/ui/async-await/suggest-missing-await-closure.rs b/src/test/ui/async-await/suggest-missing-await-closure.rs index cb992a27bc..18076a1516 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.rs +++ b/src/test/ui/async-await/suggest-missing-await-closure.rs @@ -1,7 +1,7 @@ // edition:2018 // run-rustfix -#![feature(async_await, async_closure)] +#![feature(async_closure)] fn take_u32(_x: u32) {} diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed index aa032682be..7c02a907ce 100644 --- a/src/test/ui/async-await/suggest-missing-await.fixed +++ b/src/test/ui/async-await/suggest-missing-await.fixed @@ -1,8 +1,6 @@ // edition:2018 // run-rustfix -#![feature(async_await)] - fn take_u32(_x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index 2ca814fbb2..91abd44e65 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -1,8 +1,6 @@ // edition:2018 // run-rustfix -#![feature(async_await)] - fn take_u32(_x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 9bae715027..ccca97ec20 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:15:14 + --> $DIR/suggest-missing-await.rs:13:14 | LL | take_u32(x) | ^ diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.rs b/src/test/ui/async-await/suggest-switching-edition-on-await.rs new file mode 100644 index 0000000000..1402f1ca92 --- /dev/null +++ b/src/test/ui/async-await/suggest-switching-edition-on-await.rs @@ -0,0 +1,45 @@ +use std::pin::Pin; +use std::future::Future; + +fn main() {} + +fn await_on_struct_missing() { + struct S; + let x = S; + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_struct_similar() { + struct S { + awai: u8, + } + let x = S { awai: 42 }; + x.await; + //~^ ERROR no field `await` on type + //~| HELP a field with a similar name exists + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_63533(x: Pin<&mut dyn Future>) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_apit(x: impl Future) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr new file mode 100644 index 0000000000..f623511c0e --- /dev/null +++ b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr @@ -0,0 +1,43 @@ +error[E0609]: no field `await` on type `await_on_struct_missing::S` + --> $DIR/suggest-switching-edition-on-await.rs:9:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `await_on_struct_similar::S` + --> $DIR/suggest-switching-edition-on-await.rs:22:7 + | +LL | x.await; + | ^^^^^ help: a field with a similar name exists: `awai` + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `std::pin::Pin<&mut dyn std::future::Future>` + --> $DIR/suggest-switching-edition-on-await.rs:31:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `impl Future` + --> $DIR/suggest-switching-edition-on-await.rs:40:7 + | +LL | x.await; + | ^^^^^ + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/async-await/unreachable-lint-1.rs b/src/test/ui/async-await/unreachable-lint-1.rs new file mode 100644 index 0000000000..d63d643c4e --- /dev/null +++ b/src/test/ui/async-await/unreachable-lint-1.rs @@ -0,0 +1,12 @@ +// edition:2018 +#![deny(unreachable_code)] + +async fn foo() { + return; bar().await; + //~^ ERROR unreachable statement +} + +async fn bar() { +} + +fn main() { } diff --git a/src/test/ui/async-await/unreachable-lint-1.stderr b/src/test/ui/async-await/unreachable-lint-1.stderr new file mode 100644 index 0000000000..382581bf94 --- /dev/null +++ b/src/test/ui/async-await/unreachable-lint-1.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/unreachable-lint-1.rs:5:13 + | +LL | return; bar().await; + | ------ ^^^^^^^^^^^^ unreachable statement + | | + | any code following this expression is unreachable + | +note: lint level defined here + --> $DIR/unreachable-lint-1.rs:2:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/unreachable-lint.rs b/src/test/ui/async-await/unreachable-lint.rs new file mode 100644 index 0000000000..ca18cfde4f --- /dev/null +++ b/src/test/ui/async-await/unreachable-lint.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 +#![deny(unreachable_code)] + +async fn foo() { + endless().await; +} + +async fn endless() -> ! { + loop {} +} + +fn main() { } diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs index 578d41fe0d..d8ea87d277 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -2,7 +2,7 @@ // Error message should pinpoint the type parameter T as needing to be bound // (rather than give a general error message) // edition:2018 -#![feature(async_await)] + async fn bar() -> () {} async fn foo() { diff --git a/src/test/ui/attributes/item-attributes.rs b/src/test/ui/attributes/item-attributes.rs index c760a28ecf..79cd0f5fbc 100644 --- a/src/test/ui/attributes/item-attributes.rs +++ b/src/test/ui/attributes/item-attributes.rs @@ -11,8 +11,6 @@ #![rustc_dummy] #![rustc_dummy(attr5)] -#![crate_id="foobar#0.1"] - // These are attributes of the following mod #[rustc_dummy = "val"] #[rustc_dummy = "val"] diff --git a/src/test/ui/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs index 8759344e6f..42f90eda16 100644 --- a/src/test/ui/attributes/obsolete-attr.rs +++ b/src/test/ui/attributes/obsolete-attr.rs @@ -1,9 +1,9 @@ -// Obsolete attributes fall back to feature gated custom attributes. +// Obsolete attributes fall back to unstable custom attributes. #[ab_isize="stdcall"] extern {} -//~^ ERROR cannot find attribute macro `ab_isize` in this scope +//~^ ERROR cannot find attribute `ab_isize` in this scope #[fixed_stack_segment] fn f() {} -//~^ ERROR cannot find attribute macro `fixed_stack_segment` in this scope +//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope fn main() {} diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr index 9c6909f65f..2d7c257c62 100644 --- a/src/test/ui/attributes/obsolete-attr.stderr +++ b/src/test/ui/attributes/obsolete-attr.stderr @@ -1,10 +1,10 @@ -error: cannot find attribute macro `fixed_stack_segment` in this scope +error: cannot find attribute `fixed_stack_segment` in this scope --> $DIR/obsolete-attr.rs:6:3 | LL | #[fixed_stack_segment] fn f() {} | ^^^^^^^^^^^^^^^^^^^ -error: cannot find attribute macro `ab_isize` in this scope +error: cannot find attribute `ab_isize` in this scope --> $DIR/obsolete-attr.rs:3:3 | LL | #[ab_isize="stdcall"] extern {} diff --git a/src/test/ui/attributes/unknown-attr.rs b/src/test/ui/attributes/unknown-attr.rs index 140a1fc3f9..70fef04e95 100644 --- a/src/test/ui/attributes/unknown-attr.rs +++ b/src/test/ui/attributes/unknown-attr.rs @@ -1,12 +1,12 @@ -// Unknown attributes fall back to feature gated custom attributes. +// Unknown attributes fall back to unstable custom attributes. #![feature(custom_inner_attributes)] #![mutable_doc] -//~^ ERROR cannot find attribute macro `mutable_doc` in this scope +//~^ ERROR cannot find attribute `mutable_doc` in this scope #[dance] mod a {} -//~^ ERROR cannot find attribute macro `dance` in this scope +//~^ ERROR cannot find attribute `dance` in this scope #[dance] fn main() {} -//~^ ERROR cannot find attribute macro `dance` in this scope +//~^ ERROR cannot find attribute `dance` in this scope diff --git a/src/test/ui/attributes/unknown-attr.stderr b/src/test/ui/attributes/unknown-attr.stderr index 4d463874d6..85c227dc83 100644 --- a/src/test/ui/attributes/unknown-attr.stderr +++ b/src/test/ui/attributes/unknown-attr.stderr @@ -1,16 +1,16 @@ -error: cannot find attribute macro `mutable_doc` in this scope +error: cannot find attribute `mutable_doc` in this scope --> $DIR/unknown-attr.rs:5:4 | LL | #![mutable_doc] | ^^^^^^^^^^^ -error: cannot find attribute macro `dance` in this scope +error: cannot find attribute `dance` in this scope --> $DIR/unknown-attr.rs:8:3 | LL | #[dance] mod a {} | ^^^^^ -error: cannot find attribute macro `dance` in this scope +error: cannot find attribute `dance` in this scope --> $DIR/unknown-attr.rs:11:3 | LL | #[dance] fn main() {} diff --git a/src/test/ui/attributes/unnamed-field-attributes.rs b/src/test/ui/attributes/unnamed-field-attributes.rs new file mode 100644 index 0000000000..93f364047e --- /dev/null +++ b/src/test/ui/attributes/unnamed-field-attributes.rs @@ -0,0 +1,9 @@ +// check-pass + +struct S( + #[rustfmt::skip] u8, + u16, + #[rustfmt::skip] u32, +); + +fn main() {} diff --git a/src/test/ui/attrs-resolution-errors.rs b/src/test/ui/attrs-resolution-errors.rs new file mode 100644 index 0000000000..a38b3cfa66 --- /dev/null +++ b/src/test/ui/attrs-resolution-errors.rs @@ -0,0 +1,40 @@ +enum FooEnum { + #[test] + //~^ ERROR expected an inert attribute, found an attribute macro + Bar(i32), +} + +struct FooStruct { + #[test] + //~^ ERROR expected an inert attribute, found an attribute macro + bar: i32, +} + +fn main() { + let foo_enum_bar = FooEnum::Bar(1); + match foo_enum_bar { + FooEnum::Bar(x) => {}, + _ => {} + } + + let foo_struct = FooStruct { bar: 1 }; + match foo_struct { + FooStruct { + #[test] bar + //~^ ERROR expected an inert attribute, found an attribute macro + } => {} + } + + match 1 { + 0 => {} + #[test] + //~^ ERROR expected an inert attribute, found an attribute macro + _ => {} + } + + let _another_foo_strunct = FooStruct { + #[test] + //~^ ERROR expected an inert attribute, found an attribute macro + bar: 1, + }; +} diff --git a/src/test/ui/attrs-resolution-errors.stderr b/src/test/ui/attrs-resolution-errors.stderr new file mode 100644 index 0000000000..31f2a74edb --- /dev/null +++ b/src/test/ui/attrs-resolution-errors.stderr @@ -0,0 +1,32 @@ +error: expected an inert attribute, found an attribute macro + --> $DIR/attrs-resolution-errors.rs:2:5 + | +LL | #[test] + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/attrs-resolution-errors.rs:8:5 + | +LL | #[test] + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/attrs-resolution-errors.rs:23:13 + | +LL | #[test] bar + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/attrs-resolution-errors.rs:30:9 + | +LL | #[test] + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/attrs-resolution-errors.rs:36:9 + | +LL | #[test] + | ^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/attrs-resolution.rs b/src/test/ui/attrs-resolution.rs new file mode 100644 index 0000000000..6809773237 --- /dev/null +++ b/src/test/ui/attrs-resolution.rs @@ -0,0 +1,37 @@ +// check-pass + +enum FooEnum { + #[rustfmt::skip] + Bar(i32), +} + +struct FooStruct { + #[rustfmt::skip] + bar: i32, +} + +fn main() { + let foo_enum_bar = FooEnum::Bar(1); + match foo_enum_bar { + FooEnum::Bar(x) => {} + _ => {} + } + + let foo_struct = FooStruct { bar: 1 }; + match foo_struct { + FooStruct { + #[rustfmt::skip] bar + } => {} + } + + match 1 { + 0 => {} + #[rustfmt::skip] + _ => {} + } + + let _another_foo_strunct = FooStruct { + #[rustfmt::skip] + bar: 1, + }; +} diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index f2e0d379d1..3e36f2402a 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -12,7 +12,7 @@ error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` i --> $DIR/auto-ref-slice-plus-ref.rs:8:7 | LL | a.test(); - | ^^^^ + | ^^^^ method not found in `std::vec::Vec<{integer}>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `test`, perhaps you need to implement it: @@ -22,7 +22,7 @@ error[E0599]: no method named `test` found for type `[{integer}; 1]` in the curr --> $DIR/auto-ref-slice-plus-ref.rs:10:11 | LL | ([1]).test(); - | ^^^^ + | ^^^^ method not found in `[{integer}; 1]` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `test`, perhaps you need to implement it: @@ -32,7 +32,7 @@ error[E0599]: no method named `test` found for type `&[{integer}; 1]` in the cur --> $DIR/auto-ref-slice-plus-ref.rs:11:12 | LL | (&[1]).test(); - | ^^^^ + | ^^^^ method not found in `&[{integer}; 1]` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `test`, perhaps you need to implement it: diff --git a/src/test/ui/auxiliary/cond_plugin.rs b/src/test/ui/auxiliary/cond_plugin.rs index 1f97b556a0..2819541bf6 100644 --- a/src/test/ui/auxiliary/cond_plugin.rs +++ b/src/test/ui/auxiliary/cond_plugin.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(proc_macro_hygiene)] +#![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/src/test/ui/auxiliary/proc_macro_def.rs b/src/test/ui/auxiliary/proc_macro_def.rs index dfc5a42d19..49cfb5518b 100644 --- a/src/test/ui/auxiliary/proc_macro_def.rs +++ b/src/test/ui/auxiliary/proc_macro_def.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(proc_macro_hygiene)] +#![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs deleted file mode 100644 index bc9b3a8de4..0000000000 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::sync::mpsc::channel; - -fn main() { - let (tx, rx) = channel(); - let x = Some(rx); - tx.send(false); - match x { - Some(z) if z.recv().unwrap() => { panic!() }, - //~^ ERROR cannot bind by-move into a pattern guard - Some(z) => { assert!(!z.recv().unwrap()); }, - None => panic!() - } -} diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr deleted file mode 100644 index c5f0256c2c..0000000000 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/bind-by-move-no-guards.rs:8:14 - | -LL | Some(z) if z.recv().unwrap() => { panic!() }, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/block-expr-precedence.stderr new file mode 100644 index 0000000000..1307b5d6dd --- /dev/null +++ b/src/test/ui/block-expr-precedence.stderr @@ -0,0 +1,8 @@ +warning: unnecessary trailing semicolons + --> $DIR/block-expr-precedence.rs:60:21 + | +LL | if (true) { 12; };;; -num; + | ^^ help: remove these semicolons + | + = note: `#[warn(redundant_semicolon)]` on by default + diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr index 35101df4e0..40f1aae092 100644 --- a/src/test/ui/borrowck/assign_mutable_fields.stderr +++ b/src/test/ui/borrowck/assign_mutable_fields.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/assign_mutable_fields.rs:9:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/assign_mutable_fields.rs:17:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs index 4427e25186..f11d44e221 100644 --- a/src/test/ui/borrowck/borrowck-and-init.rs +++ b/src/test/ui/borrowck/borrowck-and-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false && { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i` + println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` } diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr index 2db0751948..c7e357d460 100644 --- a/src/test/ui/borrowck/borrowck-and-init.stderr +++ b/src/test/ui/borrowck/borrowck-and-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `i` +error[E0381]: borrow of possibly-uninitialized variable: `i` --> $DIR/borrowck-and-init.rs:5:20 | LL | println!("{}", i); - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-asm.rs b/src/test/ui/borrowck/borrowck-asm.rs index 9c9cc04baa..c1b0f39f93 100644 --- a/src/test/ui/borrowck/borrowck-asm.rs +++ b/src/test/ui/borrowck/borrowck-asm.rs @@ -57,7 +57,7 @@ mod test_cases { fn indirect_is_not_init() { let x: i32; unsafe { - asm!("nop" : "=*r"(x)); //~ ERROR use of possibly uninitialized variable + asm!("nop" : "=*r"(x)); //~ ERROR use of possibly-uninitialized variable } } diff --git a/src/test/ui/borrowck/borrowck-asm.stderr b/src/test/ui/borrowck/borrowck-asm.stderr index c771373022..f85b5983ac 100644 --- a/src/test/ui/borrowck/borrowck-asm.stderr +++ b/src/test/ui/borrowck/borrowck-asm.stderr @@ -46,11 +46,11 @@ LL | unsafe { LL | asm!("nop" : "+r"(x)); | ^ cannot assign twice to immutable variable -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-asm.rs:60:32 | LL | asm!("nop" : "=*r"(x)); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/borrowck-asm.rs:68:31 diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs index 1fed2d503b..1e7306acae 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.rs +++ b/src/test/ui/borrowck/borrowck-block-unint.rs @@ -1,7 +1,7 @@ fn force(f: F) where F: FnOnce() { f(); } fn main() { let x: isize; - force(|| { //~ ERROR borrow of possibly uninitialized variable: `x` + force(|| { //~ ERROR borrow of possibly-uninitialized variable: `x` println!("{}", x); }); } diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr index d2a49962ba..578f89df46 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.stderr +++ b/src/test/ui/borrowck/borrowck-block-unint.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-block-unint.rs:4:11 | LL | force(|| { - | ^^ use of possibly uninitialized `x` + | ^^ use of possibly-uninitialized `x` LL | println!("{}", x); | - borrow occurs due to use in closure diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs index dad5325cb8..126d991a51 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr index e40d8d9dfc..bc9b25c022 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-break-uninit-2.rs:9:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs index 9af02b387d..8ccb21ae8e 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr index bbf9b9f124..766d5cfd63 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-break-uninit.rs:9:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs index 88f74d1ed3..ab607c2acb 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs @@ -78,20 +78,20 @@ fn fu_move_after_fu_move() { fn copy_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` drop(x.a); } fn borrow_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` let p = &x.a; drop(*p); } fn move_after_field_assign_after_uninit() { let mut x: A; - x.b = box 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.b = box 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` drop(x.b); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr index 8952323548..158b2e42f2 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr @@ -108,23 +108,23 @@ LL | let _z = A { a: 4, .. x }; | = note: move occurs because `x.b` has type `std::boxed::Box`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:81:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:87:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:94:5 | LL | x.b = box 1; - | ^^^ use of possibly uninitialized `x` + | ^^^ use of possibly-uninitialized `x` error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs index 044db99d54..f59bcad6f6 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.rs +++ b/src/test/ui/borrowck/borrowck-if-no-else.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; if 1 > 2 { x = 10; } - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr index 1223e409d4..3e9d3d4f6d 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-if-no-else.rs:5:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs index f632d61a6c..c13318b16c 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.rs +++ b/src/test/ui/borrowck/borrowck-if-with-else.rs @@ -7,5 +7,5 @@ fn main() { } else { x = 10; } - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr index d11f29b05f..53b8a6bba2 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-if-with-else.rs:10:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs index f7457781ad..9905e420f9 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let j = || -> isize { let i: isize; - i //~ ERROR use of possibly uninitialized variable: `i` + i //~ ERROR use of possibly-uninitialized variable: `i` }; j(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index 82a602c635..2d1d9bc8fa 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `i` +error[E0381]: use of possibly-uninitialized variable: `i` --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9 | LL | i - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs index 5055814625..7dd3396c8c 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let f = || -> isize { let i: isize; - i //~ ERROR use of possibly uninitialized variable: `i` + i //~ ERROR use of possibly-uninitialized variable: `i` }; println!("{}", f()); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr index 8997393785..fd8b90eda6 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `i` +error[E0381]: use of possibly-uninitialized variable: `i` --> $DIR/borrowck-init-in-fn-expr.rs:4:9 | LL | i - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs index 6da3098dc9..d7ec2ed75c 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs @@ -7,6 +7,6 @@ struct Point { fn main() { let mut origin: Point; origin = Point { x: 10, ..origin }; - //~^ ERROR use of possibly uninitialized variable: `origin` [E0381] + //~^ ERROR use of possibly-uninitialized variable: `origin` [E0381] origin.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr index fe55bc2fd9..a4c042d1c1 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `origin` +error[E0381]: use of possibly-uninitialized variable: `origin` --> $DIR/borrowck-init-in-fru.rs:9:5 | LL | origin = Point { x: 10, ..origin }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `origin.y` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `origin.y` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs index d3fa852ac9..784eb8cf85 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - v += 1; //~ ERROR use of possibly uninitialized variable: `v` + v += 1; //~ ERROR use of possibly-uninitialized variable: `v` v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr index 9863ceb142..6c88778ae0 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `v` +error[E0381]: use of possibly-uninitialized variable: `v` --> $DIR/borrowck-init-op-equal.rs:3:5 | LL | v += 1; - | ^^^^^^ use of possibly uninitialized `v` + | ^^^^^^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs index d895a2e16b..d9d20a2a9c 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs @@ -1,6 +1,6 @@ fn test() { let mut v: isize; - v = v + 1; //~ ERROR use of possibly uninitialized variable: `v` + v = v + 1; //~ ERROR use of possibly-uninitialized variable: `v` v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr index 80c4e0c804..fe09c8581d 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `v` +error[E0381]: use of possibly-uninitialized variable: `v` --> $DIR/borrowck-init-plus-equal.rs:3:9 | LL | v = v + 1; - | ^ use of possibly uninitialized `v` + | ^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr index a33a1d00a5..58f2cadcc6 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr @@ -1,15 +1,14 @@ -warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-migrate-to-nll.rs:28:21 +error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-migrate-to-nll.rs:29:21 | LL | let x = &mut block; | ---------- mutable borrow occurs here LL | let p: &'a u8 = &*block.current; | ^^^^^^^^^^^^^^^ immutable borrow occurs here -LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +... LL | drop(x); | - mutable borrow later used here - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs index 6dda317e57..6587dfdbc0 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs @@ -4,6 +4,8 @@ // // Therefore, for backwards-compatiblity, under borrowck=migrate the // NLL checks will be emitted as *warnings*. +// +// In Rust 2018, no errors will be downgraded to warnings. // NLL mode makes this compile-fail; we cannot currently encode a // test that is run-pass or compile-fail based on compare-mode. So @@ -15,8 +17,7 @@ // revisions: zflag edition //[zflag]compile-flags: -Z borrowck=migrate //[edition]edition:2018 -//[zflag] run-pass -//[edition] run-pass +//[zflag] check-pass pub struct Block<'a> { current: &'a u8, @@ -26,6 +27,7 @@ pub struct Block<'a> { fn bump<'a>(mut block: &mut Block<'a>) { let x = &mut block; let p: &'a u8 = &*block.current; + //[edition]~^ ERROR cannot borrow `*block.current` as immutable // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) drop(x); drop(p); diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr index a33a1d00a5..ace336a3bf 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr @@ -1,11 +1,11 @@ warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-migrate-to-nll.rs:28:21 + --> $DIR/borrowck-migrate-to-nll.rs:29:21 | LL | let x = &mut block; | ---------- mutable borrow occurs here LL | let p: &'a u8 = &*block.current; | ^^^^^^^^^^^^^^^ immutable borrow occurs here -LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +... LL | drop(x); | - mutable borrow later used here | diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs index 5b6aa7a979..9cbceeb945 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs @@ -8,12 +8,9 @@ fn foo() -> isize { let mut x = Enum::A(&mut n); match x { Enum::A(_) if { x = Enum::B(false); false } => 1, - //~^ ERROR cannot assign in a pattern guard - //~| ERROR cannot assign `x` in match guard + //~^ ERROR cannot assign `x` in match guard Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - //~^ ERROR cannot mutably borrow in a pattern guard - //~| ERROR cannot assign in a pattern guard - //~| ERROR cannot mutably borrow `x` in match guard + //~^ ERROR cannot mutably borrow `x` in match guard Enum::A(p) => *p, Enum::B(_) => 2, } diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr index 674f137dbb..6d05e97252 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -1,23 +1,3 @@ -error[E0302]: cannot assign in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:10:25 - | -LL | Enum::A(_) if { x = Enum::B(false); false } => 1, - | ^^^^^^^^^^^^^^^^^^ assignment in pattern guard - -error[E0301]: cannot mutably borrow in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:13:38 - | -LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - | ^ borrowed mutably in pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error[E0302]: cannot assign in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:13:41 - | -LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - | ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard - error[E0510]: cannot assign `x` in match guard --> $DIR/borrowck-mutate-in-guard.rs:10:25 | @@ -27,7 +7,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | ^^^^^^^^^^^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:13:33 + --> $DIR/borrowck-mutate-in-guard.rs:12:33 | LL | match x { | - value is immutable in match guard @@ -35,7 +15,6 @@ LL | match x { LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | ^^^^^^ cannot mutably borrow -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0301, E0302, E0510. -For more information about an error, try `rustc --explain E0301`. +For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs index c0d6c9c273..81b0b80bf1 100644 --- a/src/test/ui/borrowck/borrowck-or-init.rs +++ b/src/test/ui/borrowck/borrowck-or-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false || { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i` + println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` } diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr index 122f519272..3fe8d9eede 100644 --- a/src/test/ui/borrowck/borrowck-or-init.stderr +++ b/src/test/ui/borrowck/borrowck-or-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `i` +error[E0381]: borrow of possibly-uninitialized variable: `i` --> $DIR/borrowck-or-init.rs:5:20 | LL | println!("{}", i); - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs index 0fb955d201..5e5a8cdf42 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs @@ -15,7 +15,7 @@ impl Drop for Test2 { fn stuff() { let mut x : (Test2, Test2); (x.0).0 = Some(Test); - //~^ ERROR assign of possibly uninitialized variable: `x.0` + //~^ ERROR assign of possibly-uninitialized variable: `x.0` } fn main() { diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr index f0a9a7dd5e..218c4f2de5 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr @@ -1,8 +1,8 @@ -error[E0381]: assign of possibly uninitialized variable: `x.0` +error[E0381]: assign of possibly-uninitialized variable: `x.0` --> $DIR/borrowck-partial-reinit-4.rs:17:5 | LL | (x.0).0 = Some(Test); - | ^^^^^^^ use of possibly uninitialized `x.0` + | ^^^^^^^ use of possibly-uninitialized `x.0` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs index e5bee2ca4b..8c623356f6 100644 --- a/src/test/ui/borrowck/borrowck-return.rs +++ b/src/test/ui/borrowck/borrowck-return.rs @@ -1,6 +1,6 @@ fn f() -> isize { let x: isize; - return x; //~ ERROR use of possibly uninitialized variable: `x` + return x; //~ ERROR use of possibly-uninitialized variable: `x` } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr index a2b65af5db..bc74e8e343 100644 --- a/src/test/ui/borrowck/borrowck-return.stderr +++ b/src/test/ui/borrowck/borrowck-return.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-return.rs:3:12 | LL | return x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr index 5b9f49c2e7..8e4932142f 100644 --- a/src/test/ui/borrowck/borrowck-storage-dead.stderr +++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-storage-dead.rs:16:17 | LL | let _ = x + 1; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs index 83f3752a1a..e9a389657c 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.rs +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs @@ -1,5 +1,5 @@ fn main() { let bar; fn baz(_x: isize) { } - baz(bar); //~ ERROR use of possibly uninitialized variable: `bar` + baz(bar); //~ ERROR use of possibly-uninitialized variable: `bar` } diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr index 2d0b21dd0d..f7f069b81b 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `bar` +error[E0381]: use of possibly-uninitialized variable: `bar` --> $DIR/borrowck-uninit-after-item.rs:4:9 | LL | baz(bar); - | ^^^ use of possibly uninitialized `bar` + | ^^^ use of possibly-uninitialized `bar` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr index aa214f9c2f..9f35a4a8d8 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-field-access.rs:21:13 | LL | let _ = a.x + 1; - | ^^^ use of possibly uninitialized `a.x` + | ^^^ use of possibly-uninitialized `a.x` error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:25:13 diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs index bfb0dd4301..20350d61d5 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs @@ -3,32 +3,32 @@ pub fn main() { let x: isize; - x += 1; //~ ERROR use of possibly uninitialized variable: `x` + x += 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x -= 1; //~ ERROR use of possibly uninitialized variable: `x` + x -= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x *= 1; //~ ERROR use of possibly uninitialized variable: `x` + x *= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x /= 1; //~ ERROR use of possibly uninitialized variable: `x` + x /= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x %= 1; //~ ERROR use of possibly uninitialized variable: `x` + x %= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x ^= 1; //~ ERROR use of possibly uninitialized variable: `x` + x ^= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x &= 1; //~ ERROR use of possibly uninitialized variable: `x` + x &= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x |= 1; //~ ERROR use of possibly uninitialized variable: `x` + x |= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x <<= 1; //~ ERROR use of possibly uninitialized variable: `x` + x <<= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x >>= 1; //~ ERROR use of possibly uninitialized variable: `x` + x >>= 1; //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr index 163395e42d..f2036df3ce 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -1,62 +1,62 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:6:5 | LL | x += 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:9:5 | LL | x -= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:12:5 | LL | x *= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:15:5 | LL | x /= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:18:5 | LL | x %= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:21:5 | LL | x ^= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:24:5 | LL | x &= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:27:5 | LL | x |= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:30:5 | LL | x <<= 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:33:5 | LL | x >>= 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs index fa9148f984..0ccea49f32 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs @@ -15,19 +15,19 @@ fn main() { let mut a: S; - a.x = 0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &a.x; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = &&0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &**a.x; let mut a: S; - a.x = 0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &a.y; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ assign to part of possibly uninitialized variable: `a` [E0381] + a.x = &&0; //~ assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &**a.y; } diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr index d87621f04d..d99a50df75 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -1,44 +1,44 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:8:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:11:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:14:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:18:5 | LL | a.x = 0; - | ^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:22:5 | LL | a.x = &&0; - | ^^^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:27:5 | LL | a.x = 0; - | ^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:31:5 | LL | a.x = &&0; - | ^^^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^^^ use of possibly-uninitialized `a` error: aborting due to 7 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs index 71c1f596fa..017b955a39 100644 --- a/src/test/ui/borrowck/borrowck-uninit.rs +++ b/src/test/ui/borrowck/borrowck-uninit.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr index 5db9c1b250..effc209e81 100644 --- a/src/test/ui/borrowck/borrowck-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit.rs:5:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs index 9cab0b1920..3cc71e7cec 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.rs +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs @@ -10,8 +10,8 @@ fn main() { unsafe { let mut s: S; let mut u: U; - s.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `s` - u.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `u` + s.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `s` + u.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `u` let sa = s.a; let ua = u.a; } diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr index 06c884e244..bd9ec5e579 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/borrowck-union-uninitialized.rs:13:9 | LL | s.a = 0; - | ^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/borrowck-union-uninitialized.rs:14:9 | LL | u.a = 0; - | ^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^ use of possibly-uninitialized `u` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr index c03ef759f5..d1b396aba8 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -1,14 +1,14 @@ -error[E0381]: use of possibly uninitialized variable: `w` +error[E0381]: use of possibly-uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:3:5 | LL | w[5] = 0; - | ^^^^ use of possibly uninitialized `*w` + | ^^^^ use of possibly-uninitialized `*w` -error[E0381]: use of possibly uninitialized variable: `w` +error[E0381]: use of possibly-uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 | LL | w[5] = 0; - | ^^^^ use of possibly uninitialized `*w` + | ^^^^ use of possibly-uninitialized `*w` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index 2b80140c6b..ca5227c98c 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13 | LL | let y = x as *const dyn Foo; - | ^ use of possibly uninitialized `*x` + | ^ use of possibly-uninitialized `*x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index 84e717a463..24897a0f2d 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13 | LL | let y = x as *const i32; - | ^ use of possibly uninitialized `*x` + | ^ use of possibly-uninitialized `*x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs index e16bc58656..48e4221470 100644 --- a/src/test/ui/borrowck/borrowck-while-break.rs +++ b/src/test/ui/borrowck/borrowck-while-break.rs @@ -4,7 +4,7 @@ fn test(cond: bool) { v = 3; break; } - println!("{}", v); //~ ERROR borrow of possibly uninitialized variable: `v` + println!("{}", v); //~ ERROR borrow of possibly-uninitialized variable: `v` } fn main() { diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr index 0fe3cdc96a..3eaaf8d7df 100644 --- a/src/test/ui/borrowck/borrowck-while-break.stderr +++ b/src/test/ui/borrowck/borrowck-while-break.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `v` +error[E0381]: borrow of possibly-uninitialized variable: `v` --> $DIR/borrowck-while-break.rs:7:20 | LL | println!("{}", v); - | ^ use of possibly uninitialized `v` + | ^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs index 28a5fb18a7..b3ec20711c 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.rs +++ b/src/test/ui/borrowck/borrowck-while-cond.rs @@ -1,4 +1,4 @@ fn main() { let x: bool; - while x { } //~ ERROR use of possibly uninitialized variable: `x` + while x { } //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr index 06deae345a..92937a9c57 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.stderr +++ b/src/test/ui/borrowck/borrowck-while-cond.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-while-cond.rs:3:11 | LL | while x { } - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs index 4274fa997a..6b3220c7d8 100644 --- a/src/test/ui/borrowck/borrowck-while.rs +++ b/src/test/ui/borrowck/borrowck-while.rs @@ -1,7 +1,7 @@ fn f() -> isize { let mut x: isize; while 1 == 1 { x = 10; } - return x; //~ ERROR use of possibly uninitialized variable: `x` + return x; //~ ERROR use of possibly-uninitialized variable: `x` } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr index 60622d648d..a1f8f64725 100644 --- a/src/test/ui/borrowck/borrowck-while.stderr +++ b/src/test/ui/borrowck/borrowck-while.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-while.rs:4:12 | LL | return x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs index a987c00b09..7043cb3a16 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs @@ -4,19 +4,19 @@ fn main() { let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 1; let mut t: (u64, u64); t.1 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.0 = 1; let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] let mut t: (u64,); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] } diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr index a32b17b165..8d5b39341c 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -1,26 +1,26 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:6:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:11:5 | LL | t.1 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:16:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:20:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/issue-10876.rs b/src/test/ui/borrowck/issue-10876.rs index 20ab905fec..22eaa119f2 100644 --- a/src/test/ui/borrowck/issue-10876.rs +++ b/src/test/ui/borrowck/issue-10876.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass enum Nat { S(Box), diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs index 8d8ac279b2..f031a14444 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs @@ -10,7 +10,7 @@ fn main() { { let mut t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let mut u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let mut v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr index 6f18ff1613..22c6c3964e 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9 | LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9 | LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^^^^ use of possibly-uninitialized `u` -error[E0381]: assign to part of possibly uninitialized variable: `v` +error[E0381]: assign to part of possibly-uninitialized variable: `v` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9 | LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `v` + | ^^^^^^^^^^ use of possibly-uninitialized `v` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs index 1a1b376bf9..660d9e85ef 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs @@ -10,7 +10,7 @@ fn main() { { let t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr index 68873ac5c0..5f9c978c34 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9 | LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9 | LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^^^^ use of possibly-uninitialized `u` -error[E0381]: assign to part of possibly uninitialized variable: `v` +error[E0381]: assign to part of possibly-uninitialized variable: `v` --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9 | LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `v` + | ^^^^^^^^^^ use of possibly-uninitialized `v` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs index 220b2ecf04..f8efa8c891 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs @@ -1,7 +1,7 @@ fn main() { let e: i32; match e { - //~^ ERROR use of possibly uninitialized variable + //~^ ERROR use of possibly-uninitialized variable ref u if true => {} ref v if true => { let tx = 0; diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr index 9701343d2b..0eca447b55 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `e` +error[E0381]: use of possibly-uninitialized variable: `e` --> $DIR/issue-62107-match-arm-scopes.rs:3:11 | LL | match e { - | ^ use of possibly uninitialized `e` + | ^ use of possibly-uninitialized `e` error: aborting due to previous error diff --git a/src/test/ui/borrowck/move-error-snippets-ext.rs b/src/test/ui/borrowck/move-error-snippets-ext.rs new file mode 100644 index 0000000000..c77f6c8276 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets-ext.rs @@ -0,0 +1,7 @@ +// ignore-test + +macro_rules! aaa { + ($c:ident) => {{ + let a = $c; + }} +} diff --git a/src/test/ui/borrowck/move-error-snippets.rs b/src/test/ui/borrowck/move-error-snippets.rs new file mode 100644 index 0000000000..64f9565382 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE after trying to construct a cross-file snippet #63800. + +// compile-flags: --test + +#[macro_use] +#[path = "move-error-snippets-ext.rs"] +mod move_error_snippets_ext; + +struct A; + +macro_rules! sss { + () => { + #[test] + fn fff() { + static D: A = A; + aaa!(D); //~ ERROR cannot move + } + }; +} + +sss!(); + +fn main() {} diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr new file mode 100644 index 0000000000..77463c4859 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of static item `D` + --> $DIR/move-error-snippets.rs:16:18 + | +LL | | #[macro_use] + | |__________________^ move occurs because `D` has type `A`, which does not implement the `Copy` trait +... +LL | aaa!(D); + | __________________^ +... +LL | sss!(); + | ------- in this macro invocation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr index d455a8f078..f09db378a7 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:7:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:15:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index 649c127dcc..5f346708eb 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -1,8 +1,8 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index 9a2824ccb3..14f0fee84c 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -7,11 +7,11 @@ LL | x = (22, 44); LL | x.0 = 1; | ^^^^^^^ cannot assign -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_twice.rs:12:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr new file mode 100644 index 0000000000..c818379762 --- /dev/null +++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/return-local-binding-from-desugaring.rs:26:18 + | +LL | for ref x in xs { + | ^^ creates a temporary which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | result + | ------ borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/borrowck/two-phase-across-loop.rs b/src/test/ui/borrowck/two-phase-across-loop.rs index 12222342c9..3fcea7d171 100644 --- a/src/test/ui/borrowck/two-phase-across-loop.rs +++ b/src/test/ui/borrowck/two-phase-across-loop.rs @@ -1,4 +1,4 @@ -// Test that a borrow which starts as a 2-phase borrow and gets +// Test that a borrow which starts as a two-phase borrow and gets // carried around a loop winds up conflicting with itself. struct Foo { x: String } diff --git a/src/test/ui/borrowck/two-phase-multiple-activations.rs b/src/test/ui/borrowck/two-phase-multiple-activations.rs index a7fa7fac13..599138a9ce 100644 --- a/src/test/ui/borrowck/two-phase-multiple-activations.rs +++ b/src/test/ui/borrowck/two-phase-multiple-activations.rs @@ -11,7 +11,7 @@ pub trait FakeRead { } impl FakeRead for Foo { - fn read_to_end(&mut self, buf: &mut Vec) -> Result { + fn read_to_end(&mut self, _buf: &mut Vec) -> Result { Ok(4) } } @@ -19,5 +19,5 @@ impl FakeRead for Foo { fn main() { let mut a = Foo {}; let mut v = Vec::new(); - a.read_to_end(&mut v); + a.read_to_end(&mut v).unwrap(); } diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs index 3fd24bbf29..6d37d1ded6 100644 --- a/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs @@ -31,7 +31,7 @@ impl <'a> SpanlessHash<'a> { // // Not okay without two-phase borrows: the implicit // `&mut self` of the receiver is evaluated first, and - // that conflicts with the `self.cx`` access during + // that conflicts with the `self.cx` access during // argument evaluation, as demonstrated in `fn demo` // above. // diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs index fef298f7c3..a6f9d0423d 100644 --- a/src/test/ui/break-outside-loop.rs +++ b/src/test/ui/break-outside-loop.rs @@ -7,8 +7,8 @@ fn cond() -> bool { true } fn foo(_: F) where F: FnOnce() {} fn main() { - let pth = break; //~ ERROR: `break` outside of loop - if cond() { continue } //~ ERROR: `continue` outside of loop + let pth = break; //~ ERROR: `break` outside of a loop + if cond() { continue } //~ ERROR: `continue` outside of a loop while cond() { if cond() { break } @@ -21,5 +21,13 @@ fn main() { let rs: Foo = Foo{t: pth}; - let unconstrained = break; //~ ERROR: `break` outside of loop + let unconstrained = break; //~ ERROR: `break` outside of a loop + + // This used to ICE because `target_id` passed to `check_expr_break` would be the closure and + // not the `loop`, which failed in the call to `find_breakable`. (#65383) + 'lab: loop { + || { + break 'lab; //~ ERROR `break` inside of a closure + }; + } } diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr index 8f4656ab39..8e300fd848 100644 --- a/src/test/ui/break-outside-loop.stderr +++ b/src/test/ui/break-outside-loop.stderr @@ -1,34 +1,47 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/break-outside-loop.rs:10:15 | LL | let pth = break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/break-outside-loop.rs:11:17 | LL | if cond() { continue } - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop error[E0267]: `break` inside of a closure --> $DIR/break-outside-loop.rs:17:25 | +LL | foo(|| { + | -- enclosing closure LL | if cond() { break } - | ^^^^^ cannot break inside of a closure + | ^^^^^ cannot `break` inside of a closure error[E0267]: `continue` inside of a closure --> $DIR/break-outside-loop.rs:18:25 | +LL | foo(|| { + | -- enclosing closure +LL | if cond() { break } LL | if cond() { continue } - | ^^^^^^^^ cannot break inside of a closure + | ^^^^^^^^ cannot `continue` inside of a closure -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/break-outside-loop.rs:24:25 | LL | let unconstrained = break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop + +error[E0267]: `break` inside of a closure + --> $DIR/break-outside-loop.rs:30:13 + | +LL | || { + | -- enclosing closure +LL | break 'lab; + | ^^^^^^^^^^ cannot `break` inside of a closure -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0267, E0268. For more information about an error, try `rustc --explain E0267`. diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr index 4947d6e529..ab8398ec5e 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr @@ -37,11 +37,11 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:20:5 | LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `core::ffi::VaListImpl<'1>` + | ------- ------- has type `core::ffi::VaListImpl<'2>` | | - | has type `&mut core::ffi::VaListImpl<'2>` + | has type `&mut core::ffi::VaListImpl<'1>` LL | *ap0 = ap1; - | ^^^^ assignment requires that `'1` must outlive `'2` + | ^^^^ assignment requires that `'2` must outlive `'1` error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:25:5 @@ -57,11 +57,11 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:25:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { - | --- ------- has type `core::ffi::VaListImpl<'1>` + | --- ------- has type `core::ffi::VaListImpl<'2>` | | - | has type `&mut core::ffi::VaListImpl<'2>` + | has type `&mut core::ffi::VaListImpl<'1>` LL | ap0 = &mut ap1; - | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` + | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` error[E0384]: cannot assign to immutable argument `ap0` --> $DIR/variadic-ffi-4.rs:25:5 @@ -99,11 +99,11 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:33:12 | LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `core::ffi::VaListImpl<'1>` + | ------- ------- has type `core::ffi::VaListImpl<'2>` | | - | has type `&mut core::ffi::VaListImpl<'2>` + | has type `&mut core::ffi::VaListImpl<'1>` LL | *ap0 = ap1.clone(); - | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` error: aborting due to 11 previous errors diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs new file mode 100644 index 0000000000..e3b642a9d4 --- /dev/null +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs @@ -0,0 +1,6 @@ +extern { + fn foo(...); + //~^ ERROR C-variadic function must be declared with at least one named argument +} + +fn main() {} diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr new file mode 100644 index 0000000000..cb6060525f --- /dev/null +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -0,0 +1,8 @@ +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-no-fixed-args.rs:2:11 + | +LL | fn foo(...); + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 6cb33f2f2c..c6bc306e45 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -10,17 +10,15 @@ LL | only_foo(x); error[E0277]: the trait bound `{float}: Bar` is not satisfied --> $DIR/type_inference.rs:25:5 | +LL | fn only_bar(_x: T) { } + | -------- --- required by this bound in `only_bar` +... LL | only_bar(x); | ^^^^^^^^ the trait `Bar` is not implemented for `{float}` | = help: the following implementations were found: -note: required by `only_bar` - --> $DIR/type_inference.rs:12:1 - | -LL | fn only_bar(_x: T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr index 39f308cdfd..4cab52e3e9 100644 --- a/src/test/ui/class-cast-to-trait.stderr +++ b/src/test/ui/class-cast-to-trait.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `eat` found for type `std::boxed::Box` --> $DIR/class-cast-to-trait.rs:53:8 | LL | nyan.eat(); - | ^^^ + | ^^^ method not found in `std::boxed::Box` error: aborting due to previous error diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 7e4ac4e8ce..a6b52b258f 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -1,53 +1,41 @@ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:30:5 | +LL | fn with_closure_expecting_fn_with_free_region(_: F) + | ------------------------------------------ +LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) + | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` +... LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` | | | expected signature of `fn(fn(&'a u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 - | -LL | / fn with_closure_expecting_fn_with_free_region(_: F) -LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) -LL | | { -LL | | } - | |_^ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:37:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: F) + | ------------------------------------------- +LL | where F: FnOnce(fn(&u32), &i32) + | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +... LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` | | | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:46:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: F) + | ------------------------------------------- +LL | where F: FnOnce(fn(&u32), &i32) + | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` | | | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ error: aborting due to 3 previous errors diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 40fab4d4ed..ac4666fe36 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -39,53 +39,41 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:30:5 | +LL | fn with_closure_expecting_fn_with_free_region(_: F) + | ------------------------------------------ +LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) + | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` +... LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` | | | expected signature of `fn(fn(&'a u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 - | -LL | / fn with_closure_expecting_fn_with_free_region(_: F) -LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) -LL | | { -LL | | } - | |_^ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:37:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: F) + | ------------------------------------------- +LL | where F: FnOnce(fn(&u32), &i32) + | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +... LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` | | | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:46:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: F) + | ------------------------------------------- +LL | where F: FnOnce(fn(&u32), &i32) + | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` | | | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ error: aborting due to 5 previous errors diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr index c9a697496d..9fbe95a9c3 100644 --- a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr +++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -1,19 +1,15 @@ error[E0631]: type mismatch in closure arguments --> $DIR/expect-infer-var-appearing-twice.rs:14:5 | +LL | fn with_closure(_: F) + | ------------ +LL | where F: FnOnce(A, A) + | ------------ required by this bound in `with_closure` +... LL | with_closure(|x: u32, y: i32| { | ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _` | | | expected signature of `fn(_, _) -> _` - | -note: required by `with_closure` - --> $DIR/expect-infer-var-appearing-twice.rs:1:1 - | -LL | / fn with_closure(_: F) -LL | | where F: FnOnce(A, A) -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closure-expected.stderr index ff77423577..ae4f4d69b5 100644 --- a/src/test/ui/closure-expected.stderr +++ b/src/test/ui/closure-expected.stderr @@ -1,8 +1,8 @@ error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `{integer}` - --> $DIR/closure-expected.rs:3:15 + --> $DIR/closure-expected.rs:3:23 | LL | let y = x.or_else(4); - | ^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` + | ^ expected an `FnOnce<()>` closure, found `{integer}` | = help: the trait `std::ops::FnOnce<()>` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ } diff --git a/src/test/ui/closures/closure-array-break-length.rs b/src/test/ui/closures/closure-array-break-length.rs index a7f16d70ba..f3567db1fa 100644 --- a/src/test/ui/closures/closure-array-break-length.rs +++ b/src/test/ui/closures/closure-array-break-length.rs @@ -1,9 +1,9 @@ fn main() { - |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop + |_: [_; continue]| {}; //~ ERROR: `continue` outside of a loop - while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop + while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of a loop //~^ ERROR mismatched types - while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop + while |_: [_; break]| {} {} //~ ERROR: `break` outside of a loop //~^ ERROR mismatched types } diff --git a/src/test/ui/closures/closure-array-break-length.stderr b/src/test/ui/closures/closure-array-break-length.stderr index 46fbd3e0fa..18da4a94e6 100644 --- a/src/test/ui/closures/closure-array-break-length.stderr +++ b/src/test/ui/closures/closure-array-break-length.stderr @@ -1,20 +1,20 @@ -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/closure-array-break-length.rs:2:13 | LL | |_: [_; continue]| {}; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/closure-array-break-length.rs:4:19 | LL | while |_: [_; continue]| {} {} - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/closure-array-break-length.rs:7:19 | LL | while |_: [_; break]| {} {} - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error[E0308]: mismatched types --> $DIR/closure-array-break-length.rs:4:11 diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 81c4f4e00a..51077b1b29 100644 --- a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: `F` cannot be sent between threads safely --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:5:1 | +LL | struct X where F: FnOnce() + 'static + Send { + | ---------------------------------------------- required by `X` +... LL | / fn foo(blk: F) -> X where F: FnOnce() + 'static { LL | | LL | | return X { field: blk }; @@ -9,11 +12,6 @@ LL | | } | = help: the trait `std::marker::Send` is not implemented for `F` = help: consider adding a `where F: std::marker::Send` bound -note: required by `X` - --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:1:1 - | -LL | struct X where F: FnOnce() + 'static + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index 3b9fd10af3..4b703eded6 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -1,16 +1,14 @@ error[E0277]: `F` cannot be shared between threads safely - --> $DIR/closure-bounds-subtype.rs:13:5 + --> $DIR/closure-bounds-subtype.rs:13:22 | +LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { + | ---------------- ---- required by this bound in `take_const_owned` +... LL | take_const_owned(f); - | ^^^^^^^^^^^^^^^^ `F` cannot be shared between threads safely + | ^ `F` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `F` = help: consider adding a `where F: std::marker::Sync` bound -note: required by `take_const_owned` - --> $DIR/closure-bounds-subtype.rs:4:1 - | -LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/closure-move-sync.rs b/src/test/ui/closures/closure-move-sync.rs index 580cd1af4f..951a3bcb5f 100644 --- a/src/test/ui/closures/closure-move-sync.rs +++ b/src/test/ui/closures/closure-move-sync.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences use std::thread; use std::sync::mpsc::channel; diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr index 8afebc7c74..f676df9c55 100644 --- a/src/test/ui/closures/closure-move-sync.stderr +++ b/src/test/ui/closures/closure-move-sync.stderr @@ -1,24 +1,32 @@ error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely - --> $DIR/closure-move-sync.rs:6:13 + --> $DIR/closure-move-sync.rs:8:13 | LL | let t = thread::spawn(|| { | ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + | + ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL + | +LL | F: FnOnce() -> T, F: Send + 'static, T: Send + 'static + | ---- required by this bound in `std::thread::spawn` | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<()>` = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<()>` - = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6 recv:&std::sync::mpsc::Receiver<()>]` - = note: required by `std::thread::spawn` + = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:8:27: 11:6 recv:&std::sync::mpsc::Receiver<()>]` error[E0277]: `std::sync::mpsc::Sender<()>` cannot be shared between threads safely - --> $DIR/closure-move-sync.rs:18:5 + --> $DIR/closure-move-sync.rs:20:5 | LL | thread::spawn(|| tx.send(()).unwrap()); | ^^^^^^^^^^^^^ `std::sync::mpsc::Sender<()>` cannot be shared between threads safely + | + ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL + | +LL | F: FnOnce() -> T, F: Send + 'static, T: Send + 'static + | ---- required by this bound in `std::thread::spawn` | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>` = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<()>` - = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42 tx:&std::sync::mpsc::Sender<()>]` - = note: required by `std::thread::spawn` + = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:20:19: 20:42 tx:&std::sync::mpsc::Sender<()>]` error: aborting due to 2 previous errors diff --git a/src/test/ui/codemap_tests/bad-format-args.rs b/src/test/ui/codemap_tests/bad-format-args.rs index 9f90185774..dff248344a 100644 --- a/src/test/ui/codemap_tests/bad-format-args.rs +++ b/src/test/ui/codemap_tests/bad-format-args.rs @@ -1,5 +1,5 @@ fn main() { format!(); //~ ERROR requires at least a format string argument format!("" 1); //~ ERROR expected token: `,` - format!("", 1 1); //~ ERROR expected token: `,` + format!("", 1 1); //~ ERROR expected one of } diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index 5b01314d8a..3372ef6dea 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -12,11 +12,11 @@ error: expected token: `,` LL | format!("" 1); | ^ expected `,` -error: expected token: `,` +error: expected one of `,`, `.`, `?`, or an operator, found `1` --> $DIR/bad-format-args.rs:4:19 | LL | format!("", 1 1); - | ^ expected `,` + | ^ expected one of `,`, `.`, `?`, or an operator here error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index 70c1093e9e..8fe24bae7c 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -25,7 +25,7 @@ LL | fn baz(&self) {} LL | fn baz(&self) {} | ---------------- other definition for `baz` | - = note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions error: aborting due to 3 previous errors diff --git a/src/test/ui/coercion/coercion-slice.rs b/src/test/ui/coercion/coercion-slice.rs index 312b634c9f..b69edcf260 100644 --- a/src/test/ui/coercion/coercion-slice.rs +++ b/src/test/ui/coercion/coercion-slice.rs @@ -4,5 +4,5 @@ fn main() { let _: &[i32] = [0]; //~^ ERROR mismatched types //~| expected type `&[i32]` - //~| expected &[i32], found array of 1 elements + //~| expected &[i32], found array of 1 element } diff --git a/src/test/ui/coercion/coercion-slice.stderr b/src/test/ui/coercion/coercion-slice.stderr index 6fa7123711..ccd776e987 100644 --- a/src/test/ui/coercion/coercion-slice.stderr +++ b/src/test/ui/coercion/coercion-slice.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _: &[i32] = [0]; | ^^^ | | - | expected &[i32], found array of 1 elements + | expected &[i32], found array of 1 element | help: consider borrowing here: `&[0]` | = note: expected type `&[i32]` diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr index c38d7456a9..18a7cea95b 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr index c38d7456a9..18a7cea95b 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr index 928b65e003..3a3e1a4afc 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr @@ -7,7 +7,7 @@ LL | impl A where T: Remote { fn dummy(&self) { } } LL | impl A { fn dummy(&self) { } } | ------------------- other definition for `dummy` | - = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr index 928b65e003..3a3e1a4afc 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr @@ -7,7 +7,7 @@ LL | impl A where T: Remote { fn dummy(&self) { } } LL | impl A { fn dummy(&self) { } } | ------------------- other definition for `dummy` | - = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr index 6c3484c2d8..bd6f59f346 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr @@ -6,7 +6,7 @@ LL | impl Foo for T where T: Remote {} LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` | - = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr index 6c3484c2d8..bd6f59f346 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr @@ -6,7 +6,7 @@ LL | impl Foo for T where T: Remote {} LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` | - = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr index cde9360ddf..728eae5e54 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr @@ -7,7 +7,7 @@ LL | LL | impl Foo for A { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | - = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr index cde9360ddf..728eae5e54 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr @@ -7,7 +7,7 @@ LL | LL | impl Foo for A { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | - = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr index 12c7a1f977..4d9f55c121 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr index 12c7a1f977..4d9f55c121 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr index 1b6c62e9bf..f0bcf659bb 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr index 1b6c62e9bf..f0bcf659bb 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr index 11bd788c76..a40153af2c 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr index 11bd788c76..a40153af2c 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T { } LL | impl MyTrait for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)` | - = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_inherent.old.stderr b/src/test/ui/coherence/coherence_inherent.old.stderr index fa564459b2..750d243480 100644 --- a/src/test/ui/coherence/coherence_inherent.old.stderr +++ b/src/test/ui/coherence/coherence_inherent.old.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the c --> $DIR/coherence_inherent.rs:35:11 | LL | s.the_fn(); - | ^^^^^^ + | ^^^^^^ method not found in `&Lib::TheStruct` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/coherence/coherence_inherent.re.stderr b/src/test/ui/coherence/coherence_inherent.re.stderr index fa564459b2..750d243480 100644 --- a/src/test/ui/coherence/coherence_inherent.re.stderr +++ b/src/test/ui/coherence/coherence_inherent.re.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the c --> $DIR/coherence_inherent.rs:35:11 | LL | s.the_fn(); - | ^^^^^^ + | ^^^^^^ method not found in `&Lib::TheStruct` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/coherence/coherence_inherent_cc.old.stderr b/src/test/ui/coherence/coherence_inherent_cc.old.stderr index 4d93e69903..59166a4609 100644 --- a/src/test/ui/coherence/coherence_inherent_cc.old.stderr +++ b/src/test/ui/coherence/coherence_inherent_cc.old.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_li --> $DIR/coherence_inherent_cc.rs:26:11 | LL | s.the_fn(); - | ^^^^^^ + | ^^^^^^ method not found in `&coherence_inherent_cc_lib::TheStruct` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/coherence/coherence_inherent_cc.re.stderr b/src/test/ui/coherence/coherence_inherent_cc.re.stderr index 4d93e69903..59166a4609 100644 --- a/src/test/ui/coherence/coherence_inherent_cc.re.stderr +++ b/src/test/ui/coherence/coherence_inherent_cc.re.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_li --> $DIR/coherence_inherent_cc.rs:26:11 | LL | s.the_fn(); - | ^^^^^^ + | ^^^^^^ method not found in `&coherence_inherent_cc_lib::TheStruct` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/coherence/conflicting-impl-with-err.rs b/src/test/ui/coherence/conflicting-impl-with-err.rs new file mode 100644 index 0000000000..3e0234b874 --- /dev/null +++ b/src/test/ui/coherence/conflicting-impl-with-err.rs @@ -0,0 +1,16 @@ +struct ErrorKind; +struct Error(ErrorKind); + +impl From for Error { //~ ERROR failed to resolve + fn from(_: nope::Thing) -> Self { //~ ERROR failed to resolve + unimplemented!() + } +} + +impl From for Error { + fn from(_: ErrorKind) -> Self { + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/coherence/conflicting-impl-with-err.stderr b/src/test/ui/coherence/conflicting-impl-with-err.stderr new file mode 100644 index 0000000000..a8a5730acc --- /dev/null +++ b/src/test/ui/coherence/conflicting-impl-with-err.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared type or module `nope` + --> $DIR/conflicting-impl-with-err.rs:4:11 + | +LL | impl From for Error { + | ^^^^ use of undeclared type or module `nope` + +error[E0433]: failed to resolve: use of undeclared type or module `nope` + --> $DIR/conflicting-impl-with-err.rs:5:16 + | +LL | fn from(_: nope::Thing) -> Self { + | ^^^^ use of undeclared type or module `nope` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs index e01b0dfa14..a93f9a136d 100644 --- a/src/test/ui/collections-const-new.rs +++ b/src/test/ui/collections-const-new.rs @@ -1,15 +1,11 @@ -// run-pass +// check-pass -#![allow(dead_code)] // Test several functions can be used for constants // 1. Vec::new() // 2. String::new() -#![feature(const_vec_new)] -#![feature(const_string_new)] - const MY_VEC: Vec = Vec::new(); const MY_STRING: String = String::new(); -pub fn main() {} +fn main() {} diff --git a/src/test/ui/commandline-argfile-badutf8.args b/src/test/ui/commandline-argfile-badutf8.args new file mode 100644 index 0000000000..c070b0c240 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.args @@ -0,0 +1,2 @@ +--cfg +unbroken€ \ No newline at end of file diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000..161715685b --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-fail +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000..9af6fc0a51 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs new file mode 100644 index 0000000000..a29b4ab062 --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.rs @@ -0,0 +1,16 @@ +// Check to see if we can get parameters from an @argsfile file +// +// ignore-tidy-linelength +// build-fail +// normalize-stderr-test: "os error \d+" -> "os error $$ERR" +// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr new file mode 100644 index 0000000000..179ad83100 --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/src/test/ui/commandline-argfile.args b/src/test/ui/commandline-argfile.args new file mode 100644 index 0000000000..972938bf6c --- /dev/null +++ b/src/test/ui/commandline-argfile.args @@ -0,0 +1,2 @@ +--cfg +unbroken \ No newline at end of file diff --git a/src/test/ui/commandline-argfile.rs b/src/test/ui/commandline-argfile.rs new file mode 100644 index 0000000000..fc1ba0c8d6 --- /dev/null +++ b/src/test/ui/commandline-argfile.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index a33908c01c..8176e96d6d 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -9,6 +9,8 @@ LL | fn b(&self, _x: G) -> G { panic!() } | = note: expected type `fn(&E, F) -> F` found type `fn(&E, G) -> G` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs new file mode 100644 index 0000000000..9fa726f93e --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a{ +// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr new file mode 100644 index 0000000000..7d2087b4b7 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) + diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr index db3c7acff1..e9df780def 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,6 +1,9 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` + --> $DIR/cfg-attr-cfg-2.rs:8:1 | - = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` +LL | / #[cfg_attr(foo, cfg(bar))] +LL | | fn main() { } + | |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs index 0dceba28b6..7dbeba53af 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs @@ -3,6 +3,6 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_core)] //~ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr index 5a70a5efc7..7b77701ee1 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-crate-2.rs:6:21 | LL | #![cfg_attr(broken, no_core)] diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs index be762c5604..42ffb71e3d 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -1,6 +1,7 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_core, no_std)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr index 5e9adf1780..ab7e1eb960 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-multi-invalid-1.rs:4:21 | LL | #![cfg_attr(broken, no_core, no_std)] diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs index 8a9e99d703..29690e2848 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -1,6 +1,7 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_std, no_core)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr index 06b6715665..8126affbd3 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-multi-invalid-2.rs:4:29 | LL | #![cfg_attr(broken, no_std, no_core)] diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs index 22dbac7667..45b757e928 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs @@ -1,7 +1,7 @@ macro_rules! foo { () => { #[cfg_attr(all(), unknown)] - //~^ ERROR cannot find attribute macro `unknown` in this scope + //~^ ERROR cannot find attribute `unknown` in this scope fn foo() {} } } diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr index c7c52a2923..ef434ec826 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -1,4 +1,4 @@ -error: cannot find attribute macro `unknown` in this scope +error: cannot find attribute `unknown` in this scope --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27 | LL | #[cfg_attr(all(), unknown)] diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs index d80d3ea7b7..53aa355636 100644 --- a/src/test/ui/conditional-compilation/cfg-generic-params.rs +++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs @@ -16,21 +16,23 @@ struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; //~^ ERROR only lifetime parameters can be used in this context fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK -fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR attribute `unknown` is currently unknown +fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} +//~^ ERROR cannot find attribute `unknown` in this scope fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK -fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR attribute `unknown` is currently unknown +fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} +//~^ ERROR cannot find attribute `unknown` in this scope type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); -//~^ ERROR attribute `unknown` is currently unknown +//~^ ERROR cannot find attribute `unknown` in this scope type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; -//~^ ERROR attribute `unknown` is currently unknown +//~^ ERROR cannot find attribute `unknown` in this scope struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; -//~^ ERROR attribute `unknown` is currently unknown +//~^ ERROR cannot find attribute `unknown` in this scope fn main() { f_lt::<'static>(); diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr index 1f9731fcfb..d9e29c8262 100644 --- a/src/test/ui/conditional-compilation/cfg-generic-params.stderr +++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr @@ -16,51 +16,35 @@ error: only lifetime parameters can be used in this context LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; | ^ -error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/cfg-generic-params.rs:19:29 - | -LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} - | ^^^^^^^ +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:34:43 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; + | ^^^^^^^ -error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/cfg-generic-params.rs:21:29 +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:30:40 | -LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; + | ^^^^^^^ -error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/cfg-generic-params.rs:24:34 +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:26:34 | LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable -error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/cfg-generic-params.rs:28:40 +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:22:29 | -LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} + | ^^^^^^^ -error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/cfg-generic-params.rs:32:43 - | -LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; - | ^^^^^^^ +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:19:29 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} + | ^^^^^^^ error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr index c6d42c732c..0b5c3e0335 100644 --- a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` + --> $DIR/cfg-in-crate-1.rs:3:1 | - = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` +LL | #![cfg(bar)] + | ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` error: aborting due to previous error diff --git a/src/test/ui/const-generics/apit-with-const-param.rs b/src/test/ui/const-generics/apit-with-const-param.rs index 70e718d889..7acc50819a 100644 --- a/src/test/ui/const-generics/apit-with-const-param.rs +++ b/src/test/ui/const-generics/apit-with-const-param.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 09652d99e8..594a0d4b5d 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -8,10 +8,10 @@ LL | println!("{:?}", [0_usize; 33]); = note: required by `std::fmt::Debug::fmt` error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/core-traits-no-impls-length-33.rs:9:9 + --> $DIR/core-traits-no-impls-length-33.rs:9:16 | LL | set.insert([0_usize; 33]); - | ^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` + | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` | = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs index d83846fcf8..2d1a405ebd 100644 --- a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs @@ -3,6 +3,8 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +#![allow(dead_code)] + struct ArrayStruct { data: [T; N], } diff --git a/src/test/ui/const-generics/const-types.rs b/src/test/ui/const-generics/const-types.rs index 11757cd588..bc5188133d 100644 --- a/src/test/ui/const-generics/const-types.rs +++ b/src/test/ui/const-generics/const-types.rs @@ -3,7 +3,7 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -#[allow(dead_code)] +#![allow(dead_code, unused_variables)] struct ConstArray { array: [T; LEN], diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.rs b/src/test/ui/const-generics/foreign-item-const-parameter.rs new file mode 100644 index 0000000000..4673c8606c --- /dev/null +++ b/src/test/ui/const-generics/foreign-item-const-parameter.rs @@ -0,0 +1,10 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +extern "C" { + fn foo(); //~ ERROR foreign items may not have const parameters + + fn bar(_: T); //~ ERROR foreign items may not have type or const parameters +} + +fn main() {} diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.stderr new file mode 100644 index 0000000000..999feed2d3 --- /dev/null +++ b/src/test/ui/const-generics/foreign-item-const-parameter.stderr @@ -0,0 +1,27 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/foreign-item-const-parameter.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0044]: foreign items may not have const parameters + --> $DIR/foreign-item-const-parameter.rs:5:5 + | +LL | fn foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters + | + = help: replace the const parameters with concrete consts + +error[E0044]: foreign items may not have type or const parameters + --> $DIR/foreign-item-const-parameter.rs:7:5 + | +LL | fn bar(_: T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters + | + = help: replace the type or const parameters with concrete types or consts + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0044`. diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr index 8f3f91651e..47b090cb88 100644 --- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr +++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -11,7 +11,7 @@ LL | struct S; | --------- method `f` not found for this ... LL | S.f::<0>(); - | ^ + | ^ method not found in `S` error[E0107]: wrong number of const arguments: expected 0, found 1 --> $DIR/invalid-const-arg-for-type-param.rs:8:9 diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs index 68e5a52e0a..45d37b6a2f 100644 --- a/src/test/ui/const-generics/issue-61422.rs +++ b/src/test/ui/const-generics/issue-61422.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash @@ -8,7 +8,7 @@ use std::mem; fn foo() { let arr: [u8; SIZE] = unsafe { #[allow(deprecated)] - let mut array: [u8; SIZE] = mem::uninitialized(); + let array: [u8; SIZE] = mem::uninitialized(); array }; } diff --git a/src/test/ui/const-generics/issue-61432.rs b/src/test/ui/const-generics/issue-61432.rs new file mode 100644 index 0000000000..832095ce54 --- /dev/null +++ b/src/test/ui/const-generics/issue-61432.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn promote() { + // works: + // + // let n = N; + // &n; + + &N; +} + +fn main() { + promote::<0>(); +} diff --git a/src/test/ui/const-generics/issue-61432.stderr b/src/test/ui/const-generics/issue-61432.stderr new file mode 100644 index 0000000000..33f77b0281 --- /dev/null +++ b/src/test/ui/const-generics/issue-61432.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61432.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issue-64519.rs b/src/test/ui/const-generics/issue-64519.rs new file mode 100644 index 0000000000..72cce9b484 --- /dev/null +++ b/src/test/ui/const-generics/issue-64519.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Foo { + state: Option<[u8; D]>, +} + +impl Iterator for Foo<{D}> { + type Item = [u8; D]; + fn next(&mut self) -> Option { + if true { + return Some(self.state.unwrap().clone()); + } else { + return Some(self.state.unwrap().clone()); + } + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-64519.stderr b/src/test/ui/const-generics/issue-64519.stderr new file mode 100644 index 0000000000..d368f39d90 --- /dev/null +++ b/src/test/ui/const-generics/issue-64519.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-64519.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/unused-const-param.rs b/src/test/ui/const-generics/unused-const-param.rs index ee98e5eb4a..8025b3af8f 100644 --- a/src/test/ui/const-generics/unused-const-param.rs +++ b/src/test/ui/const-generics/unused-const-param.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 76013c77de..492182921b 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -2,5 +2,4 @@ fn main() { &{[1, 2, 3][4]}; //~^ ERROR index out of bounds //~| ERROR reaching this expression at runtime will panic or abort - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 18a09fdda7..0ddc2a0e79 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -6,12 +6,6 @@ LL | &{[1, 2, 3][4]}; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/array-literal-index-oob.rs:2:5 - | -LL | &{[1, 2, 3][4]}; - | ^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4 - error: reaching this expression at runtime will panic or abort --> $DIR/array-literal-index-oob.rs:2:7 | @@ -20,5 +14,5 @@ LL | &{[1, 2, 3][4]}; | | | index out of bounds: the len is 3 but the index is 4 -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/auxiliary/issue-63226.rs b/src/test/ui/consts/auxiliary/issue-63226.rs new file mode 100644 index 0000000000..39cc01a415 --- /dev/null +++ b/src/test/ui/consts/auxiliary/issue-63226.rs @@ -0,0 +1,14 @@ +pub struct VTable{ + state:extern fn(), +} + +impl VTable{ + pub const fn vtable()->&'static VTable{ + Self::VTABLE + } + + const VTABLE: &'static VTable = + &VTable{state}; +} + +extern fn state() {} diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index a5f685a159..ecbcc2a4b4 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -5,6 +5,7 @@ #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] + #![deny(const_err)] fn black_box(_: T) { @@ -21,7 +22,7 @@ fn main() { let d = 42u8 - (42u8 + 1); //~^ ERROR const_err let _e = [5u8][1]; - //~^ ERROR const_err + //~^ ERROR index out of bounds black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 659c3afc61..1d84d44dc2 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,35 +1,35 @@ error: this expression will panic at runtime - --> $DIR/const-err2.rs:15:13 + --> $DIR/const-err2.rs:16:13 | LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | note: lint level defined here - --> $DIR/const-err2.rs:8:9 + --> $DIR/const-err2.rs:9:9 | LL | #![deny(const_err)] | ^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/const-err2.rs:17:13 + --> $DIR/const-err2.rs:18:13 | LL | let b = 200u8 + 200u8 + 200u8; | ^^^^^^^^^^^^^ attempt to add with overflow error: this expression will panic at runtime - --> $DIR/const-err2.rs:19:13 + --> $DIR/const-err2.rs:20:13 | LL | let c = 200u8 * 4; | ^^^^^^^^^ attempt to multiply with overflow error: this expression will panic at runtime - --> $DIR/const-err2.rs:21:13 + --> $DIR/const-err2.rs:22:13 | LL | let d = 42u8 - (42u8 + 1); | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:23:14 + --> $DIR/const-err2.rs:24:14 | LL | let _e = [5u8][1]; | ^^^^^^^^ diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs new file mode 100644 index 0000000000..a9cf04cda7 --- /dev/null +++ b/src/test/ui/consts/const-err3.rs @@ -0,0 +1,30 @@ +// needed because negating int::MIN will behave differently between +// optimized compilation and unoptimized compilation and thus would +// lead to different lints being emitted +// compile-flags: -C overflow-checks=on -O + +#![feature(rustc_attrs)] +#![allow(exceeding_bitshifts)] + +#![deny(const_err)] + +fn black_box(_: T) { + unimplemented!() +} + +fn main() { + let a = -std::i8::MIN; + //~^ ERROR const_err + let b = 200u8 + 200u8 + 200u8; + //~^ ERROR const_err + let c = 200u8 * 4; + //~^ ERROR const_err + let d = 42u8 - (42u8 + 1); + //~^ ERROR const_err + let _e = [5u8][1]; + //~^ ERROR const_err + black_box(a); + black_box(b); + black_box(c); + black_box(d); +} diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr new file mode 100644 index 0000000000..0602707be7 --- /dev/null +++ b/src/test/ui/consts/const-err3.stderr @@ -0,0 +1,38 @@ +error: attempt to negate with overflow + --> $DIR/const-err3.rs:16:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/const-err3.rs:9:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to add with overflow + --> $DIR/const-err3.rs:18:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ + +error: attempt to multiply with overflow + --> $DIR/const-err3.rs:20:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/const-err3.rs:22:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ + +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/const-err3.rs:24:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/consts/const-err4.stderr b/src/test/ui/consts/const-err4.stderr index 1feec3c21c..081b09e330 100644 --- a/src/test/ui/consts/const-err4.stderr +++ b/src/test/ui/consts/const-err4.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs index cc5ddb4401..a2196db780 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs @@ -1,5 +1,6 @@ // only-x86_64 +#[repr(C)] union Nonsense { u: usize, int_32_ref: &'static i32, diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index 73aca91153..e0df787f80 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -1,13 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:24:5 + --> $DIR/const-pointer-values-in-various-types.rs:25:5 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:27:43 + --> $DIR/const-pointer-values-in-various-types.rs:28:43 | LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -17,7 +17,7 @@ LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_ = note: `#[deny(const_err)]` on by default error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:30:45 + --> $DIR/const-pointer-values-in-various-types.rs:31:45 | LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -25,7 +25,7 @@ LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uin | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:33:45 + --> $DIR/const-pointer-values-in-various-types.rs:34:45 | LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -33,23 +33,23 @@ LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uin | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:36:5 + --> $DIR/const-pointer-values-in-various-types.rs:37:5 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:39:5 + --> $DIR/const-pointer-values-in-various-types.rs:40:5 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:42:43 + --> $DIR/const-pointer-values-in-various-types.rs:43:43 | LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -57,7 +57,7 @@ LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:45:45 + --> $DIR/const-pointer-values-in-various-types.rs:46:45 | LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -65,7 +65,7 @@ LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:48:45 + --> $DIR/const-pointer-values-in-various-types.rs:49:45 | LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -73,23 +73,23 @@ LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:51:5 + --> $DIR/const-pointer-values-in-various-types.rs:52:5 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:54:5 + --> $DIR/const-pointer-values-in-various-types.rs:55:5 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:57:45 + --> $DIR/const-pointer-values-in-various-types.rs:58:45 | LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -97,15 +97,15 @@ LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.flo | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:60:5 + --> $DIR/const-pointer-values-in-various-types.rs:61:5 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:63:47 + --> $DIR/const-pointer-values-in-various-types.rs:64:47 | LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -113,7 +113,7 @@ LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.t | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:66:47 + --> $DIR/const-pointer-values-in-various-types.rs:67:47 | LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -121,7 +121,7 @@ LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.c | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:69:39 + --> $DIR/const-pointer-values-in-various-types.rs:70:39 | LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -129,7 +129,7 @@ LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:72:41 + --> $DIR/const-pointer-values-in-various-types.rs:73:41 | LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -137,7 +137,7 @@ LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 } | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:75:41 + --> $DIR/const-pointer-values-in-various-types.rs:76:41 | LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -145,15 +145,15 @@ LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 } | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:78:5 + --> $DIR/const-pointer-values-in-various-types.rs:79:5 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:81:43 + --> $DIR/const-pointer-values-in-various-types.rs:82:43 | LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -161,7 +161,7 @@ LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_12 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:84:39 + --> $DIR/const-pointer-values-in-various-types.rs:85:39 | LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -169,7 +169,7 @@ LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:87:41 + --> $DIR/const-pointer-values-in-various-types.rs:88:41 | LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -177,7 +177,7 @@ LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:90:41 + --> $DIR/const-pointer-values-in-various-types.rs:91:41 | LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -185,15 +185,15 @@ LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:93:5 + --> $DIR/const-pointer-values-in-various-types.rs:94:5 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:96:43 + --> $DIR/const-pointer-values-in-various-types.rs:97:43 | LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -201,7 +201,7 @@ LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:99:41 + --> $DIR/const-pointer-values-in-various-types.rs:100:41 | LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -209,15 +209,15 @@ LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:102:5 + --> $DIR/const-pointer-values-in-various-types.rs:103:5 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:105:43 + --> $DIR/const-pointer-values-in-various-types.rs:106:43 | LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -225,7 +225,7 @@ LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_ | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:108:43 + --> $DIR/const-pointer-values-in-various-types.rs:109:43 | LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.rs b/src/test/ui/consts/const-eval/const_fn_ptr.rs new file mode 100644 index 0000000000..498f801db8 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr.rs @@ -0,0 +1,37 @@ +// run-pass +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(const_fn)] + +fn double(x: usize) -> usize { x * 2 } +const fn double_const(x: usize) -> usize { x * 2 } + +const X: fn(usize) -> usize = double; +const X_const: fn(usize) -> usize = double_const; + +const fn bar(x: usize) -> usize { + X(x) +} + +const fn bar_const(x: usize) -> usize { + X_const(x) +} + +const fn foo(x: fn(usize) -> usize, y: usize) -> usize { + x(y) +} + +fn main() { + const Y: usize = bar_const(2); + assert_eq!(Y, 4); + let y = bar_const(2); + assert_eq!(y, 4); + let y = bar(2); + assert_eq!(y, 4); + + const Z: usize = foo(double_const, 2); + assert_eq!(Z, 4); + let z = foo(double_const, 2); + assert_eq!(z, 4); + let z = foo(double, 2); + assert_eq!(z, 4); +} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr new file mode 100644 index 0000000000..41452ee59e --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -0,0 +1,152 @@ +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:25:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:25:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:25:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:27:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:27:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:27:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:29:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:29:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:29:5 + | +LL | assert_eq!(y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:32:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:32:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:32:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:34:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:34:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:34:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:36:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:36:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr.rs:36:5 + | +LL | assert_eq!(z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: constant `X_const` should have an upper case name + --> $DIR/const_fn_ptr.rs:9:7 + | +LL | const X_const: fn(usize) -> usize = double_const; + | ^^^^^^^ help: convert the identifier to upper case: `X_CONST` + | + = note: `#[warn(non_upper_case_globals)]` on by default + diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs new file mode 100644 index 0000000000..14bd6558e7 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs @@ -0,0 +1,13 @@ +// run-pass +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(const_fn)] +#![allow(unused)] + +fn double(x: usize) -> usize { x * 2 } +const X: fn(usize) -> usize = double; + +const fn bar(x: usize) -> usize { + X(x) // FIXME: this should error someday +} + +fn main() {} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs new file mode 100644 index 0000000000..74c60f9a2a --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -0,0 +1,26 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(const_fn)] +#![allow(const_err)] + +fn double(x: usize) -> usize { x * 2 } +const X: fn(usize) -> usize = double; + +const fn bar(x: fn(usize) -> usize, y: usize) -> usize { + x(y) +} + +const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday +const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday + +fn main() { + assert_eq!(Y, 4); + //~^ ERROR evaluation of constant expression failed + //~^^ WARN skipping const checks + //~^^^ WARN skipping const checks + //~^^^^ WARN skipping const checks + assert_eq!(Z, 4); + //~^ ERROR evaluation of constant expression failed + //~^^ WARN skipping const checks + //~^^^ WARN skipping const checks + //~^^^^ WARN skipping const checks +} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr new file mode 100644 index 0000000000..611cc5313c --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -0,0 +1,71 @@ +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:16:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:16:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:16:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:21:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:21:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_fn_ptr_fail2.rs:21:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0080]: evaluation of constant expression failed + --> $DIR/const_fn_ptr_fail2.rs:16:5 + | +LL | assert_eq!(Y, 4); + | ^^^^^^^^^^^-^^^^^ + | | + | referenced constant has errors + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0080]: evaluation of constant expression failed + --> $DIR/const_fn_ptr_fail2.rs:21:5 + | +LL | assert_eq!(Z, 4); + | ^^^^^^^^^^^-^^^^^ + | | + | referenced constant has errors + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const_transmute.rs b/src/test/ui/consts/const-eval/const_transmute.rs index 0e0e003dcf..f0e1d82630 100644 --- a/src/test/ui/consts/const-eval/const_transmute.rs +++ b/src/test/ui/consts/const-eval/const_transmute.rs @@ -1,7 +1,9 @@ // run-pass #![feature(const_fn_union)] +#![allow(dead_code)] +#[repr(C)] union Transmute { t: T, u: U, diff --git a/src/test/ui/consts/const-eval/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs new file mode 100644 index 0000000000..b5d72d46f2 --- /dev/null +++ b/src/test/ui/consts/const-eval/dangling.rs @@ -0,0 +1,13 @@ +#![feature(const_transmute, const_raw_ptr_deref)] + +use std::{mem, usize}; + +// Make sure we error with the right kind of error on a too large slice. +const TEST: () = { unsafe { //~ NOTE + let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); + let _val = &*slice; //~ ERROR: any use of this value will cause an error + //~^ NOTE: total size is bigger than largest supported object + //~^^ on by default +} }; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr new file mode 100644 index 0000000000..286de08009 --- /dev/null +++ b/src/test/ui/consts/const-eval/dangling.stderr @@ -0,0 +1,16 @@ +error: any use of this value will cause an error + --> $DIR/dangling.rs:8:16 + | +LL | / const TEST: () = { unsafe { +LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); +LL | | let _val = &*slice; + | | ^^^^^^^ invalid slice: total size is bigger than largest supported object +LL | | +LL | | +LL | | } }; + | |____- + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs index 2cf6a5494d..ff2fff7fb7 100644 --- a/src/test/ui/consts/const-eval/double_check.rs +++ b/src/test/ui/consts/const-eval/double_check.rs @@ -8,6 +8,7 @@ enum Bar { C = 42, D = 99, } +#[repr(C)] union Union { foo: &'static Foo, bar: &'static Bar, diff --git a/src/test/ui/consts/const-eval/double_check2.rs b/src/test/ui/consts/const-eval/double_check2.rs index dc2b58faf9..7c222b113c 100644 --- a/src/test/ui/consts/const-eval/double_check2.rs +++ b/src/test/ui/consts/const-eval/double_check2.rs @@ -6,6 +6,7 @@ enum Bar { C = 42, D = 99, } +#[repr(C)] union Union { foo: &'static Foo, bar: &'static Bar, diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr index 2b61d33852..28e0922eca 100644 --- a/src/test/ui/consts/const-eval/double_check2.stderr +++ b/src/test/ui/consts/const-eval/double_check2.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/double_check2.rs:15:1 + --> $DIR/double_check2.rs:16:1 | LL | / static FOO: (&Foo, &Bar) = unsafe {( LL | | Union { u8: &BAR }.foo, @@ -7,7 +7,7 @@ LL | | Union { u8: &BAR }.bar, LL | | )}; | |___^ type validation failed: encountered 5 at .1., but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs index b0ae746ace..3f7bab0658 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs @@ -2,6 +2,7 @@ fn main() {} +#[repr(C)] union Foo { u: u32, i: i32, diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr index 5bf43cb8b6..6899b7b82c 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr @@ -1,5 +1,5 @@ error[E0658]: unions in const fn are unstable - --> $DIR/feature-gate-const_fn_union.rs:11:5 + --> $DIR/feature-gate-const_fn_union.rs:12:5 | LL | Foo { u }.i | ^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 478e453fe0..d971d825f2 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -21,16 +21,16 @@ LL | const Y: u32 = foo(0-1); | attempt to subtract with overflow error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:26 + --> $DIR/issue-43197.rs:12:23 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:23 + --> $DIR/issue-43197.rs:12:26 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs index a7c3c5318d..c6caeeffd2 100644 --- a/src/test/ui/consts/const-eval/issue-49296.rs +++ b/src/test/ui/consts/const-eval/issue-49296.rs @@ -4,6 +4,7 @@ #![feature(const_fn_union)] const unsafe fn transmute(t: T) -> U { + #[repr(C)] union Transmute { from: T, to: U, diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 7a4bba8daa..48809e0ae6 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -1,5 +1,5 @@ error: any use of this value will cause an error - --> $DIR/issue-49296.rs:18:16 + --> $DIR/issue-49296.rs:19:16 | LL | const X: u64 = *wat(42); | ---------------^^^^^^^^- diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs index 88181cb861..3edd4e0868 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs @@ -2,6 +2,7 @@ #![allow(const_err)] +#[repr(C)] union Bar { a: &'static u8, b: usize, diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr index 519ba7d84b..6618f1cd1c 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_fn_fail.rs:20:27 + --> $DIR/promoted_const_fn_fail.rs:21:27 | LL | let x: &'static u8 = &(bar() + 1); | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs index 061ab7eeb0..7887e42653 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs @@ -2,6 +2,7 @@ #![deny(const_err)] +#[repr(C)] union Bar { a: &'static u8, b: usize, diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr index 987d2304ae..5f9f3bda87 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_fn_fail_deny_const_err.rs:21:27 + --> $DIR/promoted_const_fn_fail_deny_const_err.rs:22:27 | LL | let x: &'static u8 = &(bar() + 1); | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index fa8859cbb3..45941398f4 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -5,17 +5,15 @@ fn main() { println!("{}", 0u32 - 1); let _x = 0u32 - 1; - //~^ ERROR this expression will panic at runtime [const_err] + //~^ ERROR const_err println!("{}", 1/(1-1)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(1-1); //~^ ERROR const_err //~| ERROR const_err println!("{}", 1/(false as u32)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(false as u32); //~^ ERROR const_err diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 12407accf0..40d5c73e86 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -16,59 +16,47 @@ error: attempt to divide by zero LL | println!("{}", 1/(1-1)); | ^^^^^^^ -error: this expression will panic at runtime +error: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:16:20 +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:9:20 - | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs new file mode 100644 index 0000000000..7adb394144 --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -0,0 +1,22 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +fn main() { + println!("{}", 0u32 - 1); + //~^ ERROR attempt to subtract with overflow + let _x = 0u32 - 1; + //~^ ERROR attempt to subtract with overflow + println!("{}", 1/(1-1)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(1-1); + //~^ ERROR const_err + //~| ERROR const_err + println!("{}", 1/(false as u32)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(false as u32); + //~^ ERROR const_err + //~| ERROR const_err +} diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr new file mode 100644 index 0000000000..2819e6e8fd --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -0,0 +1,68 @@ +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:6:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/promoted_errors2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:8:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs index b6a2ed1f9b..45ce040fb9 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.rs +++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs @@ -9,6 +9,7 @@ fn main() { } } +#[repr(C)] union Foo { f: Int, r: &'static u32, diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr index f8eafed68e..b72a5b80af 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr @@ -1,10 +1,10 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ref_to_int_match.rs:23:1 + --> $DIR/ref_to_int_match.rs:24:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: could not evaluate constant pattern --> $DIR/ref_to_int_match.rs:7:14 diff --git a/src/test/ui/consts/const-eval/strlen.rs b/src/test/ui/consts/const-eval/strlen.rs index 6a5cad82c3..7b14a52354 100644 --- a/src/test/ui/consts/const-eval/strlen.rs +++ b/src/test/ui/consts/const-eval/strlen.rs @@ -1,9 +1,11 @@ // run-pass -#![feature(const_str_len, const_str_as_bytes)] - const S: &str = "foo"; pub const B: &[u8] = S.as_bytes(); +pub const C: usize = B.len(); +pub const D: bool = B.is_empty(); +pub const E: bool = S.is_empty(); +pub const F: usize = S.len(); pub fn foo() -> [u8; S.len()] { let mut buf = [0; S.len()]; @@ -20,4 +22,10 @@ fn main() { assert_eq!(LEN, S.len()); assert_eq!(B, foo()); assert_eq!(B, b"foo"); + assert_eq!(C, 3); + assert_eq!(F, 3); + assert!(!D); + assert!(!E); + const EMPTY: bool = "".is_empty(); + assert!(EMPTY); } diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr index cacf863647..47f89fccf7 100644 --- a/src/test/ui/consts/const-eval/transmute-const.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | static FOO: bool = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index d4b2220695..483285aa4e 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -10,6 +10,7 @@ struct Wrap(T); enum Enum { A = 0, } +#[repr(C)] union TransmuteEnum { in1: &'static u8, in2: usize, @@ -35,6 +36,7 @@ enum Enum2 { A = 2, } +#[repr(C)] union TransmuteEnum2 { in1: usize, in2: &'static u8, @@ -60,6 +62,7 @@ const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }. // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). +#[repr(C)] union TransmuteChar { a: u32, b: char, diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8ecb1aabdd..8ebc9dbec8 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,74 +1,74 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:22:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:25:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:28:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:46:1 + --> $DIR/ub-enum.rs:48:1 | LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:50:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:50:1 + --> $DIR/ub-enum.rs:52:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:54:1 + --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:58:1 + --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:68:1 + --> $DIR/ub-enum.rs:71:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index bcbb4358ae..8ce64ced7d 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -1,5 +1,5 @@ #![feature(rustc_attrs, const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; use std::ptr::NonNull; @@ -11,10 +11,11 @@ const NON_NULL_PTR: NonNull = unsafe { mem::transmute(&1) }; const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +#[deny(const_err)] // this triggers a `const_err` so validation does not even happen const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -//~^ ERROR it is undefined behavior to use this value - let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle - let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic + let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + // Use address-of-element for pointer arithmetic. This could wrap around to NULL! + let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error mem::transmute(out_of_bounds_ptr) } }; @@ -23,6 +24,7 @@ const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +#[repr(C)] union Transmute { uninit: (), out: NonZeroU8, diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index 2f9423fed3..80d80a9867 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -4,60 +4,65 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:14:1 +error: any use of this value will cause an error + --> $DIR/ub-nonnull.rs:18:29 | LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -LL | | -LL | | let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle -LL | | let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic +LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle +LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! +LL | | let out_of_bounds_ptr = &ptr[255]; + | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; - | |____^ type validation failed: encountered a potentially NULL pointer, but expected something that cannot possibly fail to be greater or equal to 1 + | |____- + | +note: lint level defined here + --> $DIR/ub-nonnull.rs:14:8 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior +LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen + | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:21:1 + --> $DIR/ub-nonnull.rs:22:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:23:1 + --> $DIR/ub-nonnull.rs:24:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:30:1 + --> $DIR/ub-nonnull.rs:32:1 | LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:38:1 + --> $DIR/ub-nonnull.rs:40:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:44:1 + --> $DIR/ub-nonnull.rs:46:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 0d8f30159b..03ac12c8b1 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; @@ -11,6 +11,9 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +// It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, +// but that would fail to compile; so we ended up breaking user code that would +// have worked fine had we not promoted. const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index f1702955ed..01bde413c0 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 @@ -12,31 +12,31 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:14:1 + --> $DIR/ub-ref.rs:17:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:17:1 + --> $DIR/ub-ref.rs:20:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:20:1 + --> $DIR/ub-ref.rs:23:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index 42cba02f57..d2745d71bd 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -6,6 +6,7 @@ use std::mem; #[derive(Copy, Clone)] enum Bar {} +#[repr(C)] union TransmuteUnion { a: A, b: B, diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index c8842ecc23..3877f3cab6 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,26 +1,26 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:14:1 + --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:17:1 + --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:20:1 + --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs index 0a427cd885..baab14dc16 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ b/src/test/ui/consts/const-eval/ub-upvars.rs @@ -1,5 +1,5 @@ #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr index f8273ba902..ea6ab3ae5b 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.stderr @@ -8,7 +8,7 @@ LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; | |__^ type validation failed: encountered 0 at ..., but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs new file mode 100644 index 0000000000..1f810c4057 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -0,0 +1,159 @@ +// ignore-tidy-linelength +#![allow(unused)] +#![allow(const_err)] // make sure we cannot allow away the errors tested here + +// normalize-stderr-test "alignment \d+" -> "alignment N" +// normalize-stderr-test "offset \d+" -> "offset N" +// normalize-stderr-test "allocation \d+" -> "allocation N" +// normalize-stderr-test "size \d+" -> "size N" + +#[repr(C)] +union BoolTransmute { + val: u8, + bl: bool, +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct SliceRepr { + ptr: *const u8, + len: usize, +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct BadSliceRepr { + ptr: *const u8, + len: &'static u8, +} + +#[repr(C)] +union SliceTransmute { + repr: SliceRepr, + bad: BadSliceRepr, + addr: usize, + slice: &'static [u8], + raw_slice: *const [u8], + str: &'static str, + my_str: &'static MyStr, + my_slice: &'static MySliceBool, +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct DynRepr { + ptr: *const u8, + vtable: *const u8, +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct DynRepr2 { + ptr: *const u8, + vtable: *const u64, +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct BadDynRepr { + ptr: *const u8, + vtable: usize, +} + +#[repr(C)] +union DynTransmute { + repr: DynRepr, + repr2: DynRepr2, + bad: BadDynRepr, + addr: usize, + rust: &'static dyn Trait, + raw_rust: *const dyn Trait, +} + +trait Trait {} +impl Trait for bool {} + +// custom unsized type +struct MyStr(str); + +// custom unsized type with sized fields +struct MySlice(bool, T); +type MySliceBool = MySlice<[bool]>; + +// # str +// OK +const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +// bad str +const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +//~^ ERROR it is undefined behavior to use this value +// bad str +const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +//~^ ERROR it is undefined behavior to use this value +// bad str in user-defined unsized type +const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +//~^ ERROR it is undefined behavior to use this value + +// invalid UTF-8 +const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +//~^ ERROR it is undefined behavior to use this value +// invalid UTF-8 in user-defined str-like +const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; +//~^ ERROR it is undefined behavior to use this value + +// # slice +// OK +const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +// bad slice: length uninit +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; +//~^ ERROR it is undefined behavior to use this value +// bad slice: length too big +const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +//~^ ERROR it is undefined behavior to use this value +// bad slice: length not an int +const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +//~^ ERROR it is undefined behavior to use this value + +// bad data *inside* the slice +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; +//~^ ERROR it is undefined behavior to use this value + +// good MySliceBool +const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); +// bad: sized field is not okay +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); +//~^ ERROR it is undefined behavior to use this value +// bad: unsized part is not okay +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); +//~^ ERROR it is undefined behavior to use this value + +// # raw slice +const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; +//~^ ERROR it is undefined behavior to use this value + +// # trait object +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value + +// bad data *inside* the trait object +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +//~^ ERROR it is undefined behavior to use this value + +// # raw trait object +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw + +fn main() { +} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr new file mode 100644 index 0000000000..9134ef5a31 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -0,0 +1,147 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:87:1 + | +LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:90:1 + | +LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:93:1 + | +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:97:1 + | +LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:100:1 + | +LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:107:1 + | +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:110:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:113:1 + | +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:117:1 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:123:1 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:126:1 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:133:1 + | +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:138:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:141:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:144:1 + | +LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:148:1 + | +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:152:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:154:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.rs b/src/test/ui/consts/const-eval/union-const-eval-field.rs index 56f3ef3db2..7f29a5bc24 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.rs +++ b/src/test/ui/consts/const-eval/union-const-eval-field.rs @@ -4,6 +4,7 @@ type Field1 = i32; type Field2 = f32; type Field3 = i64; +#[repr(C)] union DummyUnion { field1: Field1, field2: Field2, diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr index 4a53337341..9193bd9dea 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr +++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,10 +1,10 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-const-eval-field.rs:27:5 + --> $DIR/union-const-eval-field.rs:28:5 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs index 33736b360d..5a14c7fd99 100644 --- a/src/test/ui/consts/const-eval/union-ice.rs +++ b/src/test/ui/consts/const-eval/union-ice.rs @@ -3,6 +3,7 @@ type Field1 = i32; type Field3 = i64; +#[repr(C)] union DummyUnion { field1: Field1, field3: Field3, diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index b25cb8c5aa..476f365174 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -1,13 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:13:1 + --> $DIR/union-ice.rs:14:1 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:15:1 + --> $DIR/union-ice.rs:16:1 | LL | / const FIELD_PATH: Struct = Struct { LL | | a: 42, @@ -15,10 +15,10 @@ LL | | b: unsafe { UNION.field3 }, LL | | }; | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:25:1 + --> $DIR/union-ice.rs:26:1 | LL | / const FIELD_PATH2: Struct2 = Struct2 { LL | | b: [ @@ -29,7 +29,7 @@ LL | | a: 42, LL | | }; | |__^ type validation failed: encountered undefined bytes at .b[1] | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs deleted file mode 100644 index d5405f3441..0000000000 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs +++ /dev/null @@ -1,131 +0,0 @@ -#![allow(unused)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here - -// normalize-stderr-test "alignment \d+" -> "alignment N" -// normalize-stderr-test "offset \d+" -> "offset N" -// normalize-stderr-test "allocation \d+" -> "allocation N" -// normalize-stderr-test "size \d+" -> "size N" - -union BoolTransmute { - val: u8, - bl: bool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct SliceRepr { - ptr: *const u8, - len: usize, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadSliceRepr { - ptr: *const u8, - len: &'static u8, -} - -union SliceTransmute { - repr: SliceRepr, - bad: BadSliceRepr, - slice: &'static [u8], - str: &'static str, - my_str: &'static MyStr, - my_slice: &'static MySliceBool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr { - ptr: *const u8, - vtable: *const u8, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr2 { - ptr: *const u8, - vtable: *const u64, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadDynRepr { - ptr: *const u8, - vtable: usize, -} - -union DynTransmute { - repr: DynRepr, - repr2: DynRepr2, - bad: BadDynRepr, - rust: &'static dyn Trait, -} - -trait Trait {} -impl Trait for bool {} - -// custom unsized type -struct MyStr(str); - -// custom unsized type with sized fields -struct MySlice(bool, T); -type MySliceBool = MySlice<[bool]>; - -// OK -const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; -// bad str -const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; -//~^ ERROR it is undefined behavior to use this value -// bad str -const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; -//~^ ERROR it is undefined behavior to use this value -// bad str in user-defined unsized type -const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; -//~^ ERROR it is undefined behavior to use this value - -// OK -const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; -// bad slice -const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; -//~^ ERROR it is undefined behavior to use this value -// bad slice -const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; -//~^ ERROR it is undefined behavior to use this value - -// bad trait object -const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; -//~^ ERROR it is undefined behavior to use this value -// bad trait object -const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; -//~^ ERROR it is undefined behavior to use this value -// bad trait object -const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; -//~^ ERROR it is undefined behavior to use this value - -// bad data *inside* the trait object -const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; -//~^ ERROR it is undefined behavior to use this value - -// bad data *inside* the slice -const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; -//~^ ERROR it is undefined behavior to use this value - -// good MySliceBool -const I1: &MySliceBool = &MySlice(true, [false]); -// bad: sized field is not okay -const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); -//~^ ERROR it is undefined behavior to use this value -// bad: unsized part is not okay -const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); -//~^ ERROR it is undefined behavior to use this value - -// invalid UTF-8 -const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; -//~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 in user-defined str-like -const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; -//~^ ERROR it is undefined behavior to use this value - -fn main() { -} diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr deleted file mode 100644 index aac32ecc5b..0000000000 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:78:1 - | -LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:81:1 - | -LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:84:1 - | -LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:90:1 - | -LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:93:1 - | -LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:97:1 - | -LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:100:1 - | -LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:103:1 - | -LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:107:1 - | -LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:111:1 - | -LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:117:1 - | -LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:120:1 - | -LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:124:1 - | -LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:127:1 - | -LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs index cf436141c5..848826e6ef 100644 --- a/src/test/ui/consts/const-eval/union-ub.rs +++ b/src/test/ui/consts/const-eval/union-ub.rs @@ -1,5 +1,6 @@ #![allow(const_err)] // make sure we cannot allow away the errors tested here +#[repr(C)] union DummyUnion { u8: u8, bool: bool, @@ -14,11 +15,13 @@ enum Enum { } #[derive(Copy, Clone)] +#[repr(C)] union Foo { a: bool, b: Enum, } +#[repr(C)] union Bar { foo: Foo, u8: u8, diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr index 7baa55be6e..fa67bc0d8e 100644 --- a/src/test/ui/consts/const-eval/union-ub.stderr +++ b/src/test/ui/consts/const-eval/union-ub.stderr @@ -1,10 +1,10 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub.rs:28:1 + --> $DIR/union-ub.rs:31:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/union_promotion.rs b/src/test/ui/consts/const-eval/union_promotion.rs index d3566511ef..7167f88a11 100644 --- a/src/test/ui/consts/const-eval/union_promotion.rs +++ b/src/test/ui/consts/const-eval/union_promotion.rs @@ -1,5 +1,6 @@ #![allow(const_err)] +#[repr(C)] union Foo { a: &'static u32, b: usize, diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr index b530c02f2f..ed186e3ebd 100644 --- a/src/test/ui/consts/const-eval/union_promotion.stderr +++ b/src/test/ui/consts/const-eval/union_promotion.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/union_promotion.rs:9:29 + --> $DIR/union_promotion.rs:10:29 | LL | let x: &'static bool = &unsafe { | ____________-------------____^ diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs index 30bd472192..65c642d750 100644 --- a/src/test/ui/consts/const-eval/valid-const.rs +++ b/src/test/ui/consts/const-eval/valid-const.rs @@ -1,7 +1,8 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // Some constants that *are* valid #![feature(const_transmute)] +#![deny(const_err)] use std::mem; use std::ptr::NonNull; diff --git a/src/test/ui/consts/const-int-overflowing-rpass.rs b/src/test/ui/consts/const-int-overflowing-rpass.rs index b619c7908a..9be87a6447 100644 --- a/src/test/ui/consts/const-int-overflowing-rpass.rs +++ b/src/test/ui/consts/const-int-overflowing-rpass.rs @@ -18,6 +18,10 @@ const SHR_B: (u32, bool) = 0x10u32.overflowing_shr(132); const NEG_A: (u32, bool) = 0u32.overflowing_neg(); const NEG_B: (u32, bool) = core::u32::MAX.overflowing_neg(); +const ABS_POS: (i32, bool) = 10i32.overflowing_abs(); +const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs(); +const ABS_MIN: (i32, bool) = i32::min_value().overflowing_abs(); + fn main() { assert_eq!(ADD_A, (7, false)); assert_eq!(ADD_B, (0, true)); @@ -36,4 +40,8 @@ fn main() { assert_eq!(NEG_A, (0, false)); assert_eq!(NEG_B, (1, true)); + + assert_eq!(ABS_POS, (10, false)); + assert_eq!(ABS_NEG, (10, false)); + assert_eq!(ABS_MIN, (i32::min_value(), true)); } diff --git a/src/test/ui/consts/const-int-sign-rpass.rs b/src/test/ui/consts/const-int-sign-rpass.rs index 05726cb228..dc46fce39a 100644 --- a/src/test/ui/consts/const-int-sign-rpass.rs +++ b/src/test/ui/consts/const-int-sign-rpass.rs @@ -11,6 +11,9 @@ const SIGNUM_POS: i32 = 10i32.signum(); const SIGNUM_NIL: i32 = 0i32.signum(); const SIGNUM_NEG: i32 = (-42i32).signum(); +const ABS_A: i32 = 10i32.abs(); +const ABS_B: i32 = (-10i32).abs(); + fn main() { assert!(NEGATIVE_A); assert!(!NEGATIVE_B); @@ -20,4 +23,7 @@ fn main() { assert_eq!(SIGNUM_POS, 1); assert_eq!(SIGNUM_NIL, 0); assert_eq!(SIGNUM_NEG, -1); + + assert_eq!(ABS_A, 10); + assert_eq!(ABS_B, 10); } diff --git a/src/test/ui/consts/const-int-wrapping-rpass.rs b/src/test/ui/consts/const-int-wrapping-rpass.rs index 73147d7912..2bbad99a52 100644 --- a/src/test/ui/consts/const-int-wrapping-rpass.rs +++ b/src/test/ui/consts/const-int-wrapping-rpass.rs @@ -18,6 +18,10 @@ const SHR_B: u32 = 128u32.wrapping_shr(128); const NEG_A: u32 = 5u32.wrapping_neg(); const NEG_B: u32 = 1234567890u32.wrapping_neg(); +const ABS_POS: i32 = 10i32.wrapping_abs(); +const ABS_NEG: i32 = (-10i32).wrapping_abs(); +const ABS_MIN: i32 = i32::min_value().wrapping_abs(); + fn main() { assert_eq!(ADD_A, 255); assert_eq!(ADD_B, 199); @@ -36,4 +40,8 @@ fn main() { assert_eq!(NEG_A, 4294967291); assert_eq!(NEG_B, 3060399406); + + assert_eq!(ABS_POS, 10); + assert_eq!(ABS_NEG, 10); + assert_eq!(ABS_MIN, i32::min_value()); } diff --git a/src/test/ui/consts/const-labeled-break.rs b/src/test/ui/consts/const-labeled-break.rs index 36e308ade9..7cdbb22f92 100644 --- a/src/test/ui/consts/const-labeled-break.rs +++ b/src/test/ui/consts/const-labeled-break.rs @@ -1,4 +1,4 @@ -// run-pass +// build-pass // Using labeled break in a while loop has caused an illegal instruction being // generated, and an ICE later. diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 3bcb50c6dc..24d2e3ce53 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:25:15 | LL | A = { let 0 = 0; 0 }, - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index e292e1cc16..5d59d06f79 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:31:24 | LL | let x: [i32; { let 0 = 0; 0 }] = []; - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index 8a9fbde853..6d74c26f9f 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -1,26 +1,26 @@ -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:4:22 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:8:23 | LL | static Y: i32 = { let 0 = 0; 0 }; - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:13:26 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered -error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:19:26 | LL | const X: i32 = { let 0 = 0; 0 }; - | ^ pattern `std::i32::MIN..=-1i32` not covered + | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-pattern-irrefutable.rs b/src/test/ui/consts/const-pattern-irrefutable.rs index d3f7be18a9..60e16aaf89 100644 --- a/src/test/ui/consts/const-pattern-irrefutable.rs +++ b/src/test/ui/consts/const-pattern-irrefutable.rs @@ -9,8 +9,8 @@ use foo::d; const a: u8 = 2; fn main() { - let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered - let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered - let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered + let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX + let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX + let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr index 48fe24df4d..06f5e90d2f 100644 --- a/src/test/ui/consts/const-pattern-irrefutable.stderr +++ b/src/test/ui/consts/const-pattern-irrefutable.stderr @@ -1,16 +1,16 @@ -error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered --> $DIR/const-pattern-irrefutable.rs:12:9 | LL | let a = 4; | ^ interpreted as a constant pattern, not new variable -error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered --> $DIR/const-pattern-irrefutable.rs:13:9 | LL | let c = 4; | ^ interpreted as a constant pattern, not new variable -error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered +error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered --> $DIR/const-pattern-irrefutable.rs:14:9 | LL | let d = 4; diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 113ec29239..1ae39e7563 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -4,18 +4,23 @@ error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{con LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... + --> $DIR/const-size_of-cycle.rs:6:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... --> $SRC_DIR/libcore/mem/mod.rs:LL:COL | LL | intrinsics::size_of::() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `std::intrinsics::size_of`... + --> $SRC_DIR/libcore/intrinsics.rs:LL:COL + | +LL | pub fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... - --> $DIR/const-size_of-cycle.rs:6:17 - | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/const-size_of-cycle.rs:5:1 diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs index 7b3a591223..d48d5945e7 100644 --- a/src/test/ui/consts/const_let_refutable.rs +++ b/src/test/ui/consts/const_let_refutable.rs @@ -2,6 +2,6 @@ fn main() {} const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument a + b //~ ERROR can only call other `const fn` within a `const fn` - //~^ ERROR use of possibly uninitialized variable: `a` - //~| ERROR use of possibly uninitialized variable: `b` + //~^ ERROR use of possibly-uninitialized variable: `a` + //~| ERROR use of possibly-uninitialized variable: `b` } diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index a61c9b0c9f..7f15f02d4d 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in function argument: `&[]` not covered +error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered --> $DIR/const_let_refutable.rs:3:16 | LL | const fn slice([a, b]: &[i32]) -> i32 { - | ^^^^^^ pattern `&[]` not covered + | ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn` --> $DIR/const_let_refutable.rs:4:5 @@ -13,17 +13,17 @@ LL | a + b = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b - | ^ use of possibly uninitialized `a` + | ^ use of possibly-uninitialized `a` -error[E0381]: use of possibly uninitialized variable: `b` +error[E0381]: use of possibly-uninitialized variable: `b` --> $DIR/const_let_refutable.rs:4:9 | LL | a + b - | ^ use of possibly uninitialized `b` + | ^ use of possibly-uninitialized `b` error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-63226.rs b/src/test/ui/consts/issue-63226.rs new file mode 100644 index 0000000000..deec449900 --- /dev/null +++ b/src/test/ui/consts/issue-63226.rs @@ -0,0 +1,12 @@ +// aux-build:issue-63226.rs +// compile-flags:--extern issue_63226 +// edition:2018 +// build-pass +// A regression test for issue #63226. +// Checks if `const fn` is marked as reachable. + +use issue_63226::VTable; + +static ICE_ICE:&'static VTable=VTable::vtable(); + +fn main() {} diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs new file mode 100644 index 0000000000..38911c3dcf --- /dev/null +++ b/src/test/ui/consts/issue-64059-2.rs @@ -0,0 +1,6 @@ +// compile-flags: -C overflow-checks=on -O +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs new file mode 100644 index 0000000000..c4c895fef6 --- /dev/null +++ b/src/test/ui/consts/issue-64059.rs @@ -0,0 +1,5 @@ +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr index 158581fcb1..bf0bd3aca9 100644 --- a/src/test/ui/consts/match_ice.stderr +++ b/src/test/ui/consts/match_ice.stderr @@ -7,6 +7,9 @@ LL | C => {} error[E0004]: non-exhaustive patterns: `&T` not covered --> $DIR/match_ice.rs:15:11 | +LL | struct T; + | --------- `T` defined here +... LL | match K { | ^ pattern `&T` not covered | diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs new file mode 100644 index 0000000000..0b1ab1c34f --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -0,0 +1,16 @@ +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } +//~^ dereferencing raw pointers in constant functions + +fn main() {} + +const unsafe fn no_union() { + union Foo { x: (), y: () } + Foo { x: () }.y + //~^ accessing union fields is unstable +} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr similarity index 79% rename from src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr rename to src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index d3f2ece1f9..2a4c627438 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -1,5 +1,5 @@ error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:50:77 + --> $DIR/min_const_fn_unsafe_bad.rs:1:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } | ^^^ @@ -8,7 +8,7 @@ LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:53:70 + --> $DIR/min_const_fn_unsafe_bad.rs:4:70 | LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } | ^^ @@ -17,7 +17,7 @@ LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:56:83 + --> $DIR/min_const_fn_unsafe_bad.rs:7:83 | LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } | ^^^ @@ -25,17 +25,17 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u = note: for more information, see https://github.com/rust-lang/rust/issues/51911 = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable -error[E0658]: unions in const fn are unstable - --> $DIR/min_const_fn_unsafe.rs:63:5 +error[E0723]: accessing union fields is unstable + --> $DIR/min_const_fn_unsafe_bad.rs:14:5 | LL | Foo { x: () }.y | ^^^^^^^^^^^^^^^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/51909 - = help: add `#![feature(const_fn_union)]` to the crate attributes to enable + = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe.rs:50:77 + --> $DIR/min_const_fn_unsafe_bad.rs:1:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } | ^^^ dereference of raw pointer @@ -44,5 +44,5 @@ LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { error: aborting due to 5 previous errors -Some errors have detailed explanations: E0133, E0658. +Some errors have detailed explanations: E0133, E0658, E0723. For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs similarity index 61% rename from src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs rename to src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs index 0152561aef..02c7970dec 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs @@ -1,6 +1,4 @@ -//------------------------------------------------------------------------------ -// OK -//------------------------------------------------------------------------------ +// check-pass const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } const unsafe fn ret_null_ptr_no_unsafe() -> *const T { std::ptr::null() } @@ -43,23 +41,4 @@ const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate() ret_null_mut_ptr_no_unsafe::>>() } -//------------------------------------------------------------------------------ -// NOT OK -//------------------------------------------------------------------------------ - -const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe -//~^ dereferencing raw pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } -//~^ dereferencing raw pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } -//~^ dereferencing raw pointers in constant functions - fn main() {} - -const unsafe fn no_union() { - union Foo { x: (), y: () } - Foo { x: () }.y - //~^ unions in const fn -} diff --git a/src/test/ui/consts/miri_unleashed/enum_discriminants.rs b/src/test/ui/consts/miri_unleashed/enum_discriminants.rs new file mode 100644 index 0000000000..9f34fc7395 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/enum_discriminants.rs @@ -0,0 +1,110 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// run-pass + +//! Make sure that we read and write enum discriminants correctly for corner cases caused +//! by layout optimizations. + +const OVERFLOW: usize = { + // Tests for https://github.com/rust-lang/rust/issues/62138. + #[repr(u8)] + #[allow(dead_code)] + enum WithWraparoundInvalidValues { + X = 1, + Y = 254, + } + + #[allow(dead_code)] + enum Foo { + A, + B, + C(WithWraparoundInvalidValues), + } + + let x = Foo::B; + match x { + Foo::B => 0, + _ => panic!(), + } +}; + +const MORE_OVERFLOW: usize = { + pub enum Infallible {} + + // The check that the `bool` field of `V1` is encoding a "niche variant" + // (i.e. not `V1`, so `V3` or `V4`) used to be mathematically incorrect, + // causing valid `V1` values to be interpreted as other variants. + #[allow(dead_code)] + pub enum E1 { + V1 { f: bool }, + V2 { f: Infallible }, + V3, + V4, + } + + // Computing the discriminant used to be done using the niche type (here `u8`, + // from the `bool` field of `V1`), overflowing for variants with large enough + // indices (`V3` and `V4`), causing them to be interpreted as other variants. + #[allow(dead_code)] + pub enum E2 { + V1 { f: bool }, + + /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), + _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), + _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), + _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), + _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), + _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), + _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), + _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), + _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), + _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), + _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), + _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), + _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), + _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), + _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), + _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), + _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), + _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), + _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), + _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), + _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), + _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), + _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), + _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), + _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), + _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), + _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), + _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), + _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), + _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), + _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), + _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + + V3, + V4, + } + + if let E1::V2 { .. } = (E1::V1 { f: true }) { + unreachable!() + } + if let E1::V1 { .. } = (E1::V1 { f: true }) { + } else { + unreachable!() + } + + if let E2::V1 { .. } = E2::V3:: { + unreachable!() + } + if let E2::V3 { .. } = E2::V3:: { + } else { + unreachable!() + } + + 0 +}; + +fn main() { + assert_eq!(OVERFLOW, 0); + assert_eq!(MORE_OVERFLOW, 0); +} diff --git a/src/test/ui/consts/miri_unleashed/enum_discriminants.stderr b/src/test/ui/consts/miri_unleashed/enum_discriminants.stderr new file mode 100644 index 0000000000..8ca81ad22b --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/enum_discriminants.stderr @@ -0,0 +1,72 @@ +warning: skipping const checks + --> $DIR/enum_discriminants.rs:23:13 + | +LL | let x = Foo::B; + | ^^^^^^ + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:25:9 + | +LL | Foo::B => 0, + | ^^^^^^ + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:88:28 + | +LL | if let E1::V2 { .. } = (E1::V1 { f: true }) { + | ^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:88:12 + | +LL | if let E1::V2 { .. } = (E1::V1 { f: true }) { + | ^^^^^^^^^^^^^ + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:108:5 + | +LL | assert_eq!(OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:108:5 + | +LL | assert_eq!(OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:108:5 + | +LL | assert_eq!(OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:109:5 + | +LL | assert_eq!(MORE_OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:109:5 + | +LL | assert_eq!(MORE_OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/enum_discriminants.rs:109:5 + | +LL | assert_eq!(MORE_OVERFLOW, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs index 5fb9253550..8b17f6885a 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs @@ -14,8 +14,9 @@ trait Bar> { impl Foo for () { const X: u32 = 42; } + impl Foo> for String { - const X: Vec = Vec::new(); //~ ERROR not yet stable as a const fn + const X: Vec = Vec::new(); } impl Bar for () {} diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index c56ebf60df..5bc7b70638 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -4,13 +4,5 @@ error[E0493]: destructors cannot be evaluated at compile-time LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ constants cannot evaluate destructors -error: `std::vec::Vec::::new` is not yet stable as a const fn - --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25 - | -LL | const X: Vec = Vec::new(); - | ^^^^^^^^^^ - | - = help: add `#![feature(const_vec_new)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs new file mode 100644 index 0000000000..b476e04529 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs @@ -0,0 +1,20 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +#![feature(const_raw_ptr_deref)] +#![deny(const_err)] + +use std::cell::UnsafeCell; + +// make sure we do not just intern this as mutable +const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + +const MUTATING_BEHIND_RAW: () = { + // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. + unsafe { + *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks + //~^ ERROR any use of this value will cause an error + //~^^ tried to modify constant memory + } +}; + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr new file mode 100644 index 0000000000..507d4823a1 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr @@ -0,0 +1,27 @@ +warning: skipping const checks + --> $DIR/mutable_const.rs:14:9 + | +LL | *MUTABLE_BEHIND_RAW = 99 + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: any use of this value will cause an error + --> $DIR/mutable_const.rs:14:9 + | +LL | / const MUTATING_BEHIND_RAW: () = { +LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. +LL | | unsafe { +LL | | *MUTABLE_BEHIND_RAW = 99 + | | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory +... | +LL | | } +LL | | }; + | |__- + | +note: lint level defined here + --> $DIR/mutable_const.rs:4:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr index 82569e2601..28cf3537d6 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr @@ -6,7 +6,7 @@ LL | *MUH.x.get() = 99; thread 'rustc' panicked at 'assertion failed: `(left != right)` left: `Const`, - right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC + right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic diff --git a/src/test/ui/consts/packed_pattern.stderr b/src/test/ui/consts/packed_pattern.stderr new file mode 100644 index 0000000000..9b7daf2e67 --- /dev/null +++ b/src/test/ui/consts/packed_pattern.stderr @@ -0,0 +1,8 @@ +warning: unreachable pattern + --> $DIR/packed_pattern.rs:16:9 + | +LL | FOO => unreachable!(), + | ^^^ + | + = note: `#[warn(unreachable_patterns)]` on by default + diff --git a/src/test/ui/consts/packed_pattern2.stderr b/src/test/ui/consts/packed_pattern2.stderr new file mode 100644 index 0000000000..6cc0225d30 --- /dev/null +++ b/src/test/ui/consts/packed_pattern2.stderr @@ -0,0 +1,8 @@ +warning: unreachable pattern + --> $DIR/packed_pattern2.rs:24:9 + | +LL | FOO => unreachable!(), + | ^^^ + | + = note: `#[warn(unreachable_patterns)]` on by default + diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.stderr index 74a8f3daf6..26b7a24ebf 100644 --- a/src/test/ui/consts/std/alloc.stderr +++ b/src/test/ui/consts/std/alloc.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/too_generic_eval_ice.rs b/src/test/ui/consts/too_generic_eval_ice.rs new file mode 100644 index 0000000000..7a299169bc --- /dev/null +++ b/src/test/ui/consts/too_generic_eval_ice.rs @@ -0,0 +1,13 @@ +pub struct Foo(A, B); + +impl Foo { + const HOST_SIZE: usize = std::mem::size_of::(); + + pub fn crash() -> bool { + [5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE` + //~^ the size for values of type `A` cannot be known + //~| the size for values of type `B` cannot be known + } +} + +fn main() {} diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr new file mode 100644 index 0000000000..0733a51233 --- /dev/null +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -0,0 +1,43 @@ +error[E0599]: no associated item named `HOST_SIZE` found for type `Foo` in the current scope + --> $DIR/too_generic_eval_ice.rs:7:19 + | +LL | pub struct Foo(A, B); + | --------------------------- associated item `HOST_SIZE` not found for this +... +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^ associated item not found in `Foo` + | + = note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied: + `A : std::marker::Sized` + `B : std::marker::Sized` + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/too_generic_eval_ice.rs:7:13 + | +LL | pub struct Foo(A, B); + | --------------------------- required by `Foo` +... +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `A` + = note: to learn more, visit + = help: consider adding a `where A: std::marker::Sized` bound + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/too_generic_eval_ice.rs:7:13 + | +LL | pub struct Foo(A, B); + | --------------------------- required by `Foo` +... +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `B` + = note: to learn more, visit + = help: consider adding a `where B: std::marker::Sized` bound + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 7a7d816873..c4c7a33718 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/zst_no_llvm_alloc.rs b/src/test/ui/consts/zst_no_llvm_alloc.rs new file mode 100644 index 0000000000..5d77935540 --- /dev/null +++ b/src/test/ui/consts/zst_no_llvm_alloc.rs @@ -0,0 +1,19 @@ +// run-pass + +#[repr(align(4))] +struct Foo; + +static FOO: Foo = Foo; + +fn main() { + let x: &'static () = &(); + assert_eq!(x as *const () as usize, 1); + let x: &'static Foo = &Foo; + assert_eq!(x as *const Foo as usize, 4); + + // statics must have a unique address + assert_ne!(&FOO as *const Foo as usize, 4); + + assert_eq!(>::new().as_ptr(), <&[i32]>::default().as_ptr()); + assert_eq!(>::default().as_ptr(), (&[]).as_ptr()); +} diff --git a/src/test/ui/continue-after-missing-main.nll.stderr b/src/test/ui/continue-after-missing-main.nll.stderr index aceabf3316..b94c365f25 100644 --- a/src/test/ui/continue-after-missing-main.nll.stderr +++ b/src/test/ui/continue-after-missing-main.nll.stderr @@ -1,6 +1,14 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` + --> $DIR/continue-after-missing-main.rs:1:1 | - = note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs` +LL | / #![allow(dead_code)] +LL | | +LL | | // error-pattern:`main` function not found in crate +LL | | +... | +LL | | +LL | | } + | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` error: aborting due to previous error diff --git a/src/test/ui/continue-after-missing-main.stderr b/src/test/ui/continue-after-missing-main.stderr index cc5f876590..d764e7d860 100644 --- a/src/test/ui/continue-after-missing-main.stderr +++ b/src/test/ui/continue-after-missing-main.stderr @@ -1,6 +1,14 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` + --> $DIR/continue-after-missing-main.rs:1:1 | - = note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs` +LL | / #![allow(dead_code)] +LL | | +LL | | // error-pattern:`main` function not found in crate +LL | | +... | +LL | | +LL | | } + | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` error[E0623]: lifetime mismatch --> $DIR/continue-after-missing-main.rs:30:56 diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index cceb9e328b..054bd0914d 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -5,7 +5,7 @@ LL | struct Foo { | ---------- method `clone` not found for this ... LL | let _y = x.clone(); - | ^^^^^ + | ^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/custom_attribute.rs b/src/test/ui/custom_attribute.rs index 13c873c3b7..4957184229 100644 --- a/src/test/ui/custom_attribute.rs +++ b/src/test/ui/custom_attribute.rs @@ -1,9 +1,9 @@ #![feature(stmt_expr_attributes)] -#[foo] //~ ERROR cannot find attribute macro `foo` in this scope +#[foo] //~ ERROR cannot find attribute `foo` in this scope fn main() { - #[foo] //~ ERROR cannot find attribute macro `foo` in this scope + #[foo] //~ ERROR cannot find attribute `foo` in this scope let x = (); - #[foo] //~ ERROR cannot find attribute macro `foo` in this scope + #[foo] //~ ERROR cannot find attribute `foo` in this scope x } diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr index b4f9f3f49b..4023892d29 100644 --- a/src/test/ui/custom_attribute.stderr +++ b/src/test/ui/custom_attribute.stderr @@ -1,16 +1,16 @@ -error: cannot find attribute macro `foo` in this scope +error: cannot find attribute `foo` in this scope --> $DIR/custom_attribute.rs:3:3 | LL | #[foo] | ^^^ -error: cannot find attribute macro `foo` in this scope +error: cannot find attribute `foo` in this scope --> $DIR/custom_attribute.rs:5:7 | LL | #[foo] | ^^^ -error: cannot find attribute macro `foo` in this scope +error: cannot find attribute `foo` in this scope --> $DIR/custom_attribute.rs:7:7 | LL | #[foo] diff --git a/src/test/ui/dead-code-ret.stderr b/src/test/ui/dead-code-ret.stderr index 092a176f44..8384113159 100644 --- a/src/test/ui/dead-code-ret.stderr +++ b/src/test/ui/dead-code-ret.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/dead-code-ret.rs:7:5 | +LL | return; + | ------ any code following this expression is unreachable LL | println!("Paul is dead"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/dead-code-ret.rs:3:9 diff --git a/src/test/ui/defaulted-never-note.rs b/src/test/ui/defaulted-never-note.rs index cf1922ecc7..d3fb8a0941 100644 --- a/src/test/ui/defaulted-never-note.rs +++ b/src/test/ui/defaulted-never-note.rs @@ -19,7 +19,8 @@ trait ImplementedForUnitButNotNever {} impl ImplementedForUnitButNotNever for () {} fn foo(_t: T) {} -//~^ NOTE required by `foo` +//~^ NOTE required by this bound in `foo` +//~| NOTE fn smeg() { let _x = return; diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/defaulted-never-note.stderr index 45174c3229..28c9da059e 100644 --- a/src/test/ui/defaulted-never-note.stderr +++ b/src/test/ui/defaulted-never-note.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied - --> $DIR/defaulted-never-note.rs:26:5 + --> $DIR/defaulted-never-note.rs:27:5 | +LL | fn foo(_t: T) {} + | --- ----------------------------- required by this bound in `foo` +... LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | = note: the trait is implemented for `()`. Possibly this error has been caused by changes to Rust's type-inference algorithm (see: https://github.com/rust-lang/rust/issues/48950 for more info). Consider whether you meant to use the type `()` here instead. -note: required by `foo` - --> $DIR/defaulted-never-note.rs:21:1 - | -LL | fn foo(_t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs index c4f9fdce74..464ddcc4cd 100644 --- a/src/test/ui/deprecation/deprecation-in-future.rs +++ b/src/test/ui/deprecation/deprecation-in-future.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![deny(deprecated_in_future)] diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs index 2c4d64e4e6..010464adf5 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.rs +++ b/src/test/ui/derive-uninhabited-enum-38885.rs @@ -5,12 +5,15 @@ // when deriving Debug on an empty enum #[derive(Debug)] -enum Void {} //~ WARN never used +enum Void {} #[derive(Debug)] -enum Foo { //~ WARN never used +enum Foo { Bar(u8), - Void(Void), + Void(Void), //~ WARN never used } -fn main() {} +fn main() { + let x = Foo::Bar(42); + println!("{:?}", x); +} diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 941c98b550..a3ed6798a7 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -1,14 +1,8 @@ -warning: enum is never used: `Void` - --> $DIR/derive-uninhabited-enum-38885.rs:8:1 +warning: variant is never constructed: `Void` + --> $DIR/derive-uninhabited-enum-38885.rs:13:5 | -LL | enum Void {} - | ^^^^^^^^^ +LL | Void(Void), + | ^^^^^^^^^^ | = note: `-W dead-code` implied by `-W unused` -warning: enum is never used: `Foo` - --> $DIR/derive-uninhabited-enum-38885.rs:11:1 - | -LL | enum Foo { - | ^^^^^^^^ - diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index b9e175e43d..038de80508 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,7 +5,7 @@ LL | struct Bar { | ------------------ method `clone` not found for this ... LL | Bar:: { x: 1 }.clone(); - | ^^^^^ + | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: `Bar : std::clone::Clone` diff --git a/src/test/ui/derives/derive-hygiene.rs b/src/test/ui/derives/derive-hygiene.rs new file mode 100644 index 0000000000..4fa83c4903 --- /dev/null +++ b/src/test/ui/derives/derive-hygiene.rs @@ -0,0 +1,121 @@ +// Make sure that built-in derives don't rely on the user not declaring certain +// names to work properly. + +// check-pass + +#![allow(nonstandard_style)] +#![feature(decl_macro)] + +use std::prelude::v1::test as inline; + +static f: () = (); +static cmp: () = (); +static other: () = (); +static state: () = (); +static __self_0_0: () = (); +static __self_1_0: () = (); +static __self_vi: () = (); +static __arg_1_0: () = (); +static debug_trait_builder: () = (); + +struct isize; +trait i16 {} + +trait MethodsInDerives: Sized { + fn debug_tuple(self) {} + fn debug_struct(self) {} + fn field(self) {} + fn finish(self) {} + fn clone(self) {} + fn cmp(self) {} + fn partial_cmp(self) {} + fn eq(self) {} + fn ne(self) {} + fn le(self) {} + fn lt(self) {} + fn ge(self) {} + fn gt(self) {} + fn hash(self) {} +} + +trait GenericAny {} +impl GenericAny for S {} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum __H { V(i32), } + +#[repr(i16)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum W { A, B } + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct X>> { + A: A, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct Y(B) +where + B: From; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum Z { + C(C), + B { C: C }, +} + +// Make sure that we aren't using `self::` in paths, since it doesn't work in +// non-module scopes. +const NON_MODULE: () = { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X self::X> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y(B) + where + B: From; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z { + C(C), + B { C: C }, + } +}; + +macro m() { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X>> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y(B) + where + B: From; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z { + C(C), + B { C: C }, + } +} + +m!(); + +fn main() {} diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs index 3018a7b6d0..ed87360a0b 100644 --- a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs +++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr index 417c720c63..708ebca9fb 100644 --- a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -1,10 +1,13 @@ error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied - --> $DIR/derives-span-Hash-enum-struct-variant.rs:9:6 + --> $DIR/derives-span-Hash-enum-struct-variant.rs:11:6 | LL | x: Error | ^^^^^^^^ the trait `std::hash::Hash` is not implemented for `Error` + | + ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL | - = note: required by `std::hash::Hash::hash` +LL | fn hash(&self, state: &mut H); + | - required by this bound in `std::hash::Hash::hash` error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-enum.rs b/src/test/ui/derives/derives-span-Hash-enum.rs index bb656e5c2f..5b3649c982 100644 --- a/src/test/ui/derives/derives-span-Hash-enum.rs +++ b/src/test/ui/derives/derives-span-Hash-enum.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' diff --git a/src/test/ui/derives/derives-span-Hash-enum.stderr b/src/test/ui/derives/derives-span-Hash-enum.stderr index 25be879488..dc171cbe5d 100644 --- a/src/test/ui/derives/derives-span-Hash-enum.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum.stderr @@ -1,10 +1,13 @@ error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied - --> $DIR/derives-span-Hash-enum.rs:9:6 + --> $DIR/derives-span-Hash-enum.rs:11:6 | LL | Error | ^^^^^ the trait `std::hash::Hash` is not implemented for `Error` + | + ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL | - = note: required by `std::hash::Hash::hash` +LL | fn hash(&self, state: &mut H); + | - required by this bound in `std::hash::Hash::hash` error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-struct.rs b/src/test/ui/derives/derives-span-Hash-struct.rs index fa5e2af6be..ead70861a0 100644 --- a/src/test/ui/derives/derives-span-Hash-struct.rs +++ b/src/test/ui/derives/derives-span-Hash-struct.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' diff --git a/src/test/ui/derives/derives-span-Hash-struct.stderr b/src/test/ui/derives/derives-span-Hash-struct.stderr index c0574453a7..429449b82b 100644 --- a/src/test/ui/derives/derives-span-Hash-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-struct.stderr @@ -1,10 +1,13 @@ error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied - --> $DIR/derives-span-Hash-struct.rs:8:5 + --> $DIR/derives-span-Hash-struct.rs:10:5 | LL | x: Error | ^^^^^^^^ the trait `std::hash::Hash` is not implemented for `Error` + | + ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL | - = note: required by `std::hash::Hash::hash` +LL | fn hash(&self, state: &mut H); + | - required by this bound in `std::hash::Hash::hash` error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.rs b/src/test/ui/derives/derives-span-Hash-tuple-struct.rs index 3822bce146..820f13ed18 100644 --- a/src/test/ui/derives/derives-span-Hash-tuple-struct.rs +++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr index 6339c38578..a6c4c479b2 100644 --- a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -1,10 +1,13 @@ error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied - --> $DIR/derives-span-Hash-tuple-struct.rs:8:5 + --> $DIR/derives-span-Hash-tuple-struct.rs:10:5 | LL | Error | ^^^^^ the trait `std::hash::Hash` is not implemented for `Error` + | + ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL | - = note: required by `std::hash::Hash::hash` +LL | fn hash(&self, state: &mut H); + | - required by this bound in `std::hash::Hash::hash` error: aborting due to previous error diff --git a/src/test/ui/derives/deriving-bounds.stderr b/src/test/ui/derives/deriving-bounds.stderr index 99976da72d..b18df35118 100644 --- a/src/test/ui/derives/deriving-bounds.stderr +++ b/src/test/ui/derives/deriving-bounds.stderr @@ -1,15 +1,3 @@ -error: cannot find derive macro `Send` in this scope - --> $DIR/deriving-bounds.rs:1:10 - | -LL | #[derive(Send)] - | ^^^^ - | -note: unsafe traits like `Send` should be implemented explicitly - --> $DIR/deriving-bounds.rs:1:10 - | -LL | #[derive(Send)] - | ^^^^ - error: cannot find derive macro `Sync` in this scope --> $DIR/deriving-bounds.rs:5:10 | @@ -22,5 +10,17 @@ note: unsafe traits like `Sync` should be implemented explicitly LL | #[derive(Sync)] | ^^^^ +error: cannot find derive macro `Send` in this scope + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + | +note: unsafe traits like `Send` should be implemented explicitly + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index e6060c269e..4cca14ae08 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -1,41 +1,35 @@ error[E0277]: the trait bound `C: std::marker::Copy` is not satisfied - --> $DIR/deriving-copyclone.rs:31:5 + --> $DIR/deriving-copyclone.rs:31:13 | +LL | fn is_copy(_: T) {} + | ------- ---- required by this bound in `is_copy` +... LL | is_copy(B { a: 1, b: C }); - | ^^^^^^^ the trait `std::marker::Copy` is not implemented for `C` + | ^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `C` | = note: required because of the requirements on the impl of `std::marker::Copy` for `B` -note: required by `is_copy` - --> $DIR/deriving-copyclone.rs:18:1 - | -LL | fn is_copy(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: std::clone::Clone` is not satisfied - --> $DIR/deriving-copyclone.rs:32:5 + --> $DIR/deriving-copyclone.rs:32:14 | +LL | fn is_clone(_: T) {} + | -------- ----- required by this bound in `is_clone` +... LL | is_clone(B { a: 1, b: C }); - | ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `C` + | ^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `C` | = note: required because of the requirements on the impl of `std::clone::Clone` for `B` -note: required by `is_clone` - --> $DIR/deriving-copyclone.rs:19:1 - | -LL | fn is_clone(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `D: std::marker::Copy` is not satisfied - --> $DIR/deriving-copyclone.rs:35:5 + --> $DIR/deriving-copyclone.rs:35:13 | +LL | fn is_copy(_: T) {} + | ------- ---- required by this bound in `is_copy` +... LL | is_copy(B { a: 1, b: D }); - | ^^^^^^^ the trait `std::marker::Copy` is not implemented for `D` + | ^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `D` | = note: required because of the requirements on the impl of `std::marker::Copy` for `B` -note: required by `is_copy` - --> $DIR/deriving-copyclone.rs:18:1 - | -LL | fn is_copy(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index cfb1da037d..1bd4543f23 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `i8: Foo` is not satisfied - --> $DIR/issue-39802-show-5-trait-impls.rs:24:5 + --> $DIR/issue-39802-show-5-trait-impls.rs:24:21 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&1i8); - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i8` + | ^^^^ the trait `Foo` is not implemented for `i8` | = help: the following implementations were found: > @@ -10,34 +13,30 @@ LL | Foo::::bar(&1i8); > > > -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Foo` is not satisfied - --> $DIR/issue-39802-show-5-trait-impls.rs:25:5 + --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&1u8); - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u8` + | ^^^^ the trait `Foo` is not implemented for `u8` | = help: the following implementations were found: > > > > -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `bool: Foo` is not satisfied - --> $DIR/issue-39802-show-5-trait-impls.rs:26:5 + --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&true); - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `bool` + | ^^^^^ the trait `Foo` is not implemented for `bool` | = help: the following implementations were found: > @@ -45,11 +44,6 @@ LL | Foo::::bar(&true); > > and 2 others -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 87e48cd1e1..5b384045a4 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -61,8 +61,9 @@ error[E0038]: the trait `X` cannot be made into an object | LL | impl dyn X { | ^^^^^ the trait `X` cannot be made into an object - | - = note: method `xxx` has no receiver +... +LL | fn xxx() { ### } + | --- associated function `xxx` has no `self` parameter error: aborting due to 9 previous errors diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 63eec50c2d..6902779f33 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,27 +1,16 @@ fn foo() { (0..13).collect>(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` } fn bar() { Vec::new(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR cannot find function `new` in the crate root } fn qux() { (0..13).collect(); //~^ ERROR chained comparison - //~| ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` - //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index fe517ee349..7a08fda27e 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -8,7 +8,7 @@ LL | (0..13).collect>(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:10:8 + --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); | ^^^^^^^ @@ -17,7 +17,7 @@ LL | Vec::new(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:20 + --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); | ^^^^^^^^ @@ -25,79 +25,5 @@ LL | (0..13).collect(); = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:24 - | -LL | (0..13).collect(); - | ^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:2:21 - | -LL | (0..13).collect>(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:2:25 - | -LL | (0..13).collect>(); - | ^^^ not a value - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:10:5 - | -LL | Vec::new(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:10:9 - | -LL | Vec::new(); - | ^^^ not a value - -error[E0425]: cannot find function `new` in the crate root - --> $DIR/issue-40396.rs:10:15 - | -LL | Vec::new(); - | ^^^ not found in the crate root - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:18:21 - | -LL | (0..13).collect(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:18:25 - | -LL | (0..13).collect(); - | ^^^ not a value - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:2:13 - | -LL | (0..13).collect>(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:18:13 - | -LL | (0..13).collect(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0308]: mismatched types - --> $DIR/issue-40396.rs:18:29 - | -LL | (0..13).collect(); - | ^^ expected bool, found () - | - = note: expected type `bool` - found type `()` - -error: aborting due to 14 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0423, E0425, E0615. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index f1c93d5463..f5edbe2a3a 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -28,7 +28,10 @@ error: expected `{`, found `;` LL | if not // lack of braces is [sic] | -- this `if` statement has a condition, but no block LL | println!("Then when?"); - | ^ expected `{` + | ^ + | | + | expected `{` + | help: try placing this code inside a block: `{ ; }` error: unexpected `2` after identifier --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.rs b/src/test/ui/did_you_mean/multiple-pattern-typo.rs deleted file mode 100644 index 14ad33d53b..0000000000 --- a/src/test/ui/did_you_mean/multiple-pattern-typo.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - let x = 3; - match x { - 1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern - _ => (), - } -} diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.stderr b/src/test/ui/did_you_mean/multiple-pattern-typo.stderr deleted file mode 100644 index a29fa584b2..0000000000 --- a/src/test/ui/did_you_mean/multiple-pattern-typo.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected token `||` after pattern - --> $DIR/multiple-pattern-typo.rs:4:15 - | -LL | 1 | 2 || 3 => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` - -error: aborting due to previous error - diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index a646d98324..b05b92bf1e 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -1,6 +1,9 @@ error[E0275]: overflow evaluating the requirement `J: std::marker::Send` --> $DIR/recursion_limit.rs:34:5 | +LL | fn is_send() { } + | ------- ---- required by this bound in `is_send` +... LL | is_send::(); | ^^^^^^^^^^^^ | @@ -14,11 +17,6 @@ LL | is_send::(); = note: required because it appears within the type `C` = note: required because it appears within the type `B` = note: required because it appears within the type `A` -note: required by `is_send` - --> $DIR/recursion_limit.rs:31:1 - | -LL | fn is_send() { } - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs index a4f4c2666a..fb13fd764b 100644 --- a/src/test/ui/drop/dropck_legal_cycles.rs +++ b/src/test/ui/drop/dropck_legal_cycles.rs @@ -143,7 +143,7 @@ pub fn main() { v[0].descend_into_self(&mut c); assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 1: { v[0] -> v[1], v[1] -> v[0] }; // does not exercise `v` itself @@ -158,7 +158,7 @@ pub fn main() { v[0].descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 2: { v[0] -> v, v[1] -> v } let v: V = Named::new("v"); @@ -171,7 +171,7 @@ pub fn main() { v.descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 3: { hk0 -> hv0, hv0 -> hk0, hk1 -> hv1, hv1 -> hk1 }; // does not exercise `h` itself @@ -193,7 +193,7 @@ pub fn main() { assert!(c.saw_prev_marked); } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 4: { h -> (hmk0,hmv0,hmk1,hmv1), {hmk0,hmv0,hmk1,hmv1} -> h } @@ -216,7 +216,7 @@ pub fn main() { // break; } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 5: { vd[0] -> vd[1], vd[1] -> vd[0] }; // does not exercise vd itself @@ -232,7 +232,7 @@ pub fn main() { vd[0].descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 6: { vd -> (vd0, vd1), {vd0, vd1} -> vd } let mut vd: VecDeque = VecDeque::new(); @@ -247,7 +247,7 @@ pub fn main() { vd[0].descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 7: { vm -> (vm0, vm1), {vm0, vm1} -> vm } let mut vm: HashMap = HashMap::new(); @@ -262,7 +262,7 @@ pub fn main() { vm[&0].descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 8: { ll -> (ll0, ll1), {ll0, ll1} -> ll } let mut ll: LinkedList = LinkedList::new(); @@ -282,7 +282,7 @@ pub fn main() { // break; } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 9: { bh -> (bh0, bh1), {bh0, bh1} -> bh } let mut bh: BinaryHeap = BinaryHeap::new(); @@ -302,7 +302,7 @@ pub fn main() { // break; } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 10: { btm -> (btk0, btv1), {bt0, bt1} -> btm } let mut btm: BTreeMap = BTreeMap::new(); @@ -323,7 +323,7 @@ pub fn main() { // break; } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 10: { bts -> (bts0, bts1), {bts0, bts1} -> btm } let mut bts: BTreeSet = BTreeSet::new(); @@ -343,7 +343,7 @@ pub fn main() { // break; } - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 } let (rc0, rc1, rc2): (RCRC, RCRC, RCRC); @@ -361,7 +361,7 @@ pub fn main() { rc0.descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // We want to take the previous Rc case and generalize it to Arc. // @@ -395,7 +395,7 @@ pub fn main() { arc0.descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW); @@ -413,7 +413,7 @@ pub fn main() { arc0.descend_into_self(&mut c); assert!(c.saw_prev_marked); - if PRINT { println!(""); } + if PRINT { println!(); } // Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs let (arc0, arc1, arc2): (ARCM, ARCM, ARCM); diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index f3f5c38227..91063edf0f 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,10 +7,8 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default -#![allow(unused_assignments)] -#![allow(unused_variables)] #![feature(slice_patterns)] -#![feature(async_await)] +#![allow(unused)] use std::{ cell::{Cell, RefCell}, diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr index dbcb0fcebb..5e93a02342 100644 --- a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr @@ -8,7 +8,9 @@ LL | } | - | | | `o2` dropped here while still borrowed - | borrow might be used here, when `o2` is dropped and runs the destructor for type `std::boxed::Box>` + | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box>` + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 @@ -20,7 +22,9 @@ LL | } | - | | | `o3` dropped here while still borrowed - | borrow might be used here, when `o3` is dropped and runs the destructor for type `std::boxed::Box>` + | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box>` + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:113:13 @@ -38,7 +42,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough @@ -62,7 +66,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr index 1e779208e5..dc3fbed593 100644 --- a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr @@ -2,7 +2,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:111:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` LL | o1.set0(&o2); | ^^^ borrowed value does not live long enough ... @@ -13,7 +13,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` LL | o1.set0(&o2); LL | o1.set1(&o3); | ^^^ borrowed value does not live long enough @@ -37,7 +37,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough @@ -49,7 +49,7 @@ error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o1` is borrowed for `'static` + | -------- cast requires that `o1` is borrowed for `'static` ... LL | o3.set0(&o1); | ^^^ borrowed value does not live long enough @@ -61,7 +61,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr index 8606479ff6..6754574f0b 100644 --- a/src/test/ui/duplicate/duplicate-type-parameter.stderr +++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:1:12 | LL | type Foo = Option; @@ -6,7 +6,7 @@ LL | type Foo = Option; | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:4:14 | LL | struct Bar(T); @@ -14,7 +14,7 @@ LL | struct Bar(T); | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:7:14 | LL | struct Baz { @@ -22,7 +22,7 @@ LL | struct Baz { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:12:12 | LL | enum Boo { @@ -30,7 +30,7 @@ LL | enum Boo { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:18:11 | LL | fn quux(x: T) {} @@ -38,7 +38,7 @@ LL | fn quux(x: T) {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:21:13 | LL | trait Qux {} @@ -46,7 +46,7 @@ LL | trait Qux {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:24:8 | LL | impl Qux for Option {} diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs index 2684c8e00b..9f34a3887b 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs @@ -5,7 +5,7 @@ extern crate edition_kw_macro_2018; mod one_async { - produces_async! {} //~ ERROR expected identifier, found reserved keyword + produces_async! {} //~ ERROR expected identifier, found keyword } mod two_async { produces_async_raw! {} // OK diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index 321545740c..04a70cf983 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5 | LL | produces_async! {} - | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword + | ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs index fb8e0cdb4c..dbc0465b08 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -5,7 +5,7 @@ extern crate edition_kw_macro_2015; pub fn check_async() { - let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` + let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK r#async = consumes_async!(async); // OK @@ -15,6 +15,6 @@ pub fn check_async() { if passes_ident!(async) == 1 {} if passes_ident!(r#async) == 1 {} // OK - module::async(); //~ ERROR expected identifier, found reserved keyword `async` + module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK } diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index 3c4a153353..be991cd0c8 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -1,18 +1,18 @@ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 | LL | let mut async = 1; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | let mut r#async = 1; | ^^^^^^^ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 | LL | module::async(); - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | module::r#async(); diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs index 6f766550d4..a8e69fed69 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs @@ -5,7 +5,7 @@ extern crate edition_kw_macro_2018; mod one_async { - produces_async! {} //~ ERROR expected identifier, found reserved keyword `async` + produces_async! {} //~ ERROR expected identifier, found keyword `async` } mod two_async { produces_async_raw! {} // OK diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index 8942e3ce43..fb12051eed 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5 | LL | produces_async! {} - | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword + | ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs index 88cebf45ad..5aca0839f0 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -5,7 +5,7 @@ extern crate edition_kw_macro_2018; pub fn check_async() { - let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` + let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK r#async = consumes_async!(async); // OK @@ -15,6 +15,6 @@ pub fn check_async() { if passes_ident!(async) == 1 {} if passes_ident!(r#async) == 1 {} // OK - module::async(); //~ ERROR expected identifier, found reserved keyword `async` + module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK } diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 46aa9ca34e..93a7627f88 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -1,18 +1,18 @@ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 | LL | let mut async = 1; - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | let mut r#async = 1; | ^^^^^^^ -error: expected identifier, found reserved keyword `async` +error: expected identifier, found keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 | LL | module::async(); - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | module::r#async(); diff --git a/src/test/ui/elided-test.stderr b/src/test/ui/elided-test.stderr index d22eee4e8b..175bd03306 100644 --- a/src/test/ui/elided-test.stderr +++ b/src/test/ui/elided-test.stderr @@ -1,6 +1,10 @@ error[E0601]: `main` function not found in crate `elided_test` + --> $DIR/elided-test.rs:5:1 | - = note: consider adding a `main` function to `$DIR/elided-test.rs` +LL | / #[test] +LL | | fn main() { +LL | | } + | |_^ consider adding a `main` function to `$DIR/elided-test.rs` error: aborting due to previous error diff --git a/src/test/ui/empty/empty-macro-use.stderr b/src/test/ui/empty/empty-macro-use.stderr index 16300411c8..8e3e06896e 100644 --- a/src/test/ui/empty/empty-macro-use.stderr +++ b/src/test/ui/empty/empty-macro-use.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `macro_two!` in this scope +error: cannot find macro `macro_two` in this scope --> $DIR/empty-macro-use.rs:7:5 | LL | macro_two!(); diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs index ffd2545b29..f0ecea42f3 100644 --- a/src/test/ui/empty/empty-never-array.rs +++ b/src/test/ui/empty/empty-never-array.rs @@ -10,7 +10,7 @@ fn transmute(t: T) -> U { let Helper::U(u) = Helper::T(t, []); //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered u - //~^ ERROR use of possibly uninitialized variable: `u` + //~^ ERROR use of possibly-uninitialized variable: `u` } fn main() { diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 01ee1c3a4d..7d59d553d8 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -3,6 +3,7 @@ error[E0005]: refutable pattern in local binding: `T(_, _)` not covered | LL | / enum Helper { LL | | T(T, [!; 0]), + | | - not covered LL | | #[allow(dead_code)] LL | | U(U), LL | | } @@ -11,11 +12,11 @@ LL | | } LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered -error[E0381]: use of possibly uninitialized variable: `u` +error[E0381]: use of possibly-uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 | LL | u - | ^ use of possibly uninitialized `u` + | ^ use of possibly-uninitialized `u` error: aborting due to 2 previous errors diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 777b9d4a4a..6c15e7bf28 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -20,15 +20,16 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `E:: --> $DIR/empty-struct-tuple-pat.rs:29:9 | LL | E::Empty4 => () - | ^^^^^^^^^ not a unit struct/variant or constant + | ^^^^^^^^^ did you mean `E::Empty4 ( /* fields */ )`? error[E0532]: expected unit struct/variant or constant, found tuple variant `XE::XEmpty5` --> $DIR/empty-struct-tuple-pat.rs:33:9 | LL | XE::XEmpty5 => (), | ^^^^------- - | | - | help: a unit variant with a similar name exists: `XEmpty4` + | | | + | | help: a unit variant with a similar name exists: `XEmpty4` + | did you mean `XE::XEmpty5 ( /* fields */ )`? error: aborting due to 4 previous errors diff --git a/src/test/ui/error-codes/E0008.rs b/src/test/ui/error-codes/E0008.rs deleted file mode 100644 index c87ef4cb85..0000000000 --- a/src/test/ui/error-codes/E0008.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, - //~^ ERROR E0008 - _ => {}, - } -} diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr deleted file mode 100644 index 6b45439c4b..0000000000 --- a/src/test/ui/error-codes/E0008.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/E0008.rs:3:14 - | -LL | Some(s) if s.len() == 0 => {}, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/error-codes/E0023.rs b/src/test/ui/error-codes/E0023.rs index 2a97e9048a..7ac22bb710 100644 --- a/src/test/ui/error-codes/E0023.rs +++ b/src/test/ui/error-codes/E0023.rs @@ -1,14 +1,17 @@ enum Fruit { Apple(String, String), Pear(u32), + Orange((String, String)), + Banana(()), } - fn main() { let x = Fruit::Apple(String::new(), String::new()); match x { Fruit::Apple(a) => {}, //~ ERROR E0023 Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 Fruit::Pear(1, 2) => {}, //~ ERROR E0023 + Fruit::Orange(a, b) => {}, //~ ERROR E0023 + Fruit::Banana() => {}, //~ ERROR E0023 } } diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 1bc90a995f..dbce6003a2 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -1,21 +1,56 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/E0023.rs:10:9 + --> $DIR/E0023.rs:11:9 | +LL | Apple(String, String), + | --------------------- tuple variant defined here +... LL | Fruit::Apple(a) => {}, | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields - --> $DIR/E0023.rs:11:9 + --> $DIR/E0023.rs:12:9 | +LL | Apple(String, String), + | --------------------- tuple variant defined here +... LL | Fruit::Apple(a, b, c) => {}, | ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field - --> $DIR/E0023.rs:12:9 + --> $DIR/E0023.rs:13:9 | +LL | Pear(u32), + | --------- tuple variant defined here +... LL | Fruit::Pear(1, 2) => {}, | ^^^^^^^^^^^^^^^^^ expected 1 field, found 2 -error: aborting due to 3 previous errors +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:14:9 + | +LL | Orange((String, String)), + | ------------------------ tuple variant defined here +... +LL | Fruit::Orange(a, b) => {}, + | ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2 +help: missing parenthesis + | +LL | Fruit::Orange((a, b)) => {}, + | ^ ^ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:15:9 + | +LL | Banana(()), + | ---------- tuple variant defined here +... +LL | Fruit::Banana() => {}, + | ^^^^^^^^^^^^^^^ expected 1 field, found 0 +help: missing parenthesis + | +LL | Fruit::Banana(()) => {}, + | ^ ^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 6a27b07fa8..1943965139 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -1,14 +1,13 @@ // compile-flags: -Z teach trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index fb630de7fc..80f3d4441b 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033-teach.rs:8:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: method `foo` has no receiver error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033-teach.rs:13:9 + --> $DIR/E0033-teach.rs:12:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index 582600e110..e5f0530f45 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -1,12 +1,11 @@ trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index fe9f45d86a..c2843796cc 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033.rs:6:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: method `foo` has no receiver error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033.rs:11:9 + --> $DIR/E0033.rs:10:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index e3d7593e42..5c4d6d53c4 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/E0038.rs:5:1 | +LL | fn foo(&self) -> Self; + | --- method `foo` references the `Self` type in its parameters or return type +... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs index a5265e7dc1..9eee9c31d3 100644 --- a/src/test/ui/error-codes/E0044.rs +++ b/src/test/ui/error-codes/E0044.rs @@ -1,7 +1,7 @@ extern { fn sqrt(f: T) -> T; //~^ ERROR foreign items may not have type parameters [E0044] - //~| HELP use specialization instead of type parameters by replacing them with concrete types + //~| HELP replace the type parameters with concrete types //~| NOTE can't have type parameters } diff --git a/src/test/ui/error-codes/E0044.stderr b/src/test/ui/error-codes/E0044.stderr index 57c21116b2..e889c167b9 100644 --- a/src/test/ui/error-codes/E0044.stderr +++ b/src/test/ui/error-codes/E0044.stderr @@ -4,7 +4,7 @@ error[E0044]: foreign items may not have type parameters LL | fn sqrt(f: T) -> T; | ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters | - = help: use specialization instead of type parameters by replacing them with concrete types like `u32` + = help: replace the type parameters with concrete types like `u32` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr index 745dccfb17..445053a4a8 100644 --- a/src/test/ui/error-codes/E0138.stderr +++ b/src/test/ui/error-codes/E0138.stderr @@ -1,4 +1,4 @@ -error[E0138]: multiple 'start' functions +error[E0138]: multiple `start` functions --> $DIR/E0138.rs:7:1 | LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs index 71eff0e746..8a43f38fcf 100644 --- a/src/test/ui/error-codes/E0194.rs +++ b/src/test/ui/error-codes/E0194.rs @@ -1,7 +1,7 @@ trait Foo { fn do_something(&self) -> T; fn do_something_else(&self, bar: T); - //~^ ERROR E0194 + //~^ ERROR E0403 } fn main() { diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr index ab4918a4e2..f2c908eea0 100644 --- a/src/test/ui/error-codes/E0194.stderr +++ b/src/test/ui/error-codes/E0194.stderr @@ -1,12 +1,12 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0194.rs:3:26 | LL | trait Foo { - | - first `T` declared here + | - first use of `T` LL | fn do_something(&self) -> T; LL | fn do_something_else(&self, bar: T); - | ^ shadows another type parameter + | ^ already used error: aborting due to previous error -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index a10f2c0057..bcbd3a91cb 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -1,11 +1,11 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/E0214.rs:2:15 + --> $DIR/E0214.rs:2:12 | LL | let v: Vec(&str) = vec!["foo"]; - | ^^^^^^ - | | - | only `Fn` traits may use parentheses - | help: use angle brackets instead: `<&str>` + | ^^^^^^^^^ + | | + | only `Fn` traits may use parentheses + | help: use angle brackets instead: `Vec<&str>` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0267.stderr b/src/test/ui/error-codes/E0267.stderr index b14cfd1a52..1f8657373e 100644 --- a/src/test/ui/error-codes/E0267.stderr +++ b/src/test/ui/error-codes/E0267.stderr @@ -2,7 +2,9 @@ error[E0267]: `break` inside of a closure --> $DIR/E0267.rs:2:18 | LL | let w = || { break; }; - | ^^^^^ cannot break inside of a closure + | -- ^^^^^ cannot `break` inside of a closure + | | + | enclosing closure error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr index 3c77e7f3df..c926f9e487 100644 --- a/src/test/ui/error-codes/E0268.stderr +++ b/src/test/ui/error-codes/E0268.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/E0268.rs:2:5 | LL | break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index 16c3ab9d74..c56853f45a 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -1,16 +1,14 @@ error[E0271]: type mismatch resolving `::AssociatedType == u32` --> $DIR/E0271.rs:10:5 | +LL | fn foo(t: T) where T: Trait { + | --- ------------------ required by this bound in `foo` +... LL | foo(3_i8); | ^^^ expected reference, found u32 | = note: expected type `&'static str` found type `u32` -note: required by `foo` - --> $DIR/E0271.rs:3:1 - | -LL | fn foo(t: T) where T: Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 40991cb229..f607a9fbbf 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -1,6 +1,9 @@ error[E0275]: overflow evaluating the requirement `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/E0275.rs:5:1 | +LL | trait Foo {} + | --------- required by `Foo` +... LL | impl Foo for T where Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -132,11 +135,6 @@ LL | impl Foo for T where Bar: Foo {} = note: required because of the requirements on the impl of `Foo` for `Bar>>` = note: required because of the requirements on the impl of `Foo` for `Bar>` = note: required because of the requirements on the impl of `Foo` for `Bar` -note: required by `Foo` - --> $DIR/E0275.rs:1:1 - | -LL | trait Foo {} - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr index a4db1c8b09..407e51e4f5 100644 --- a/src/test/ui/error-codes/E0277-2.stderr +++ b/src/test/ui/error-codes/E0277-2.stderr @@ -1,6 +1,9 @@ error[E0277]: `*const u8` cannot be sent between threads safely --> $DIR/E0277-2.rs:16:5 | +LL | fn is_send() { } + | ------- ---- required by this bound in `is_send` +... LL | is_send::(); | ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | @@ -8,11 +11,6 @@ LL | is_send::(); = note: required because it appears within the type `Baz` = note: required because it appears within the type `Bar` = note: required because it appears within the type `Foo` -note: required by `is_send` - --> $DIR/E0277-2.rs:13:1 - | -LL | fn is_send() { } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr index e5e416da88..a069d048c8 100644 --- a/src/test/ui/error-codes/E0277.stderr +++ b/src/test/ui/error-codes/E0277.stderr @@ -11,16 +11,13 @@ LL | fn f(p: Path) { } = help: unsized locals are gated as an unstable feature error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/E0277.rs:17:5 - | -LL | some_func(5i32); - | ^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `some_func` - --> $DIR/E0277.rs:9:1 + --> $DIR/E0277.rs:17:15 | LL | fn some_func(foo: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------- --- required by this bound in `some_func` +... +LL | some_func(5i32); + | ^^^^ the trait `Foo` is not implemented for `i32` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr index 3a5040eb6d..0f610a5e42 100644 --- a/src/test/ui/error-codes/E0282.stderr +++ b/src/test/ui/error-codes/E0282.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/E0282.rs:2:9 | LL | let x = "hello".chars().rev().collect(); - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index e1f53e592f..1d99f99c62 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: Generator` --> $DIR/E0283.rs:18:21 | +LL | fn create() -> u32; + | ------------------- required by `Generator::create` +... LL | let cont: u32 = Generator::create(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `Generator::create` - --> $DIR/E0283.rs:2:5 - | -LL | fn create() -> u32; - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0301.rs b/src/test/ui/error-codes/E0301.rs deleted file mode 100644 index 3b451801c9..0000000000 --- a/src/test/ui/error-codes/E0301.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - match Some(()) { - None => { }, - option if option.take().is_none() => {}, //~ ERROR E0301 - Some(_) => { } //~^ ERROR E0596 - } -} diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr deleted file mode 100644 index 4f12fd3850..0000000000 --- a/src/test/ui/error-codes/E0301.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0301]: cannot mutably borrow in a pattern guard - --> $DIR/E0301.rs:4:19 - | -LL | option if option.take().is_none() => {}, - | ^^^^^^ borrowed mutably in pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error[E0596]: cannot borrow `option` as mutable, as it is immutable for the pattern guard - --> $DIR/E0301.rs:4:19 - | -LL | option if option.take().is_none() => {}, - | ^^^^^^ cannot borrow as mutable - | - = note: variables bound in patterns are immutable until the end of the pattern guard - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0301, E0596. -For more information about an error, try `rustc --explain E0301`. diff --git a/src/test/ui/error-codes/E0302.rs b/src/test/ui/error-codes/E0302.rs deleted file mode 100644 index 69f5953deb..0000000000 --- a/src/test/ui/error-codes/E0302.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - match Some(()) { - None => { }, - option if { option = None; false } => { }, //~ ERROR E0302 - //~^ ERROR cannot assign to `option`, as it is immutable for the pattern guard - Some(_) => { } - } -} diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr deleted file mode 100644 index a077fcaea4..0000000000 --- a/src/test/ui/error-codes/E0302.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0302]: cannot assign in a pattern guard - --> $DIR/E0302.rs:4:21 - | -LL | option if { option = None; false } => { }, - | ^^^^^^^^^^^^^ assignment in pattern guard - -error[E0594]: cannot assign to `option`, as it is immutable for the pattern guard - --> $DIR/E0302.rs:4:21 - | -LL | option if { option = None; false } => { }, - | ^^^^^^^^^^^^^ cannot assign - | - = note: variables bound in patterns are immutable until the end of the pattern guard - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0302`. diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr index 2bd7de6c24..d76a58a7c8 100644 --- a/src/test/ui/error-codes/E0403.stderr +++ b/src/test/ui/error-codes/E0403.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0403.rs:1:11 | LL | fn foo(s: T, u: T) {} diff --git a/src/test/ui/error-codes/E0601.rs b/src/test/ui/error-codes/E0601.rs index 47feb7f836..4380ddeac0 100644 --- a/src/test/ui/error-codes/E0601.rs +++ b/src/test/ui/error-codes/E0601.rs @@ -1 +1 @@ -// Test for main function not found. +//~ ERROR `main` function not found diff --git a/src/test/ui/error-codes/E0601.stderr b/src/test/ui/error-codes/E0601.stderr index cbc20db35d..a687f57561 100644 --- a/src/test/ui/error-codes/E0601.stderr +++ b/src/test/ui/error-codes/E0601.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `E0601` + --> $DIR/E0601.rs:1:37 | - = note: consider adding a `main` function to `$DIR/E0601.rs` +LL | + | ^ consider adding a `main` function to `$DIR/E0601.rs` error: aborting due to previous error diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index 8808e95d81..73571a375b 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -24,7 +24,7 @@ error[E0599]: no method named `z` found for type `&str` in the current scope --> $DIR/error-festival.rs:16:7 | LL | x.z(); - | ^ + | ^ method not found in `&str` error[E0600]: cannot apply unary operator `!` to type `Question` --> $DIR/error-festival.rs:19:5 diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr index 7143f8c914..d0148f418e 100644 --- a/src/test/ui/error-should-say-copy-not-pod.stderr +++ b/src/test/ui/error-should-say-copy-not-pod.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied - --> $DIR/error-should-say-copy-not-pod.rs:6:5 - | -LL | check_bound("nocopy".to_string()); - | ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `check_bound` - --> $DIR/error-should-say-copy-not-pod.rs:3:1 + --> $DIR/error-should-say-copy-not-pod.rs:6:17 | LL | fn check_bound(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `check_bound` +... +LL | check_bound("nocopy".to_string()); + | ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs index 82c64bcf6a..9ab8e13893 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs @@ -6,11 +6,11 @@ struct Foo<'a,'b> { impl<'a,'b> Foo<'a,'b> { fn bar(self: Foo<'b,'a> - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index e6f9eded9a..4bf2d573d4 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> @@ -17,7 +17,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a,'b> Foo<'a,'b> { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> diff --git a/src/test/ui/ext-nonexistent.stderr b/src/test/ui/ext-nonexistent.stderr index 3fbbb49526..f3aa83fd50 100644 --- a/src/test/ui/ext-nonexistent.stderr +++ b/src/test/ui/ext-nonexistent.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `iamnotanextensionthatexists!` in this scope +error: cannot find macro `iamnotanextensionthatexists` in this scope --> $DIR/ext-nonexistent.rs:2:13 | LL | fn main() { iamnotanextensionthatexists!(""); } diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs index c3975f6b92..64c4107e89 100644 --- a/src/test/ui/extenv/issue-55897.rs +++ b/src/test/ui/extenv/issue-55897.rs @@ -1,7 +1,7 @@ use prelude::*; //~ ERROR unresolved import `prelude` mod unresolved_env { - use env; + use env; //~ ERROR unresolved import `env` include!(concat!(env!("NON_EXISTENT"), "/data.rs")); //~^ ERROR cannot determine resolution for the macro `env` diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr index 9d68131bea..c57a467cdb 100644 --- a/src/test/ui/extenv/issue-55897.stderr +++ b/src/test/ui/extenv/issue-55897.stderr @@ -19,6 +19,12 @@ LL | use prelude::*; | unresolved import | help: a similar path exists: `std::prelude` +error[E0432]: unresolved import `env` + --> $DIR/issue-55897.rs:4:9 + | +LL | use env; + | ^^^ no `env` in the root + error: cannot determine resolution for the macro `env` --> $DIR/issue-55897.rs:6:22 | @@ -27,6 +33,6 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | = note: import resolution is stuck, try simplifying macro imports -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/extern/extern-types-not-sync-send.stderr b/src/test/ui/extern/extern-types-not-sync-send.stderr index bc9d96df77..c395f3875e 100644 --- a/src/test/ui/extern/extern-types-not-sync-send.stderr +++ b/src/test/ui/extern/extern-types-not-sync-send.stderr @@ -1,28 +1,24 @@ error[E0277]: `A` cannot be shared between threads safely - --> $DIR/extern-types-not-sync-send.rs:13:5 + --> $DIR/extern-types-not-sync-send.rs:13:19 | +LL | fn assert_sync() { } + | ----------- ---- required by this bound in `assert_sync` +... LL | assert_sync::(); - | ^^^^^^^^^^^^^^^^ `A` cannot be shared between threads safely + | ^ `A` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `A` -note: required by `assert_sync` - --> $DIR/extern-types-not-sync-send.rs:9:1 - | -LL | fn assert_sync() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `A` cannot be sent between threads safely - --> $DIR/extern-types-not-sync-send.rs:16:5 + --> $DIR/extern-types-not-sync-send.rs:16:19 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::(); - | ^^^^^^^^^^^^^^^^ `A` cannot be sent between threads safely + | ^ `A` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `A` -note: required by `assert_send` - --> $DIR/extern-types-not-sync-send.rs:10:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr index 4e4f5550fe..0417186eed 100644 --- a/src/test/ui/extern/extern-types-unsized.stderr +++ b/src/test/ui/extern/extern-types-unsized.stderr @@ -1,50 +1,47 @@ error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/extern-types-unsized.rs:22:5 + --> $DIR/extern-types-unsized.rs:22:20 | +LL | fn assert_sized() { } + | ------------ - required by this bound in `assert_sized` +... LL | assert_sized::(); - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:25:5 | +LL | fn assert_sized() { } + | ------------ - required by this bound in `assert_sized` +... LL | assert_sized::(); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Foo` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:28:5 | +LL | fn assert_sized() { } + | ------------ - required by this bound in `assert_sized` +... LL | assert_sized::>(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Bar`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Bar` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:31:5 | +LL | fn assert_sized() { } + | ------------ - required by this bound in `assert_sized` +... LL | assert_sized::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -52,11 +49,6 @@ LL | assert_sized::>>(); = note: to learn more, visit = note: required because it appears within the type `Bar` = note: required because it appears within the type `Bar>` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr index dce33f3d63..9a6af8119a 100644 --- a/src/test/ui/extern/extern-wrong-value-type.stderr +++ b/src/test/ui/extern/extern-wrong-value-type.stderr @@ -1,16 +1,14 @@ error[E0277]: expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}` - --> $DIR/extern-wrong-value-type.rs:9:5 + --> $DIR/extern-wrong-value-type.rs:9:11 | +LL | fn is_fn(_: F) where F: Fn() {} + | ----- ---- required by this bound in `is_fn` +... LL | is_fn(f); - | ^^^^^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` + | ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` | = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}` = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ } -note: required by `is_fn` - --> $DIR/extern-wrong-value-type.rs:4:1 - | -LL | fn is_fn(_: F) where F: Fn() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs new file mode 100644 index 0000000000..ff10d412a1 --- /dev/null +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -0,0 +1,65 @@ +// run-pass +// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten no threads support + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run destructors as it unwinds the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had fat LTO turned on. + +// Unlike issue-64655-extern-rust-must-allow-unwind.rs, the issue +// embodied in this test cropped up regardless of optimization level. +// Therefore it seemed worthy of being enshrined as a dedicated unit +// test. + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions just enumerate lto settings (the opt-level appeared irrelevant in practice) + +// revisions: no thin fat +//[no]compile-flags: -C lto=no +//[thin]compile-flags: -C lto=thin +//[fat]compile-flags: -C lto=fat + +#![feature(core_panic)] + +// (For some reason, reproducing the LTO issue requires pulling in std +// explicitly this way.) +#![no_std] +extern crate std; + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::boxed::Box; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs"; + core::panicking::panic(&("???", s, 17, 4)); + }); + + let wait = handle.join(); + + // Reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs new file mode 100644 index 0000000000..bc15fcb0e3 --- /dev/null +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -0,0 +1,83 @@ +// run-pass +// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten no threads support + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run destructors as it unwinds the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had optimization *and* fat +// LTO turned on. + +// This test is the closest thing to a "regression test" we can do +// without actually spawning subprocesses and comparing stderr +// results. +// +// This test takes the code from the above issue and adapts it to +// better fit our test infrastructure: +// +// * Instead of relying on `println!` to observe whether the destructor +// is run, we instead run the code in a spawned thread and +// communicate the destructor's operation via a synchronous atomic +// in static memory. +// +// * To keep the output from confusing a casual user, we override the +// panic hook to be a no-op (rather than printing a message to +// stderr). +// +// (pnkfelix has confirmed by hand that these additions do not mask +// the underlying bug.) + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions combine each lto setting with each optimization +// setting; pnkfelix observed three differing behaviors at opt-levels +// 0/1/2+3 for this test, so it seems prudent to be thorough. + +// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2 fat3 + +//[no0]compile-flags: -C opt-level=0 -C lto=no +//[no1]compile-flags: -C opt-level=1 -C lto=no +//[no2]compile-flags: -C opt-level=2 -C lto=no +//[no3]compile-flags: -C opt-level=3 -C lto=no +//[thin0]compile-flags: -C opt-level=0 -C lto=thin +//[thin1]compile-flags: -C opt-level=1 -C lto=thin +//[thin2]compile-flags: -C opt-level=2 -C lto=thin +//[thin3]compile-flags: -C opt-level=3 -C lto=thin +//[fat0]compile-flags: -C opt-level=0 -C lto=fat +//[fat1]compile-flags: -C opt-level=1 -C lto=fat +//[fat2]compile-flags: -C opt-level=2 -C lto=fat +//[fat3]compile-flags: -C opt-level=3 -C lto=fat + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + None::<()>.expect("???"); + }); + + let wait = handle.join(); + + // reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} diff --git a/src/test/ui/feature-gate-optimize_attribute.rs b/src/test/ui/feature-gate-optimize_attribute.rs index 7fc0fdde6f..15aa3a6af4 100644 --- a/src/test/ui/feature-gate-optimize_attribute.rs +++ b/src/test/ui/feature-gate-optimize_attribute.rs @@ -1,17 +1,17 @@ #![crate_type="rlib"] -#![optimize(speed)] //~ ERROR `#[optimize]` attribute is an unstable feature +#![optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature -#[optimize(size)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature mod module { -#[optimize(size)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn size() {} -#[optimize(speed)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn speed() {} #[optimize(banana)] -//~^ ERROR `#[optimize]` attribute is an unstable feature +//~^ ERROR the `#[optimize]` attribute is an experimental feature //~| ERROR E0722 fn not_known() {} diff --git a/src/test/ui/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gate-optimize_attribute.stderr index 4ec512eaf3..3e3ad71c34 100644 --- a/src/test/ui/feature-gate-optimize_attribute.stderr +++ b/src/test/ui/feature-gate-optimize_attribute.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:7:1 | LL | #[optimize(size)] @@ -7,7 +7,7 @@ LL | #[optimize(size)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:10:1 | LL | #[optimize(speed)] @@ -16,7 +16,7 @@ LL | #[optimize(speed)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:13:1 | LL | #[optimize(banana)] @@ -25,7 +25,7 @@ LL | #[optimize(banana)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:4:1 | LL | #[optimize(size)] @@ -34,7 +34,7 @@ LL | #[optimize(size)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:2:1 | LL | #![optimize(speed)] diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs index 784a1d2697..641e4b852e 100644 --- a/src/test/ui/feature-gate/allow-features-empty.rs +++ b/src/test/ui/feature-gate/allow-features-empty.rs @@ -1,8 +1,6 @@ // compile-flags: -Z allow_features= // Note: This test uses rustc internal flags because they will never stabilize. -#![feature(rustc_diagnostic_macros)] //~ ERROR - #![feature(rustc_const_unstable)] //~ ERROR #![feature(lang_items)] //~ ERROR diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr index ab41422ed0..a87d105850 100644 --- a/src/test/ui/feature-gate/allow-features-empty.stderr +++ b/src/test/ui/feature-gate/allow-features-empty.stderr @@ -1,27 +1,21 @@ -error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:4:12 - | -LL | #![feature(rustc_diagnostic_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:6:12 + --> $DIR/allow-features-empty.rs:4:12 | LL | #![feature(rustc_const_unstable)] | ^^^^^^^^^^^^^^^^^^^^ error[E0725]: the feature `lang_items` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:8:12 + --> $DIR/allow-features-empty.rs:6:12 | LL | #![feature(lang_items)] | ^^^^^^^^^^ error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:10:12 + --> $DIR/allow-features-empty.rs:8:12 | LL | #![feature(unknown_stdlib_feature)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0725`. diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs index de3439a5b6..de69e48a65 100644 --- a/src/test/ui/feature-gate/allow-features.rs +++ b/src/test/ui/feature-gate/allow-features.rs @@ -1,8 +1,6 @@ -// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items +// compile-flags: -Z allow_features=lang_items // Note: This test uses rustc internal flags because they will never stabilize. -#![feature(rustc_diagnostic_macros)] - #![feature(rustc_const_unstable)] //~ ERROR #![feature(lang_items)] diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr index 5b39a6f053..157dddf06a 100644 --- a/src/test/ui/feature-gate/allow-features.stderr +++ b/src/test/ui/feature-gate/allow-features.stderr @@ -1,11 +1,11 @@ error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features - --> $DIR/allow-features.rs:6:12 + --> $DIR/allow-features.rs:4:12 | LL | #![feature(rustc_const_unstable)] | ^^^^^^^^^^^^^^^^^^^^ error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features - --> $DIR/allow-features.rs:10:12 + --> $DIR/allow-features.rs:8:12 | LL | #![feature(unknown_stdlib_feature)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs index 92844f9306..b6c8648a7d 100644 --- a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs @@ -1,4 +1,4 @@ -//~ ERROR kind="static-nobundle" is feature gated +//~ ERROR kind="static-nobundle" is unstable // Test the behavior of rustc when non-existent library is statically linked // compile-flags: -l static-nobundle=nonexistent diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr index 059559dd92..cfff4c36a6 100644 --- a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: kind="static-nobundle" is feature gated +error[E0658]: kind="static-nobundle" is unstable | = note: for more information, see https://github.com/rust-lang/rust/issues/37403 = help: add `#![feature(static_nobundle)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 6d51bb3f8a..68ff95e420 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -84,12 +84,12 @@ #![crate_name = "0900"] #![crate_type = "bin"] // cannot pass "0800" here -// For #![crate_id], see issue #43142. (I cannot bear to enshrine current behavior in a test) +#![crate_id = "10"] //~ WARN use of deprecated attribute // FIXME(#44232) we should warn that this isn't used. #![feature(rust1)] -// For #![no_start], see issue #43144. (I cannot bear to enshrine current behavior in a test) +#![no_start] //~ WARN use of deprecated attribute // (cannot easily gating state of crate-level #[no_main]; but non crate-level is below at "0400") #![no_builtins] diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 864df35a79..b2a6018b53 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -186,6 +186,20 @@ LL | mod inner { #![macro_escape] } | = help: consider an outer attribute, `#[macro_use]` mod ... +warning: use of deprecated attribute `crate_id`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:87:1 + | +LL | #![crate_id = "10"] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated attribute `no_start`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:92:1 + | +LL | #![no_start] + | ^^^^^^^^^^^^ help: remove this attribute + warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12 | diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr index be3536aa78..f14591c85e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr @@ -1,5 +1,5 @@ error: cannot find derive macro `x3300` in this scope - --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 + --> $DIR/issue-43106-gating-of-derive-2.rs:12:14 | LL | #[derive(x3300)] | ^^^^^ @@ -11,7 +11,7 @@ LL | #[derive(x3300)] | ^^^^^ error: cannot find derive macro `x3300` in this scope - --> $DIR/issue-43106-gating-of-derive-2.rs:12:14 + --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 | LL | #[derive(x3300)] | ^^^^^ diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs index 1397412988..c5d9e0db4d 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs @@ -1,9 +1,6 @@ // `#![derive]` raises errors when it occurs at contexts other than ADT // definitions. -#![derive(Debug)] -//~^ ERROR `derive` may only be applied to structs, enums and unions - #[derive(Debug)] //~^ ERROR `derive` may only be applied to structs, enums and unions mod derive { diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr index 25f160983d..db29a2bddd 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr @@ -1,38 +1,32 @@ error: `derive` may only be applied to structs, enums and unions --> $DIR/issue-43106-gating-of-derive.rs:4:1 | -LL | #![derive(Debug)] - | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` - -error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:7:1 - | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:10:17 + --> $DIR/issue-43106-gating-of-derive.rs:7:17 | LL | mod inner { #![derive(Debug)] } | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:13:5 + --> $DIR/issue-43106-gating-of-derive.rs:10:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:26:5 + --> $DIR/issue-43106-gating-of-derive.rs:23:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:30:5 + --> $DIR/issue-43106-gating-of-derive.rs:27:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 41c9f79bfe..61da38eea7 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -10,7 +10,9 @@ // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change +//~^ ERROR intrinsic must be in extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental +//~^ ERROR intrinsic must be in extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -22,7 +24,9 @@ extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental an // Methods in trait definition trait Tr { extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental @@ -31,8 +35,6 @@ trait Tr { extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change - extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change - extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -47,7 +49,9 @@ struct S; // Methods in trait impl impl Tr for S { extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -60,7 +64,9 @@ impl Tr for S { // Methods in inherent impl impl S { extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 88e0b8667b..afda76dc2b 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:13:1 + --> $DIR/feature-gate-abi.rs:14:1 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:14:1 + --> $DIR/feature-gate-abi.rs:16:1 | LL | extern "vectorcall" fn f3() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | extern "vectorcall" fn f3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:15:1 + --> $DIR/feature-gate-abi.rs:17:1 | LL | extern "rust-call" fn f4() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | extern "rust-call" fn f4() {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:16:1 + --> $DIR/feature-gate-abi.rs:18:1 | LL | extern "msp430-interrupt" fn f5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | extern "msp430-interrupt" fn f5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:17:1 + --> $DIR/feature-gate-abi.rs:19:1 | LL | extern "ptx-kernel" fn f6() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | extern "ptx-kernel" fn f6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:18:1 + --> $DIR/feature-gate-abi.rs:20:1 | LL | extern "x86-interrupt" fn f7() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | extern "x86-interrupt" fn f7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:19:1 + --> $DIR/feature-gate-abi.rs:21:1 | LL | extern "thiscall" fn f8() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | extern "thiscall" fn f8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:20:1 + --> $DIR/feature-gate-abi.rs:22:1 | LL | extern "amdgpu-kernel" fn f9() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | extern "amdgpu-kernel" fn f9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:24:5 + --> $DIR/feature-gate-abi.rs:26:5 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:25:5 + --> $DIR/feature-gate-abi.rs:28:5 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | extern "platform-intrinsic" fn m2(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:26:5 + --> $DIR/feature-gate-abi.rs:30:5 | LL | extern "vectorcall" fn m3(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +102,7 @@ LL | extern "vectorcall" fn m3(); = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:27:5 + --> $DIR/feature-gate-abi.rs:31:5 | LL | extern "rust-call" fn m4(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | extern "rust-call" fn m4(); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:28:5 + --> $DIR/feature-gate-abi.rs:32:5 | LL | extern "msp430-interrupt" fn m5(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | extern "msp430-interrupt" fn m5(); = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:29:5 + --> $DIR/feature-gate-abi.rs:33:5 | LL | extern "ptx-kernel" fn m6(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | extern "ptx-kernel" fn m6(); = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:30:5 + --> $DIR/feature-gate-abi.rs:34:5 | LL | extern "x86-interrupt" fn m7(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL | extern "x86-interrupt" fn m7(); = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:31:5 + --> $DIR/feature-gate-abi.rs:35:5 | LL | extern "thiscall" fn m8(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,7 +146,7 @@ LL | extern "thiscall" fn m8(); = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:32:5 + --> $DIR/feature-gate-abi.rs:36:5 | LL | extern "amdgpu-kernel" fn m9(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,25 +154,8 @@ LL | extern "amdgpu-kernel" fn m9(); = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable -error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:34:5 - | -LL | extern "rust-intrinsic" fn dm1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` to the crate attributes to enable - -error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:35:5 - | -LL | extern "platform-intrinsic" fn dm2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/27731 - = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable - error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:36:5 + --> $DIR/feature-gate-abi.rs:38:5 | LL | extern "vectorcall" fn dm3() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -180,7 +163,7 @@ LL | extern "vectorcall" fn dm3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:37:5 + --> $DIR/feature-gate-abi.rs:39:5 | LL | extern "rust-call" fn dm4() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +172,7 @@ LL | extern "rust-call" fn dm4() {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:38:5 + --> $DIR/feature-gate-abi.rs:40:5 | LL | extern "msp430-interrupt" fn dm5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +181,7 @@ LL | extern "msp430-interrupt" fn dm5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:39:5 + --> $DIR/feature-gate-abi.rs:41:5 | LL | extern "ptx-kernel" fn dm6() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +190,7 @@ LL | extern "ptx-kernel" fn dm6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:40:5 + --> $DIR/feature-gate-abi.rs:42:5 | LL | extern "x86-interrupt" fn dm7() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +199,7 @@ LL | extern "x86-interrupt" fn dm7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:41:5 + --> $DIR/feature-gate-abi.rs:43:5 | LL | extern "thiscall" fn dm8() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -224,7 +207,7 @@ LL | extern "thiscall" fn dm8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:42:5 + --> $DIR/feature-gate-abi.rs:44:5 | LL | extern "amdgpu-kernel" fn dm9() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +216,7 @@ LL | extern "amdgpu-kernel" fn dm9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:49:5 + --> $DIR/feature-gate-abi.rs:51:5 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +224,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:50:5 + --> $DIR/feature-gate-abi.rs:53:5 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -250,7 +233,7 @@ LL | extern "platform-intrinsic" fn m2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:51:5 + --> $DIR/feature-gate-abi.rs:55:5 | LL | extern "vectorcall" fn m3() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -258,7 +241,7 @@ LL | extern "vectorcall" fn m3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:52:5 + --> $DIR/feature-gate-abi.rs:56:5 | LL | extern "rust-call" fn m4() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -267,7 +250,7 @@ LL | extern "rust-call" fn m4() {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:53:5 + --> $DIR/feature-gate-abi.rs:57:5 | LL | extern "msp430-interrupt" fn m5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -276,7 +259,7 @@ LL | extern "msp430-interrupt" fn m5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:54:5 + --> $DIR/feature-gate-abi.rs:58:5 | LL | extern "ptx-kernel" fn m6() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -285,7 +268,7 @@ LL | extern "ptx-kernel" fn m6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:55:5 + --> $DIR/feature-gate-abi.rs:59:5 | LL | extern "x86-interrupt" fn m7() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -294,7 +277,7 @@ LL | extern "x86-interrupt" fn m7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:56:5 + --> $DIR/feature-gate-abi.rs:60:5 | LL | extern "thiscall" fn m8() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -302,7 +285,7 @@ LL | extern "thiscall" fn m8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:57:5 + --> $DIR/feature-gate-abi.rs:61:5 | LL | extern "amdgpu-kernel" fn m9() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -311,7 +294,7 @@ LL | extern "amdgpu-kernel" fn m9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:62:5 + --> $DIR/feature-gate-abi.rs:66:5 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -319,7 +302,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:63:5 + --> $DIR/feature-gate-abi.rs:68:5 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -328,7 +311,7 @@ LL | extern "platform-intrinsic" fn im2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:64:5 + --> $DIR/feature-gate-abi.rs:70:5 | LL | extern "vectorcall" fn im3() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -336,7 +319,7 @@ LL | extern "vectorcall" fn im3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:65:5 + --> $DIR/feature-gate-abi.rs:71:5 | LL | extern "rust-call" fn im4() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -345,7 +328,7 @@ LL | extern "rust-call" fn im4() {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:66:5 + --> $DIR/feature-gate-abi.rs:72:5 | LL | extern "msp430-interrupt" fn im5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -354,7 +337,7 @@ LL | extern "msp430-interrupt" fn im5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:67:5 + --> $DIR/feature-gate-abi.rs:73:5 | LL | extern "ptx-kernel" fn im6() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -363,7 +346,7 @@ LL | extern "ptx-kernel" fn im6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:68:5 + --> $DIR/feature-gate-abi.rs:74:5 | LL | extern "x86-interrupt" fn im7() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -372,7 +355,7 @@ LL | extern "x86-interrupt" fn im7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:69:5 + --> $DIR/feature-gate-abi.rs:75:5 | LL | extern "thiscall" fn im8() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -380,7 +363,7 @@ LL | extern "thiscall" fn im8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:70:5 + --> $DIR/feature-gate-abi.rs:76:5 | LL | extern "amdgpu-kernel" fn im9() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -389,7 +372,7 @@ LL | extern "amdgpu-kernel" fn im9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:74:11 + --> $DIR/feature-gate-abi.rs:80:11 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -397,7 +380,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:75:11 + --> $DIR/feature-gate-abi.rs:81:11 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -406,7 +389,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:76:11 + --> $DIR/feature-gate-abi.rs:82:11 | LL | type A3 = extern "vectorcall" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -414,7 +397,7 @@ LL | type A3 = extern "vectorcall" fn(); = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:77:11 + --> $DIR/feature-gate-abi.rs:83:11 | LL | type A4 = extern "rust-call" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -423,7 +406,7 @@ LL | type A4 = extern "rust-call" fn(); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:78:11 + --> $DIR/feature-gate-abi.rs:84:11 | LL | type A5 = extern "msp430-interrupt" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -432,7 +415,7 @@ LL | type A5 = extern "msp430-interrupt" fn(); = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:79:11 + --> $DIR/feature-gate-abi.rs:85:11 | LL | type A6 = extern "ptx-kernel" fn (); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -441,7 +424,7 @@ LL | type A6 = extern "ptx-kernel" fn (); = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:80:11 + --> $DIR/feature-gate-abi.rs:86:11 | LL | type A7 = extern "x86-interrupt" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -450,7 +433,7 @@ LL | type A7 = extern "x86-interrupt" fn(); = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:81:11 + --> $DIR/feature-gate-abi.rs:87:11 | LL | type A8 = extern "thiscall" fn(); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -458,7 +441,7 @@ LL | type A8 = extern "thiscall" fn(); = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:82:11 + --> $DIR/feature-gate-abi.rs:88:11 | LL | type A9 = extern "amdgpu-kernel" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -467,7 +450,7 @@ LL | type A9 = extern "amdgpu-kernel" fn(); = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:85:1 + --> $DIR/feature-gate-abi.rs:91:1 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -475,7 +458,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:86:1 + --> $DIR/feature-gate-abi.rs:92:1 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -484,7 +467,7 @@ LL | extern "platform-intrinsic" {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:87:1 + --> $DIR/feature-gate-abi.rs:93:1 | LL | extern "vectorcall" {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -492,7 +475,7 @@ LL | extern "vectorcall" {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:88:1 + --> $DIR/feature-gate-abi.rs:94:1 | LL | extern "rust-call" {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -501,7 +484,7 @@ LL | extern "rust-call" {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:89:1 + --> $DIR/feature-gate-abi.rs:95:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -510,7 +493,7 @@ LL | extern "msp430-interrupt" {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:90:1 + --> $DIR/feature-gate-abi.rs:96:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -519,7 +502,7 @@ LL | extern "ptx-kernel" {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:91:1 + --> $DIR/feature-gate-abi.rs:97:1 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -528,7 +511,7 @@ LL | extern "x86-interrupt" {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:92:1 + --> $DIR/feature-gate-abi.rs:98:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -536,7 +519,7 @@ LL | extern "thiscall" {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:93:1 + --> $DIR/feature-gate-abi.rs:99:1 | LL | extern "amdgpu-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -544,6 +527,54 @@ LL | extern "amdgpu-kernel" {} = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable -error: aborting due to 63 previous errors +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:26:32 + | +LL | extern "rust-intrinsic" fn m1(); + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:28:36 + | +LL | extern "platform-intrinsic" fn m2(); + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:12:33 + | +LL | extern "rust-intrinsic" fn f1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:14:37 + | +LL | extern "platform-intrinsic" fn f2() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:51:37 + | +LL | extern "rust-intrinsic" fn m1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:53:41 + | +LL | extern "platform-intrinsic" fn m2() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:66:38 + | +LL | extern "rust-intrinsic" fn im1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:68:42 + | +LL | extern "platform-intrinsic" fn im2() {} + | ^^ + +error: aborting due to 69 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs index 17b4f775ad..ad89096183 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs @@ -5,7 +5,7 @@ use core::alloc::Layout; -#[alloc_error_handler] //~ ERROR `#[alloc_error_handler]` is an unstable feature +#[alloc_error_handler] //~ ERROR the `#[alloc_error_handler]` attribute is an experimental feature fn oom(info: Layout) -> ! { loop {} } diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr index d18cc09ffe..79e44bf0d8 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[alloc_error_handler]` is an unstable feature +error[E0658]: the `#[alloc_error_handler]` attribute is an experimental feature --> $DIR/feature-gate-alloc-error-handler.rs:8:1 | LL | #[alloc_error_handler] diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.rs b/src/test/ui/feature-gates/feature-gate-allow_fail.rs index f9ad485514..287d4ccf18 100644 --- a/src/test/ui/feature-gates/feature-gate-allow_fail.rs +++ b/src/test/ui/feature-gates/feature-gate-allow_fail.rs @@ -1,6 +1,6 @@ // check that #[allow_fail] is feature-gated -#[allow_fail] //~ ERROR allow_fail attribute is currently unstable +#[allow_fail] //~ ERROR the `#[allow_fail]` attribute is an experimental feature fn ok_to_fail() { assert!(false); } diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr index 37bf3a262a..0f60a2de3a 100644 --- a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr @@ -1,4 +1,4 @@ -error[E0658]: allow_fail attribute is currently unstable +error[E0658]: the `#[allow_fail]` attribute is an experimental feature --> $DIR/feature-gate-allow_fail.rs:3:1 | LL | #[allow_fail] diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs deleted file mode 100644 index 801aeb82aa..0000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs +++ /dev/null @@ -1,9 +0,0 @@ -// edition:2015 - -async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition - //~^ ERROR async fn is unstable - -fn main() { - let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` - let _ = async || { true }; //~ ERROR cannot find value `async` in this scope -} diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr deleted file mode 100644 index 0157ed5534..0000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/feature-gate-async-await-2015-edition.rs:3:1 - | -LL | async fn foo() {} - | ^^^^^ - -error[E0422]: cannot find struct, variant or union type `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:7:13 - | -LL | let _ = async {}; - | ^^^^^ not found in this scope - -error[E0425]: cannot find value `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:8:13 - | -LL | let _ = async || { true }; - | ^^^^^ not found in this scope - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await-2015-edition.rs:3:1 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0422, E0425, E0658, E0670. -For more information about an error, try `rustc --explain E0422`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs deleted file mode 100644 index 78391c0e10..0000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await.rs +++ /dev/null @@ -1,18 +0,0 @@ -// edition:2018 - -struct S; - -impl S { - async fn foo() {} //~ ERROR async fn is unstable -} - -trait T { - async fn foo(); //~ ERROR trait fns cannot be declared `async` - //~^ ERROR async fn is unstable -} - -async fn foo() {} //~ ERROR async fn is unstable - -fn main() { - let _ = async {}; //~ ERROR async blocks are unstable -} diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr deleted file mode 100644 index 9f4a90157a..0000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error[E0706]: trait fns cannot be declared `async` - --> $DIR/feature-gate-async-await.rs:10:5 - | -LL | async fn foo(); - | ^^^^^^^^^^^^^^^ - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:6:5 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:10:5 - | -LL | async fn foo(); - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:14:1 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async blocks are unstable - --> $DIR/feature-gate-async-await.rs:17:13 - | -LL | let _ = async {}; - | ^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs index d34936b42a..936cab268d 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs @@ -1,18 +1,18 @@ // Check that literals in attributes parse just fine. -#[fake_attr] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(100)] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr("hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(name = "hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute macro `fake_attr` in th -#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute macro `fake_attr` in this scop -#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute macro `fake_attr` in -#[fake_attr(true)] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_attr(b"hi")] //~ ERROR cannot find attribute macro `fake_attr` in this scope -#[fake_doc(r"doc")] //~ ERROR cannot find attribute macro `fake_doc` in this scope +#[fake_attr] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(100)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr("hello")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(name = "hello")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute `fake_attr` in th +#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute `fake_attr` in this scop +#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute `fake_attr` in +#[fake_attr(true)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(b"hi")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_doc(r"doc")] //~ ERROR cannot find attribute `fake_doc` in this scope struct Q {} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr index efdc2d1cd3..b7c45ec1fb 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr @@ -1,76 +1,76 @@ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:3:3 | LL | #[fake_attr] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:4:3 | LL | #[fake_attr(100)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:5:3 | LL | #[fake_attr(1, 2, 3)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:6:3 | LL | #[fake_attr("hello")] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:7:3 | LL | #[fake_attr(name = "hello")] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:8:3 | LL | #[fake_attr(1, "hi", key = 12, true, false)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:9:3 | LL | #[fake_attr(key = "hello", val = 10)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:10:3 | LL | #[fake_attr(key("hello"), val(10))] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:11:3 | LL | #[fake_attr(enabled = true, disabled = false)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:12:3 | LL | #[fake_attr(true)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:13:3 | LL | #[fake_attr(pi = 3.14159)] | ^^^^^^^^^ -error: cannot find attribute macro `fake_attr` in this scope +error: cannot find attribute `fake_attr` in this scope --> $DIR/feature-gate-custom_attribute.rs:14:3 | LL | #[fake_attr(b"hi")] | ^^^^^^^^^ -error: cannot find attribute macro `fake_doc` in this scope +error: cannot find attribute `fake_doc` in this scope --> $DIR/feature-gate-custom_attribute.rs:15:3 | LL | #[fake_doc(r"doc")] diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs index 8fe11cb02a..e4c80141aa 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs @@ -4,54 +4,54 @@ // gate-test-custom_attribute struct StLt<#[lt_struct] 'a>(&'a u32); -//~^ ERROR the attribute `lt_struct` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_struct` in this scope struct StTy<#[ty_struct] I>(I); -//~^ ERROR the attribute `ty_struct` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_struct` in this scope enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } -//~^ ERROR the attribute `lt_enum` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_enum` in this scope enum EnTy<#[ty_enum] J> { A(J), B } -//~^ ERROR the attribute `ty_enum` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_enum` in this scope trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } -//~^ ERROR the attribute `lt_trait` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_trait` in this scope trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } -//~^ ERROR the attribute `ty_trait` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_trait` in this scope type TyLt<#[lt_type] 'd> = &'d u32; -//~^ ERROR the attribute `lt_type` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_type` in this scope type TyTy<#[ty_type] L> = (L, ); -//~^ ERROR the attribute `ty_type` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_type` in this scope impl<#[lt_inherent] 'e> StLt<'e> { } -//~^ ERROR the attribute `lt_inherent` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_inherent` in this scope impl<#[ty_inherent] M> StTy { } -//~^ ERROR the attribute `ty_inherent` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_inherent` in this scope impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { - //~^ ERROR the attribute `lt_impl_for` is currently unknown to the compiler + //~^ ERROR cannot find attribute `lt_impl_for` in this scope fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } } } impl<#[ty_impl_for] N> TrTy for StTy { - //~^ ERROR the attribute `ty_impl_for` is currently unknown to the compiler + //~^ ERROR cannot find attribute `ty_impl_for` in this scope fn foo(&self, _: N) { } } fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } -//~^ ERROR the attribute `lt_fn` is currently unknown to the compiler +//~^ ERROR cannot find attribute `lt_fn` in this scope fn f_ty<#[ty_fn] O>(_: O) { } -//~^ ERROR the attribute `ty_fn` is currently unknown to the compiler +//~^ ERROR cannot find attribute `ty_fn` in this scope impl StTy { fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } - //~^ ERROR the attribute `lt_meth` is currently unknown to the compiler + //~^ ERROR cannot find attribute `lt_meth` in this scope fn m_ty<#[ty_meth] P>(_: P) { } - //~^ ERROR the attribute `ty_meth` is currently unknown to the compiler + //~^ ERROR cannot find attribute `ty_meth` in this scope } fn hof_lt(_: Q) where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 - //~^ ERROR the attribute `lt_hof` is currently unknown to the compiler + //~^ ERROR cannot find attribute `lt_hof` in this scope { } diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr index 15e0c41b90..bc89caddb4 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr @@ -1,156 +1,104 @@ -error[E0658]: the attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:6:13 +error: cannot find attribute `lt_hof` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:53:21 | -LL | struct StLt<#[lt_struct] 'a>(&'a u32); - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 + | ^^^^^^ -error[E0658]: the attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:8:13 +error: cannot find attribute `ty_meth` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:48:15 | -LL | struct StTy<#[ty_struct] I>(I); - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn m_ty<#[ty_meth] P>(_: P) { } + | ^^^^^^^ -error[E0658]: the attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:11:11 +error: cannot find attribute `lt_meth` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:46:15 | -LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + | ^^^^^^^ -error[E0658]: the attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:13:11 - | -LL | enum EnTy<#[ty_enum] J> { A(J), B } - | ^^^^^^^^^^ +error: cannot find attribute `ty_fn` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:42:11 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn f_ty<#[ty_fn] O>(_: O) { } + | ^^^^^ -error[E0658]: the attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:16:12 +error: cannot find attribute `lt_fn` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:40:11 | -LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } - | ^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } + | ^^^^^ -error[E0658]: the attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:18:12 - | -LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } - | ^^^^^^^^^^^ +error: cannot find attribute `ty_impl_for` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:35:8 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | impl<#[ty_impl_for] N> TrTy for StTy { + | ^^^^^^^^^^^ -error[E0658]: the attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:21:11 - | -LL | type TyLt<#[lt_type] 'd> = &'d u32; - | ^^^^^^^^^^ +error: cannot find attribute `lt_impl_for` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:31:8 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { + | ^^^^^^^^^^^ -error[E0658]: the attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:23:11 - | -LL | type TyTy<#[ty_type] L> = (L, ); - | ^^^^^^^^^^ +error: cannot find attribute `ty_inherent` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:28:8 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | impl<#[ty_inherent] M> StTy { } + | ^^^^^^^^^^^ -error[E0658]: the attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:26:6 +error: cannot find attribute `lt_inherent` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:26:8 | LL | impl<#[lt_inherent] 'e> StLt<'e> { } - | ^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + | ^^^^^^^^^^^ -error[E0658]: the attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:28:6 +error: cannot find attribute `ty_type` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:23:13 | -LL | impl<#[ty_inherent] M> StTy { } - | ^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | type TyTy<#[ty_type] L> = (L, ); + | ^^^^^^^ -error[E0658]: the attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:31:6 +error: cannot find attribute `lt_type` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:21:13 | -LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { - | ^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | type TyLt<#[lt_type] 'd> = &'d u32; + | ^^^^^^^ -error[E0658]: the attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:35:6 +error: cannot find attribute `ty_trait` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:18:14 | -LL | impl<#[ty_impl_for] N> TrTy for StTy { - | ^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } + | ^^^^^^^^ -error[E0658]: the attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:40:9 +error: cannot find attribute `lt_trait` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:16:14 | -LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } - | ^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } + | ^^^^^^^^ -error[E0658]: the attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:42:9 +error: cannot find attribute `ty_enum` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:13:13 | -LL | fn f_ty<#[ty_fn] O>(_: O) { } - | ^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | enum EnTy<#[ty_enum] J> { A(J), B } + | ^^^^^^^ -error[E0658]: the attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:46:13 +error: cannot find attribute `lt_enum` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:11:13 | -LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } + | ^^^^^^^ -error[E0658]: the attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:48:13 +error: cannot find attribute `ty_struct` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:8:15 | -LL | fn m_ty<#[ty_meth] P>(_: P) { } - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | struct StTy<#[ty_struct] I>(I); + | ^^^^^^^^^ -error[E0658]: the attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/feature-gate-custom_attribute2.rs:53:19 +error: cannot find attribute `lt_struct` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:6:15 | -LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 - | ^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | struct StLt<#[lt_struct] 'a>(&'a u32); + | ^^^^^^^^^ error: aborting due to 17 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.rs b/src/test/ui/feature-gates/feature-gate-doc_alias.rs index adb6fc217a..c95722102d 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_alias.rs +++ b/src/test/ui/feature-gates/feature-gate-doc_alias.rs @@ -1,4 +1,4 @@ -#[doc(alias = "foo")] //~ ERROR: `#[doc(alias = "...")]` is experimental +#[doc(alias = "foo")] //~ ERROR: `#[doc(alias)]` is experimental pub struct Foo; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr index dddaa45de8..540b1f5ccb 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr +++ b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[doc(alias = "...")]` is experimental +error[E0658]: `#[doc(alias)]` is experimental --> $DIR/feature-gate-doc_alias.rs:1:1 | LL | #[doc(alias = "foo")] diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.rs b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs index bb3846e7f6..b12b8a1057 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_cfg.rs +++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs @@ -1,2 +1,2 @@ -#[doc(cfg(unix))] //~ ERROR: `#[doc(cfg(...))]` is experimental +#[doc(cfg(unix))] //~ ERROR: `#[doc(cfg)]` is experimental fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr index 7b0a231df4..eaa908d003 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr +++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[doc(cfg(...))]` is experimental +error[E0658]: `#[doc(cfg)]` is experimental --> $DIR/feature-gate-doc_cfg.rs:1:1 | LL | #[doc(cfg(unix))] diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs index 6cdcfa67c3..4bb9a40deb 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs +++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs @@ -1,4 +1,4 @@ -#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword = "...")]` is experimental +#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is experimental /// wonderful mod foo{} diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr index abde0bea9b..15a41d9ffa 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr +++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[doc(keyword = "...")]` is experimental +error[E0658]: `#[doc(keyword)]` is experimental --> $DIR/feature-gate-doc_keyword.rs:1:1 | LL | #[doc(keyword = "match")] diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs index dec3fa1857..9d68d3ec4f 100644 --- a/src/test/ui/feature-gates/feature-gate-external_doc.rs +++ b/src/test/ui/feature-gates/feature-gate-external_doc.rs @@ -1,2 +1,2 @@ -#[doc(include="asdf.md")] //~ ERROR: `#[doc(include = "...")]` is experimental +#[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr index a5a874374d..683c0ad217 100644 --- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr +++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[doc(include = "...")]` is experimental +error[E0658]: `#[doc(include)]` is experimental --> $DIR/feature-gate-external_doc.rs:1:1 | LL | #[doc(include="asdf.md")] diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs index cee930fd78..382d891fee 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.rs +++ b/src/test/ui/feature-gates/feature-gate-generators.rs @@ -2,3 +2,9 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield statement outside of generator literal } + +#[cfg(FALSE)] +fn foo() { + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental +} diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr index cdb0560125..24b814b410 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.stderr +++ b/src/test/ui/feature-gates/feature-gate-generators.stderr @@ -7,12 +7,30 @@ LL | yield true; = note: for more information, see https://github.com/rust-lang/rust/issues/43122 = help: add `#![feature(generators)]` to the crate attributes to enable +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:8:5 + | +LL | yield; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:9:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + error[E0627]: yield statement outside of generator literal --> $DIR/feature-gate-generators.rs:2:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.rs b/src/test/ui/feature-gates/feature-gate-intrinsics.rs index d1da943382..e0dc3cc579 100644 --- a/src/test/ui/feature-gates/feature-gate-intrinsics.rs +++ b/src/test/ui/feature-gates/feature-gate-intrinsics.rs @@ -3,5 +3,6 @@ extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change } extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change +//~^ ERROR intrinsic must be in fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr index 09843f05af..101a10e8df 100644 --- a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr +++ b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr @@ -22,7 +22,13 @@ error[E0093]: unrecognized intrinsic function: `bar` LL | fn bar(); | ^^^^^^^^^ unrecognized intrinsic -error: aborting due to 3 previous errors +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-intrinsics.rs:5:34 + | +LL | extern "rust-intrinsic" fn baz() {} + | ^^ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0093, E0658. For more information about an error, try `rustc --explain E0093`. diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs index 078ecc5776..359ed835bc 100644 --- a/src/test/ui/feature-gates/feature-gate-is_sorted.rs +++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs @@ -1,11 +1,11 @@ fn main() { - // Assert `Iterator` methods are feature gated + // Assert `Iterator` methods are unstable assert!([1, 2, 2, 9].iter().is_sorted()); //~^ ERROR: use of unstable library feature 'is_sorted': new API assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); //~^ ERROR: use of unstable library feature 'is_sorted': new API - // Assert `[T]` methods are feature gated + // Assert `[T]` methods are unstable assert!([1, 2, 2, 9].is_sorted()); //~^ ERROR: use of unstable library feature 'is_sorted': new API assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.rs b/src/test/ui/feature-gates/feature-gate-link_cfg.rs index 1905346e2b..27ec2e98eb 100644 --- a/src/test/ui/feature-gates/feature-gate-link_cfg.rs +++ b/src/test/ui/feature-gates/feature-gate-link_cfg.rs @@ -1,5 +1,5 @@ #[link(name = "foo", cfg(foo))] -//~^ ERROR: is feature gated +//~^ ERROR: is unstable extern {} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr index 58aa4ed749..f6c5061546 100644 --- a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr +++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr @@ -1,4 +1,4 @@ -error[E0658]: is feature gated +error[E0658]: is unstable --> $DIR/feature-gate-link_cfg.rs:1:1 | LL | #[link(name = "foo", cfg(foo))] diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs index ea06c775b1..5050c4792b 100644 --- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs +++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs @@ -1,7 +1,7 @@ use std::fmt::{Debug, Display}; #[marker] trait ExplicitMarker {} -//~^ ERROR marker traits is an experimental feature +//~^ ERROR the `#[marker]` attribute is an experimental feature impl ExplicitMarker for T {} impl ExplicitMarker for T {} diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr index 94dfaf9206..304c081c5a 100644 --- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr +++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr @@ -1,4 +1,4 @@ -error[E0658]: marker traits is an experimental feature +error[E0658]: the `#[marker]` attribute is an experimental feature --> $DIR/feature-gate-marker_trait_attr.rs:3:1 | LL | #[marker] trait ExplicitMarker {} diff --git a/src/test/ui/feature-gates/feature-gate-no_core.rs b/src/test/ui/feature-gates/feature-gate-no_core.rs index 40178edd74..706efd7867 100644 --- a/src/test/ui/feature-gates/feature-gate-no_core.rs +++ b/src/test/ui/feature-gates/feature-gate-no_core.rs @@ -1,5 +1,5 @@ #![crate_type = "rlib"] -#![no_core] //~ ERROR no_core is experimental +#![no_core] //~ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/feature-gates/feature-gate-no_core.stderr b/src/test/ui/feature-gates/feature-gate-no_core.stderr index 4d4ca96544..a80b3cbba2 100644 --- a/src/test/ui/feature-gates/feature-gate-no_core.stderr +++ b/src/test/ui/feature-gates/feature-gate-no_core.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/feature-gate-no_core.rs:3:1 | LL | #![no_core] diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs index aca214d193..950f170f4f 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs @@ -1,6 +1,6 @@ //#![feature(non_exhaustive)] -#[non_exhaustive] //~ERROR non exhaustive is an experimental feature +#[non_exhaustive] //~ERROR the `#[non_exhaustive]` attribute is an experimental feature pub enum NonExhaustiveEnum { Unit, Tuple(u32), diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr index 8a01aa9eb6..482332b8d7 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr @@ -1,4 +1,4 @@ -error[E0658]: non exhaustive is an experimental feature +error[E0658]: the `#[non_exhaustive]` attribute is an experimental feature --> $DIR/feature-gate-non_exhaustive.rs:3:1 | LL | #[non_exhaustive] diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs index 13983726c7..c985298a30 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -16,8 +16,8 @@ fn f() {} fn g() {} #[rustc_dummy] -//~^ ERROR used by the test suite +//~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests #[rustc_unknown] //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler -//~| ERROR cannot find attribute macro `rustc_unknown` in this scope +//~| ERROR cannot find attribute `rustc_unknown` in this scope fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 23cf936ee8..d6fdab2b04 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -37,13 +37,13 @@ LL | #[rustc_unknown] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: cannot find attribute macro `rustc_unknown` in this scope +error: cannot find attribute `rustc_unknown` in this scope --> $DIR/feature-gate-rustc-attrs.rs:20:3 | LL | #[rustc_unknown] | ^^^^^^^^^^^^^ -error[E0658]: used by the test suite +error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests and will never be stable --> $DIR/feature-gate-rustc-attrs.rs:18:1 | LL | #[rustc_dummy] diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs deleted file mode 100644 index 63c2c31fd3..0000000000 --- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Test that diagnostic macros are gated by `rustc_diagnostic_macros` feature -// gate - -__register_diagnostic!(E0001); -//~^ ERROR cannot find macro `__register_diagnostic!` in this scope - -fn main() { - __diagnostic_used!(E0001); - //~^ ERROR cannot find macro `__diagnostic_used!` in this scope -} - -__build_diagnostic_array!(DIAGNOSTICS); -//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr deleted file mode 100644 index 478bc09f29..0000000000 --- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: cannot find macro `__build_diagnostic_array!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:12:1 - | -LL | __build_diagnostic_array!(DIAGNOSTICS); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot find macro `__register_diagnostic!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1 - | -LL | __register_diagnostic!(E0001); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: cannot find macro `__diagnostic_used!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5 - | -LL | __diagnostic_used!(E0001); - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs index 1ce6c54aa4..644b1f964a 100644 --- a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs +++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs @@ -1,5 +1,5 @@ #[link(name="foo", kind="static-nobundle")] -//~^ ERROR: kind="static-nobundle" is feature gated +//~^ ERROR: kind="static-nobundle" is unstable extern {} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr index f2e29cf067..cc0d426d6c 100644 --- a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr +++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr @@ -1,4 +1,4 @@ -error[E0658]: kind="static-nobundle" is feature gated +error[E0658]: kind="static-nobundle" is unstable --> $DIR/feature-gate-static-nobundle.rs:1:1 | LL | #[link(name="foo", kind="static-nobundle")] diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.rs b/src/test/ui/feature-gates/feature-gate-type_ascription.rs index e42e340550..7a59715730 100644 --- a/src/test/ui/feature-gates/feature-gate-type_ascription.rs +++ b/src/test/ui/feature-gates/feature-gate-type_ascription.rs @@ -1,4 +1,4 @@ -// Type ascription is feature gated +// Type ascription is unstable fn main() { let a = 10: u8; //~ ERROR type ascription is experimental diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index fc4317b316..c05379c71e 100644 --- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -44,10 +44,10 @@ LL | impl Fn<()> for Foo { = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0229]: associated type bindings are not allowed here - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:15:12 + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:15:6 | LL | impl FnOnce() for Foo1 { - | ^^ associated type not allowed here + | ^^^^^^^^ associated type not allowed here error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:21:6 diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs index 08e8ec9a56..6d8ac7e8f2 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs @@ -8,7 +8,7 @@ extern { fn extern_fn(); // CHECK-NOT: Function Attrs: nounwind // CHECK: declare void @unwinding_extern_fn - #[unwind(allowed)] //~ ERROR `#[unwind]` is experimental + #[unwind(allowed)] //~ ERROR the `#[unwind]` attribute is an experimental feature fn unwinding_extern_fn(); } diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr index 639b87e016..10cc494213 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[unwind]` is experimental +error[E0658]: the `#[unwind]` attribute is an experimental feature --> $DIR/feature-gate-unwind-attributes.rs:11:5 | LL | #[unwind(allowed)] diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr index 1f698c90cb..be6e41afaf 100644 --- a/src/test/ui/fmt/send-sync.stderr +++ b/src/test/ui/fmt/send-sync.stderr @@ -1,6 +1,9 @@ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/send-sync.rs:8:5 | +LL | fn send(_: T) {} + | ---- ---- required by this bound in `send` +... LL | send(format_args!("{:?}", c)); | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -12,15 +15,13 @@ LL | send(format_args!("{:?}", c)); = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `std::fmt::Arguments<'_>` -note: required by `send` - --> $DIR/send-sync.rs:1:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/send-sync.rs:9:5 | +LL | fn sync(_: T) {} + | ---- ---- required by this bound in `sync` +... LL | sync(format_args!("{:?}", c)); | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -32,11 +33,6 @@ LL | sync(format_args!("{:?}", c)); = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `std::fmt::Arguments<'_>` -note: required by `sync` - --> $DIR/send-sync.rs:2:1 - | -LL | fn sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr index 504bc2605e..f891b9c643 100644 --- a/src/test/ui/fn/fn-trait-formatting.stderr +++ b/src/test/ui/fn/fn-trait-formatting.stderr @@ -26,17 +26,15 @@ LL | let _: () = (box || -> isize { unimplemented!() }) as Box isize>` error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `{integer}` - --> $DIR/fn-trait-formatting.rs:19:5 + --> $DIR/fn-trait-formatting.rs:19:14 | +LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} + | -------- ------------------ required by this bound in `needs_fn` +... LL | needs_fn(1); - | ^^^^^^^^ expected an `Fn<(isize,)>` closure, found `{integer}` + | ^ expected an `Fn<(isize,)>` closure, found `{integer}` | = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}` -note: required by `needs_fn` - --> $DIR/fn-trait-formatting.rs:3:1 - | -LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs index 43b1a04c22..1871cf9d23 100644 --- a/src/test/ui/for/for-c-in-str.rs +++ b/src/test/ui/for/for-c-in-str.rs @@ -6,6 +6,9 @@ fn main() { //~| NOTE `&str` is not an iterator //~| HELP the trait `std::iter::Iterator` is not implemented for `&str` //~| NOTE required by `std::iter::IntoIterator::into_iter` - println!(""); + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + println!(); } } diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr index 0d77fd4efd..14aea2dc27 100644 --- a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr +++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` not covered +error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9 | LL | for &1 in [1].iter() {} - | ^^ pattern `&std::i32::MIN..=0i32` not covered + | ^^ patterns `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr index 02fdb808da..0672014a92 100644 --- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr +++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/for-loop-unconstrained-element-type.rs:8:14 | LL | for i in Vec::new() { } - | ^^^^^^^^^^ - | | - | cannot infer type - | the element type for this iterator is not specified + | ^^^^^^^^^^ the element type for this iterator is not specified error: aborting due to previous error diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr index 42591683fe..c9a71e0385 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator-yielding-or-returning-itself.stderr @@ -16,20 +16,17 @@ LL | | }) error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 | +LL | pub fn want_cyclic_generator_yield(_: T) + | --------------------------- +LL | where T: Generator + | --------- required by this bound in `want_cyclic_generator_yield` +... LL | want_cyclic_generator_yield(|| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size | = note: closures cannot capture themselves or take themselves as argument; this error may be the result of a recent compiler bug-fix, see https://github.com/rust-lang/rust/issues/46062 for more details -note: required by `want_cyclic_generator_yield` - --> $DIR/generator-yielding-or-returning-itself.rs:22:1 - | -LL | / pub fn want_cyclic_generator_yield(_: T) -LL | | where T: Generator -LL | | { -LL | | } - | |_^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 92f92e2a32..dab4d348ce 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,20 +1,26 @@ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:30:5 | +LL | auto trait Foo {} + | ----------------- trait `Foo` defined here +... LL | assert_foo(gen); - | ^^^^^^^^^^ + | ^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0` - = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` + = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`... + = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:48:5 | +LL | auto trait Foo {} + | ----------------- trait `Foo` defined here +... LL | assert_foo(gen); - | ^^^^^^^^^^ + | ^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1` - = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` + = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs index ce4642020f..e3d1902934 100644 --- a/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs +++ b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs @@ -4,7 +4,7 @@ // check-pass // edition:2018 -#![feature(async_await, generators, generator_trait)] +#![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/ui/generator/issue-62506-two_awaits.rs b/src/test/ui/generator/issue-62506-two_awaits.rs index 774019b6a5..672e16b780 100644 --- a/src/test/ui/generator/issue-62506-two_awaits.rs +++ b/src/test/ui/generator/issue-62506-two_awaits.rs @@ -4,7 +4,6 @@ // check-pass // edition:2018 -#![feature(async_await)] use std::future::Future; pub trait T { diff --git a/src/test/run-pass/generator/niche-in-generator.rs b/src/test/ui/generator/niche-in-generator.rs similarity index 95% rename from src/test/run-pass/generator/niche-in-generator.rs rename to src/test/ui/generator/niche-in-generator.rs index 9a644ed44a..42bee81f52 100644 --- a/src/test/run-pass/generator/niche-in-generator.rs +++ b/src/test/ui/generator/niche-in-generator.rs @@ -1,5 +1,7 @@ // Test that niche finding works with captured generator upvars. +// run-pass + #![feature(generators)] use std::mem::size_of_val; diff --git a/src/test/ui/generator/no-arguments-on-generators.stderr b/src/test/ui/generator/no-arguments-on-generators.stderr deleted file mode 100644 index 23ae21585f..0000000000 --- a/src/test/ui/generator/no-arguments-on-generators.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error[E0628]: generators cannot have explicit arguments - --> $DIR/no-arguments-on-generators.rs:4:15 - | -LL | let gen = |start| { - | ^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/generator/no-arguments-on-generators.rs b/src/test/ui/generator/no-parameters-on-generators.rs similarity index 90% rename from src/test/ui/generator/no-arguments-on-generators.rs rename to src/test/ui/generator/no-parameters-on-generators.rs index 344c1179be..a2632a4bd7 100644 --- a/src/test/ui/generator/no-arguments-on-generators.rs +++ b/src/test/ui/generator/no-parameters-on-generators.rs @@ -1,7 +1,7 @@ #![feature(generators)] fn main() { - let gen = |start| { //~ ERROR generators cannot have explicit arguments + let gen = |start| { //~ ERROR generators cannot have explicit parameters yield; }; } diff --git a/src/test/ui/generator/no-parameters-on-generators.stderr b/src/test/ui/generator/no-parameters-on-generators.stderr new file mode 100644 index 0000000000..41862f2b07 --- /dev/null +++ b/src/test/ui/generator/no-parameters-on-generators.stderr @@ -0,0 +1,8 @@ +error[E0628]: generators cannot have explicit parameters + --> $DIR/no-parameters-on-generators.rs:4:15 + | +LL | let gen = |start| { + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 7ea9832c99..620db245d3 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -1,32 +1,28 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:16:5 | +LL | fn assert_send(_: T) {} + | ----------- ---- required by this bound in `main::assert_send` +... LL | assert_send(|| { | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -note: required by `main::assert_send` - --> $DIR/not-send-sync.rs:7:5 - | -LL | fn assert_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | +LL | fn assert_sync(_: T) {} + | ----------- ---- required by this bound in `main::assert_sync` +... LL | assert_sync(|| { | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because it appears within the type `{std::cell::Cell, ()}` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` -note: required by `main::assert_sync` - --> $DIR/not-send-sync.rs:6:5 - | -LL | fn assert_sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs index 1e4593002c..8b75721420 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.rs +++ b/src/test/ui/generator/partial-initialization-across-yield.rs @@ -10,7 +10,7 @@ fn test_tuple() { let _ = || { let mut t: (i32, i32); t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.1 = 88; let _ = t; @@ -21,7 +21,7 @@ fn test_tuple_struct() { let _ = || { let mut t: T; t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.1 = 88; let _ = t; @@ -32,7 +32,7 @@ fn test_struct() { let _ = || { let mut t: S; t.x = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.y = 88; let _ = t; diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr index 8bf0037e07..66b86488ea 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.stderr +++ b/src/test/ui/generator/partial-initialization-across-yield.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:12:9 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:23:9 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:34:9 | LL | t.x = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 3 previous errors diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 404d3069f7..f2b1078e2b 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied - --> $DIR/static-not-unpin.rs:14:5 - | -LL | assert_unpin(generator); - | ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` - | -note: required by `assert_unpin` - --> $DIR/static-not-unpin.rs:7:1 + --> $DIR/static-not-unpin.rs:14:18 | LL | fn assert_unpin(_: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------ ----- required by this bound in `assert_unpin` +... +LL | assert_unpin(generator); + | ^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` error: aborting due to previous error diff --git a/src/test/ui/generic/generic-extern.stderr b/src/test/ui/generic/generic-extern.stderr index e7625abb1c..c90215b612 100644 --- a/src/test/ui/generic/generic-extern.stderr +++ b/src/test/ui/generic/generic-extern.stderr @@ -4,7 +4,7 @@ error[E0044]: foreign items may not have type parameters LL | fn foo(); | ^^^^^^^^^^^^ can't have type parameters | - = help: use specialization instead of type parameters by replacing them with concrete types like `u32` + = help: replace the type parameters with concrete types like `u32` error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs index a8f38180cc..88d396101d 100644 --- a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs @@ -14,7 +14,6 @@ fn want_foo() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct { @@ -30,7 +29,6 @@ fn one() { want_foo::>(); } -/////////////////////////////////////////////////////////////////////////// // Expressed as shorthand struct AnotherStruct { diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs new file mode 100644 index 0000000000..04e2ddd4a6 --- /dev/null +++ b/src/test/ui/hrtb/due-to-where-clause.rs @@ -0,0 +1,16 @@ +// ignore-compare-mode-nll +// ^ This code works in nll mode. + +fn main() { + test::(&mut 42); //~ ERROR implementation of `Foo` is not general enough +} + +trait Foo<'a> {} + +struct FooS<'a> { + data: &'a mut u32, +} + +impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {} + +fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {} diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr new file mode 100644 index 0000000000..9fef1e3354 --- /dev/null +++ b/src/test/ui/hrtb/due-to-where-clause.stderr @@ -0,0 +1,14 @@ +error: implementation of `Foo` is not general enough + --> $DIR/due-to-where-clause.rs:5:5 + | +LL | test::(&mut 42); + | ^^^^^^^^^^^^ implementation of `Foo` is not general enough +... +LL | trait Foo<'a> {} + | ---------------- trait `Foo` defined here + | + = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index 77a5491cb6..003f326593 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -1,11 +1,14 @@ error: implementation of `Deserialize` is not general enough --> $DIR/hrtb-cache-issue-54302.rs:19:5 | +LL | trait Deserialize<'de> {} + | ------------------------- trait `Deserialize` defined here +... LL | assert_deserialize_owned::<&'static str>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | - = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` - = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs index 391303676d..004d62ac51 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.rs +++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs @@ -15,7 +15,6 @@ fn want_foo1() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct; diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 3fb6baa35e..9822b48f4f 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,19 +1,16 @@ error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:28:10 + --> $DIR/hrtb-conflate-regions.rs:27:22 | +LL | fn want_foo2() + | --------- +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | -------------------------------------- required by this bound in `want_foo2` +... LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` + | ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` | = help: the following implementations were found: > -note: required by `want_foo2` - --> $DIR/hrtb-conflate-regions.rs:8:1 - | -LL | / fn want_foo2() -LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7f2ca037f0..969d9eda73 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,20 +1,17 @@ error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11 | +LL | fn foo() + | --- +LL | where +LL | T: Trait fn(&'b u32)>, + | -------------------------- required by this bound in `foo` +... LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` | = help: the following implementations were found: <() as Trait> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1 - | -LL | / fn foo() -LL | | where -LL | | T: Trait fn(&'b u32)>, -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr index cd5982e758..dddc2bcce4 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr @@ -1,20 +1,17 @@ error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5 + --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11 | +LL | fn foo() + | --- +LL | where +LL | T: Trait fn(fn(&'b u32))>, + | ------------------------------ required by this bound in `foo` +... LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` + | ^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` | = help: the following implementations were found: <() as Trait> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1 - | -LL | / fn foo() -LL | | where -LL | | T: Trait fn(fn(&'b u32))>, -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index f10e427a54..23ef75944d 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,20 +1,17 @@ error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11 | +LL | fn foo() + | --- +LL | where +LL | T: Trait fn(Cell<&'b u32>)>, + | -------------------------------- required by this bound in `foo` +... LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` + | ^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` | = help: the following implementations were found: <() as Trait)>> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1 - | -LL | / fn foo() -LL | | where -LL | | T: Trait fn(Cell<&'b u32>)>, -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index b5d945fe15..c2cc8ebad2 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,18 +1,15 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 | +LL | fn want_bar_for_any_ccx(b: &B) + | -------------------- +LL | where B : for<'ccx> Bar<'ccx> + | ------------------- required by this bound in `want_bar_for_any_ccx` +... LL | want_bar_for_any_ccx(b); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` | = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 - | -LL | / fn want_bar_for_any_ccx(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | } - | |_^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index 20a8fd459f..a93814ad4c 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,39 +1,28 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 + --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 | LL | want_foo_for_any_tcx(f); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` + | ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` +... +LL | fn want_foo_for_any_tcx(f: &F) + | -------------------- +LL | where F : for<'tcx> Foo<'tcx> + | ------------------- required by this bound in `want_foo_for_any_tcx` | = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound -note: required by `want_foo_for_any_tcx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 - | -LL | / fn want_foo_for_any_tcx(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> -LL | | { -LL | | want_foo_for_some_tcx(f); -LL | | want_foo_for_any_tcx(f); -LL | | } - | |_^ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 + --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | LL | want_bar_for_any_ccx(b); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` +... +LL | fn want_bar_for_any_ccx(b: &B) + | -------------------- +LL | where B : for<'ccx> Bar<'ccx> + | ------------------- required by this bound in `want_bar_for_any_ccx` | = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 - | -LL | / fn want_bar_for_any_ccx(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | want_foo_for_some_tcx(b); -... | -LL | | want_bar_for_any_ccx(b); -LL | | } - | |_^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 115851ddf9..6ec0beefd6 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,36 +1,30 @@ error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:24:5 + --> $DIR/hrtb-just-for-static.rs:24:17 | +LL | fn want_hrtb() + | --------- +LL | where T : for<'a> Foo<&'a isize> + | ---------------------- required by this bound in `want_hrtb` +... LL | want_hrtb::() - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` + | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` | = help: the following implementations were found: > -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 - | -LL | / fn want_hrtb() -LL | | where T : for<'a> Foo<&'a isize> -LL | | { -LL | | } - | |_^ error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:30:5 + --> $DIR/hrtb-just-for-static.rs:30:17 | +LL | fn want_hrtb() + | --------- +LL | where T : for<'a> Foo<&'a isize> + | ---------------------- required by this bound in `want_hrtb` +... LL | want_hrtb::<&'a u32>() - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` + | ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` | = help: the following implementations were found: <&'a u32 as Foo<&'a isize>> -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 - | -LL | / fn want_hrtb() -LL | | where T : for<'a> Foo<&'a isize> -LL | | { -LL | | } - | |_^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index e7deca7644..c0e3fd3cf4 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -1,11 +1,17 @@ error: implementation of `Stream` is not general enough --> $DIR/issue-30786.rs:108:22 | -LL | let map = source.map(|x: &_| x); - | ^^^ +LL | / pub trait Stream { +LL | | type Item; +LL | | fn next(self) -> Option; +LL | | } + | |_- trait `Stream` defined here +... +LL | let map = source.map(|x: &_| x); + | ^^^ implementation of `Stream` is not general enough | - = note: `Stream` would have to be implemented for the type `&'0 mut Map`, for any lifetime `'0` - = note: but `Stream` is actually implemented for the type `&'1 mut Map`, for some specific lifetime `'1` + = note: `Stream` would have to be implemented for the type `&'0 mut Map`, for any lifetime `'0`... + = note: ...but `Stream` is actually implemented for the type `&'1 mut Map`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index 8614d86d93..1cfd93e59d 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,11 +1,11 @@ error: higher-ranked subtype error - --> $DIR/issue-30786.rs:112:18 + --> $DIR/issue-30786.rs:113:18 | LL | let filter = map.filter(|x: &_| true); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:17 + --> $DIR/issue-30786.rs:115:17 | LL | let count = filter.count(); // Assert that we still have a valid stream. | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index b9920a1950..c42297ca68 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -16,7 +16,7 @@ //[nll]compile-flags: -Z borrowck=mir -pub trait Stream { +pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here type Item; fn next(self) -> Option; } @@ -109,6 +109,7 @@ fn main() { //[migrate]~^ ERROR implementation of `Stream` is not general enough //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 + //[migrate]~| NOTE implementation of `Stream` is not general enough let filter = map.filter(|x: &_| true); //[nll]~^ ERROR higher-ranked subtype error let count = filter.count(); // Assert that we still have a valid stream. diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index b308291d5c..c818041e59 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied - --> $DIR/issue-46989.rs:40:5 + --> $DIR/issue-46989.rs:40:18 | +LL | fn assert_foo() {} + | ---------- --- required by this bound in `assert_foo` +... LL | assert_foo::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` | = help: the following implementations were found: -note: required by `assert_foo` - --> $DIR/issue-46989.rs:37:1 - | -LL | fn assert_foo() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs index 4bcaef3616..392e7233b5 100644 --- a/src/test/ui/hrtb/issue-57639.rs +++ b/src/test/ui/hrtb/issue-57639.rs @@ -10,7 +10,7 @@ // // See [this comment on GitHub][c] for more details. // -// run-pass +// check-pass // // [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861 diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index c2d0e0c2a2..fd6fce938b 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -6,6 +6,8 @@ LL | let v = Unit2.m( | = note: expected type `Unit4` found type `<_ as Ty<'_>>::V` + = note: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as std::ops::FnOnce<((&u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:38:19 diff --git a/src/test/ui/hygiene/auxiliary/codegen-attrs.rs b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs new file mode 100644 index 0000000000..74afedbeb7 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs @@ -0,0 +1,10 @@ +#![feature(decl_macro)] + +macro m($f:ident) { + #[export_name = "export_function_name"] + pub fn $f() -> i32 { + 2 + } +} + +m!(rust_function_name); diff --git a/src/test/ui/hygiene/auxiliary/not-libstd.rs b/src/test/ui/hygiene/auxiliary/not-libstd.rs new file mode 100644 index 0000000000..babba293d0 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/not-libstd.rs @@ -0,0 +1 @@ +pub fn not_in_lib_std() {} diff --git a/src/test/ui/hygiene/cross-crate-codegen-attrs.rs b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs new file mode 100644 index 0000000000..af6b133438 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs @@ -0,0 +1,12 @@ +// Make sure that macro expanded codegen attributes work across crates. +// We used to gensym the identifiers in attributes, which stopped dependent +// crates from seeing them, resulting in linker errors in cases like this one. + +// run-pass +// aux-build:codegen-attrs.rs + +extern crate codegen_attrs; + +fn main() { + assert_eq!(codegen_attrs::rust_function_name(), 2); +} diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs index 3ad7435fec..83ca28167a 100644 --- a/src/test/ui/hygiene/no_implicit_prelude-2018.rs +++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs @@ -4,7 +4,7 @@ mod bar { fn f() { ::std::print!(""); // OK - print!(); //~ ERROR cannot find macro `print!` in this scope + print!(); //~ ERROR cannot find macro `print` in this scope } } diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr index 0fdb18d967..f31b75238d 100644 --- a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `print!` in this scope +error: cannot find macro `print` in this scope --> $DIR/no_implicit_prelude-2018.rs:7:9 | LL | print!(); diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs index 890c830754..204e7b2487 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.rs +++ b/src/test/ui/hygiene/no_implicit_prelude.rs @@ -13,7 +13,7 @@ mod bar { } fn f() { ::foo::m!(); - assert_eq!(0, 0); //~ ERROR cannot find macro `panic!` in this scope + assert_eq!(0, 0); //~ ERROR cannot find macro `panic` in this scope } } diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index a89176fe69..bc0ce746be 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -1,3 +1,11 @@ +error: cannot find macro `panic` in this scope + --> $DIR/no_implicit_prelude.rs:16:9 + | +LL | assert_eq!(0, 0); + | ^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + error[E0433]: failed to resolve: use of undeclared type or module `Vec` --> $DIR/no_implicit_prelude.rs:11:9 | @@ -7,14 +15,6 @@ LL | fn f() { ::bar::m!(); } LL | Vec::new(); | ^^^ use of undeclared type or module `Vec` -error: cannot find macro `panic!` in this scope - --> $DIR/no_implicit_prelude.rs:16:9 - | -LL | assert_eq!(0, 0); - | ^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - error[E0599]: no method named `clone` found for type `()` in the current scope --> $DIR/no_implicit_prelude.rs:12:12 | @@ -22,7 +22,7 @@ LL | fn f() { ::bar::m!(); } | ------------ in this macro invocation ... LL | ().clone() - | ^^^^^ + | ^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/hygiene/prelude-import-hygiene.rs b/src/test/ui/hygiene/prelude-import-hygiene.rs new file mode 100644 index 0000000000..51e7bed658 --- /dev/null +++ b/src/test/ui/hygiene/prelude-import-hygiene.rs @@ -0,0 +1,29 @@ +// Make sure that attribute used when injecting the prelude are resolved +// hygienically. + +// check-pass +// aux-build:not-libstd.rs + +//revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +// The prelude import shouldn't see these as candidates for when it's trying to +// use the built-in macros. +extern crate core; +use core::prelude::v1::test as prelude_import; +use core::prelude::v1::test as macro_use; + +// Should not be used for the prelude import - not a concern in the 2015 edition +// because `std` is already declared in the crate root. +#[cfg(rust2018)] +extern crate not_libstd as std; + +#[cfg(rust2018)] +mod x { + // The extern crate item should override `std` in the extern prelude. + fn f() { + std::not_in_lib_std(); + } +} + +fn main() {} diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index 4192b97e75..39e32522c7 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -5,7 +5,7 @@ LL | fn f() { ::baz::m!(); } | ------------ in this macro invocation ... LL | pub macro m() { ().f() } - | ^ + | ^ method not found in `()` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index beac4c17ab..6971873ba6 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -13,3 +13,13 @@ macro_rules! foo /* 0#0 */ { ($ x : ident) => { y + $ x } } fn bar /* 0#0 */() { let x /* 0#0 */ = 1; y /* 0#1 */ + x /* 0#0 */ } fn y /* 0#0 */() { } + +/* +Expansions: +0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root +1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo) + +SyntaxContexts: +#0: parent: #0, outer_mark: (ExpnId(0), Opaque) +#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent) +*/ diff --git a/src/test/ui/if-ret.stderr b/src/test/ui/if-ret.stderr new file mode 100644 index 0000000000..58cc707605 --- /dev/null +++ b/src/test/ui/if-ret.stderr @@ -0,0 +1,10 @@ +warning: unreachable block in `if` expression + --> $DIR/if-ret.rs:6:24 + | +LL | fn foo() { if (return) { } } + | -------- ^^^ unreachable block in `if` expression + | | + | any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs index 15892de838..826371be35 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.rs +++ b/src/test/ui/if/if-without-else-as-fn-expr.rs @@ -3,7 +3,6 @@ fn foo(bar: usize) -> usize { return 3; } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo2(bar: usize) -> usize { @@ -11,7 +10,6 @@ fn foo2(bar: usize) -> usize { return 3; }; //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] x } @@ -20,7 +18,6 @@ fn foo3(bar: usize) -> usize { 3 } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo_let(bar: usize) -> usize { @@ -28,7 +25,6 @@ fn foo_let(bar: usize) -> usize { return 3; } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo2_let(bar: usize) -> usize { @@ -36,7 +32,6 @@ fn foo2_let(bar: usize) -> usize { return 3; }; //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] x } @@ -45,7 +40,6 @@ fn foo3_let(bar: usize) -> usize { 3 } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } // FIXME(60254): deduplicate first error in favor of second. diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr index 06600b1cb9..b49c2aa631 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.stderr +++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr @@ -1,14 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:2:5 - | -LL | / if bar % 5 == 0 { -LL | | return 3; -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause --> $DIR/if-without-else-as-fn-expr.rs:2:5 | @@ -24,20 +13,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:10:20 - | -LL | let x: usize = if bar % 5 == 0 { - | ____________________^ -LL | | return 3; -LL | | }; - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:10:20 + --> $DIR/if-without-else-as-fn-expr.rs:9:20 | LL | let x: usize = if bar % 5 == 0 { | _________-__________^ @@ -52,19 +29,8 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:19:5 - | -LL | / if bar % 5 == 0 { -LL | | 3 -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:19:5 + --> $DIR/if-without-else-as-fn-expr.rs:17:5 | LL | fn foo3(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -78,19 +44,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:27:5 - | -LL | / if let 0 = 1 { -LL | | return 3; -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:27:5 + --> $DIR/if-without-else-as-fn-expr.rs:24:5 | LL | fn foo_let(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -104,20 +59,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:35:20 - | -LL | let x: usize = if let 0 = 1 { - | ____________________^ -LL | | return 3; -LL | | }; - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:35:20 + --> $DIR/if-without-else-as-fn-expr.rs:31:20 | LL | let x: usize = if let 0 = 1 { | _________-__________^ @@ -132,19 +75,8 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:44:5 - | -LL | / if let 0 = 1 { -LL | | 3 -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:44:5 + --> $DIR/if-without-else-as-fn-expr.rs:39:5 | LL | fn foo3_let(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -158,7 +90,6 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0317. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 61450d3203..d11941fee1 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -72,16 +72,14 @@ LL | | } error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/auto-trait-leak.rs:15:5 | +LL | fn send(_: T) {} + | ---- ---- required by this bound in `send` +... LL | send(cycle2().clone()); | ^^^^ `std::rc::Rc` cannot be sent between threads safely | = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `impl std::clone::Clone` -note: required by `send` - --> $DIR/auto-trait-leak.rs:4:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 19899ff83f..d163e1dff7 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -1,32 +1,28 @@ error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:13:5 | +LL | fn send(_: T) {} + | ---- ---- required by this bound in `send` +... LL | send(before()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` -note: required by `send` - --> $DIR/auto-trait-leak2.rs:10:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:16:5 | +LL | fn send(_: T) {} + | ---- ---- required by this bound in `send` +... LL | send(after()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` -note: required by `send` - --> $DIR/auto-trait-leak2.rs:10:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr index ad108173a7..644d26b340 100644 --- a/src/test/ui/impl-trait/bindings-opaque.stderr +++ b/src/test/ui/impl-trait/bindings-opaque.stderr @@ -10,19 +10,19 @@ error[E0599]: no method named `count_ones` found for type `impl std::marker::Cop --> $DIR/bindings-opaque.rs:11:17 | LL | let _ = FOO.count_ones(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ method not found in `impl std::marker::Copy` error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope --> $DIR/bindings-opaque.rs:13:17 | LL | let _ = BAR.count_ones(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ method not found in `impl std::marker::Copy` error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope --> $DIR/bindings-opaque.rs:15:17 | LL | let _ = foo.count_ones(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ method not found in `impl std::marker::Copy` error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index c33261bfd0..235c1f80ef 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -1,13 +1,12 @@ // compile-fail +// ignore-tidy-linelength // edition:2018 -#![feature(async_await)] #![feature(impl_trait_in_bindings)] //~^ WARNING the feature `impl_trait_in_bindings` is incomplete // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo(T); @@ -32,7 +31,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { @@ -44,7 +42,8 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR: type mismatch + //~^ ERROR: type mismatch + //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope Foo(()) } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index aa306a7e08..99c6a8cdd6 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -7,25 +7,35 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:29:32 + --> $DIR/bound-normalization-fail.rs:28:32 | LL | fn foo_fail() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type | = note: expected type `()` found type `::Assoc` + = note: consider constraining the associated type `::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the return type of a function must have a statically known size +error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/bound-normalization-fail.rs:44:41 + | +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` - --> $DIR/bound-normalization-fail.rs:46:41 + --> $DIR/bound-normalization-fail.rs:44:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type | = note: expected type `()` found type `>::Assoc` + = note: consider constraining the associated type `>::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the return type of a function must have a statically known size -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/bound-normalization-pass.rs b/src/test/ui/impl-trait/bound-normalization-pass.rs index 5b634e3106..fff17667fd 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.rs +++ b/src/test/ui/impl-trait/bound-normalization-pass.rs @@ -1,14 +1,12 @@ // check-pass // edition:2018 -#![feature(async_await)] #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_bindings)] //~^ WARNING the feature `impl_trait_in_bindings` is incomplete // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo(T); @@ -32,7 +30,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { @@ -59,7 +56,6 @@ mod lifetimes { } } -///////////////////////////////////////////// // Reduction using `impl Trait` in bindings mod impl_trait_in_bindings { @@ -80,7 +76,6 @@ mod impl_trait_in_bindings { } } -///////////////////////////////////////////// // The same applied to `type Foo = impl Bar`s mod opaque_types { diff --git a/src/test/ui/impl-trait/bound-normalization-pass.stderr b/src/test/ui/impl-trait/bound-normalization-pass.stderr index 229acdb2b1..d048da7f60 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.stderr +++ b/src/test/ui/impl-trait/bound-normalization-pass.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/bound-normalization-pass.rs:6:12 + --> $DIR/bound-normalization-pass.rs:5:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/closure-calling-parent-fn.rs b/src/test/ui/impl-trait/closure-calling-parent-fn.rs index 58d7875ccd..9dab334a21 100644 --- a/src/test/ui/impl-trait/closure-calling-parent-fn.rs +++ b/src/test/ui/impl-trait/closure-calling-parent-fn.rs @@ -5,7 +5,7 @@ // `foo` and hence is treated opaquely within the closure body. This // resulted in a failed subtype relationship. // -// run-pass +// check-pass fn foo() -> impl Copy { || foo(); } fn bar() -> impl Copy { || bar(); } diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs new file mode 100644 index 0000000000..3b71415738 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs @@ -0,0 +1,16 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { type Item: ?Sized; } +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn foo(x: &str, y: &str) -> impl Foo { () } + +fn main() { } diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs new file mode 100644 index 0000000000..e8da52aad0 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs @@ -0,0 +1,11 @@ +// Test that we don't get an error with `dyn Object` in an impl Trait +// when there are multiple inputs. The `dyn Object` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Alpha {} +trait Object {} +impl Alpha for T {} +fn alpha(x: &str, y: &str) -> impl Alpha { () } +fn main() { } diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs new file mode 100644 index 0000000000..aad9d89fe2 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs @@ -0,0 +1,27 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Foo { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs new file mode 100644 index 0000000000..8d34c1b6c2 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs @@ -0,0 +1,23 @@ +// Test that `impl Alpha` resets the object-lifetime +// default to `'static`. +// +// check-pass + +trait Alpha { + fn item(&self) -> Box { + panic!() + } +} + +trait Object {} +impl Alpha for T {} +fn alpha(x: &str, y: &str) -> impl Alpha { () } +fn is_static(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Alpha { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 3e6181adec..e30e2626e9 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -15,6 +15,8 @@ LL | let _: i32 = Leak::leak(hide(0_i32)); | = note: expected type `i32` found type `::T` + = note: consider constraining the associated type `::T` to `i32` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/equality2.rs:38:10 diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr index 357e6b026e..e4d0a731eb 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -9,6 +9,8 @@ LL | fn foo(&self, a: &impl Debug, b: &B) { } | = note: expected type `fn(&(), &B, &impl Debug)` found type `fn(&(), &impl Debug, &B)` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index dfee20ca64..1ca2e3d906 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -1,6 +1,7 @@ // edition:2018 // ignore-tidy-linelength -#![feature(async_await, type_alias_impl_trait)] + +#![feature(type_alias_impl_trait)] pub trait Bar { type E: Copy; diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 676c3fe3d4..01371b4d5c 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `impl std::future::Future: std::marker::Copy` is not satisfied - --> $DIR/issue-55872-2.rs:12:5 + --> $DIR/issue-55872-2.rs:13:5 | LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future` @@ -7,7 +7,7 @@ LL | type E = impl Copy; = note: the return type of a function must have a statically known size error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:14:28 + --> $DIR/issue-55872-2.rs:15:28 | LL | fn foo() -> Self::E { | ____________________________^ diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 666418f6ee..441191beaf 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -5,7 +5,7 @@ LL | struct Bar; | ----------- method `foo` not found for this ... LL | f1.foo(1usize); - | ^^^ + | ^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `foo`, perhaps you need to implement it: diff --git a/src/test/ui/impl-trait/issues/issue-53457.rs b/src/test/ui/impl-trait/issues/issue-53457.rs index de8c579743..3f97502492 100644 --- a/src/test/ui/impl-trait/issues/issue-53457.rs +++ b/src/test/ui/impl-trait/issues/issue-53457.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(type_alias_impl_trait)] @@ -9,7 +9,7 @@ fn bar(f: F) -> F { } fn foo() -> X { - bar(|x| ()) + bar(|_| ()) } fn main() {} diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index afb3376638..fb870d6c6f 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ----------- method `is_empty` not found for this ... LL | foo(|s| s.is_empty()); - | ^^^^^^^^ + | ^^^^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `is_empty`, perhaps you need to implement it: diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs index 2da3886bb5..3911769b0c 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs @@ -1,5 +1,5 @@ // edition:2018 -// run-pass +// check-pass // revisions: migrate mir //[mir]compile-flags: -Z borrowck=mir diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.rs b/src/test/ui/impl-trait/needs_least_region_or_bound.rs index 52475f65a8..3c8682bb62 100644 --- a/src/test/ui/impl-trait/needs_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/needs_least_region_or_bound.rs @@ -1,9 +1,7 @@ -// run-pass +// check-pass #![feature(member_constraints)] -use std::fmt::Debug; - trait MultiRegionTrait<'a, 'b> {} impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {} diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index d980d7ccca..be8f3ab1b7 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `method` found for type `u32` in the current scope --> $DIR/no-method-suggested-traits.rs:23:10 | LL | 1u32.method(); - | ^^^^^^ + | ^^^^^^ method not found in `u32` | = help: items from traits can only be used if the trait is in scope help: the following traits are implemented but not in scope, perhaps add a `use` for one of them: @@ -20,7 +20,7 @@ error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::box --> $DIR/no-method-suggested-traits.rs:26:44 | LL | std::rc::Rc::new(&mut Box::new(&1u32)).method(); - | ^^^^^^ + | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u32>>` | = help: items from traits can only be used if the trait is in scope help: the following traits are implemented but not in scope, perhaps add a `use` for one of them: @@ -38,7 +38,7 @@ error[E0599]: no method named `method` found for type `char` in the current scop --> $DIR/no-method-suggested-traits.rs:30:9 | LL | 'a'.method(); - | ^^^^^^ + | ^^^^^^ method not found in `char` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -49,8 +49,16 @@ LL | use foo::Bar; error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope --> $DIR/no-method-suggested-traits.rs:32:43 | +LL | fn method(&self) {} + | ------ + | | + | the method is available for `std::boxed::Box>>` here + | the method is available for `std::pin::Pin>>` here + | the method is available for `std::sync::Arc>>` here + | the method is available for `std::rc::Rc>>` here +... LL | std::rc::Rc::new(&mut Box::new(&'a')).method(); - | ^^^^^^ + | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&char>>` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -62,7 +70,7 @@ error[E0599]: no method named `method` found for type `i32` in the current scope --> $DIR/no-method-suggested-traits.rs:35:10 | LL | 1i32.method(); - | ^^^^^^ + | ^^^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -74,7 +82,7 @@ error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::box --> $DIR/no-method-suggested-traits.rs:37:44 | LL | std::rc::Rc::new(&mut Box::new(&1i32)).method(); - | ^^^^^^ + | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&i32>>` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -89,7 +97,7 @@ LL | struct Foo; | ----------- method `method` not found for this ... LL | Foo.method(); - | ^^^^^^ + | ^^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `method`, perhaps you need to implement one of them: @@ -102,7 +110,7 @@ error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::box --> $DIR/no-method-suggested-traits.rs:42:43 | LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); - | ^^^^^^ + | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `method`, perhaps you need to implement one of them: @@ -115,7 +123,7 @@ error[E0599]: no method named `method2` found for type `u64` in the current scop --> $DIR/no-method-suggested-traits.rs:45:10 | LL | 1u64.method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `u64` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -125,7 +133,7 @@ error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::bo --> $DIR/no-method-suggested-traits.rs:47:44 | LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -135,7 +143,7 @@ error[E0599]: no method named `method2` found for type `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:50:37 | LL | no_method_suggested_traits::Foo.method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -145,7 +153,7 @@ error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::bo --> $DIR/no-method-suggested-traits.rs:52:71 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -155,7 +163,7 @@ error[E0599]: no method named `method2` found for type `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:54:40 | LL | no_method_suggested_traits::Bar::X.method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -165,7 +173,7 @@ error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::bo --> $DIR/no-method-suggested-traits.rs:56:74 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method2`, perhaps you need to implement it: @@ -178,7 +186,7 @@ LL | struct Foo; | ----------- method `method3` not found for this ... LL | Foo.method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method3`, perhaps you need to implement it: @@ -188,7 +196,7 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo --> $DIR/no-method-suggested-traits.rs:61:43 | LL | std::rc::Rc::new(&mut Box::new(&Foo)).method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method3`, perhaps you need to implement it: @@ -201,7 +209,7 @@ LL | enum Bar { X } | -------- method `method3` not found for this ... LL | Bar::X.method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method3`, perhaps you need to implement it: @@ -211,7 +219,7 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo --> $DIR/no-method-suggested-traits.rs:65:46 | LL | std::rc::Rc::new(&mut Box::new(&Bar::X)).method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `method3`, perhaps you need to implement it: @@ -221,37 +229,37 @@ error[E0599]: no method named `method3` found for type `usize` in the current sc --> $DIR/no-method-suggested-traits.rs:69:13 | LL | 1_usize.method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `usize` error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope --> $DIR/no-method-suggested-traits.rs:70:47 | LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&usize>>` error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:71:37 | LL | no_method_suggested_traits::Foo.method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:72:71 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:74:40 | LL | no_method_suggested_traits::Bar::X.method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:75:74 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` error: aborting due to 24 previous errors diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs new file mode 100644 index 0000000000..cfd9c0ec5b --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs @@ -0,0 +1,25 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. Even when there's an opaque type in another crate +// hiding this. + +fn id(t: T) -> impl Sized { t } + +fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id2()) +} + +fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id()) +} + +fn wrap(t: T) -> impl Sized { (t,) } + +fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap2()) +} + +fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap()) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr new file mode 100644 index 0000000000..7572c6c1bf --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr @@ -0,0 +1,35 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22 + | +LL | fn recursive_id() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23 + | +LL | fn recursive_id2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24 + | +LL | fn recursive_wrap() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 + | +LL | fn recursive_wrap2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr index d223b9672c..d92c3f034e 100644 --- a/src/test/ui/impl-trait/universal-mismatched-type.stderr +++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr @@ -8,6 +8,8 @@ LL | x | = note: expected type `std::string::String` found type `impl Debug` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 145d6a8431..98a70f268c 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -6,6 +6,8 @@ LL | a = y; | = note: expected type `impl Debug` (type parameter) found type `impl Debug` (type parameter) + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs index 613ccc0b24..7b53f0c536 100644 --- a/src/test/ui/imports/gensymed.rs +++ b/src/test/ui/imports/gensymed.rs @@ -1,7 +1,9 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // edition:2018 // aux-build:gensymed.rs extern crate gensymed; +use gensymed::*; + fn main() {} diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 5afdd8889a..7d013828bd 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -21,25 +21,6 @@ LL | use inner1::*; | ^^^^^^^^^ = help: consider adding an explicit import of `exported` to disambiguate -error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/local-modularized-tricky-fail-1.rs:46:1 - | -LL | include!(); - | ^^^^^^^ ambiguous name - | - = note: `include` could refer to a macro from prelude -note: `include` could also refer to the macro defined here - --> $DIR/local-modularized-tricky-fail-1.rs:17:5 - | -LL | / macro_rules! include { -LL | | () => () -LL | | } - | |_____^ -... -LL | define_include!(); - | ------------------ in this macro invocation - = help: use `crate::include` to refer to this macro unambiguously - error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/local-modularized-tricky-fail-1.rs:35:5 | @@ -59,6 +40,25 @@ LL | define_panic!(); | ---------------- in this macro invocation = help: use `crate::panic` to refer to this macro unambiguously +error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) + --> $DIR/local-modularized-tricky-fail-1.rs:46:1 + | +LL | include!(); + | ^^^^^^^ ambiguous name + | + = note: `include` could refer to a macro from prelude +note: `include` could also refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:17:5 + | +LL | / macro_rules! include { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_include!(); + | ------------------ in this macro invocation + = help: use `crate::include` to refer to this macro unambiguously + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/reexports.rs b/src/test/ui/imports/reexports.rs index b0a591b08a..d76cc41be4 100644 --- a/src/test/ui/imports/reexports.rs +++ b/src/test/ui/imports/reexports.rs @@ -1,16 +1,21 @@ +#![warn(unused_imports)] + mod a { fn foo() {} mod foo {} mod a { pub use super::foo; //~ ERROR cannot be re-exported - pub use super::*; //~ ERROR must import something with the glob's visibility + pub use super::*; + //~^ WARNING glob import doesn't reexport anything because no candidate is public enough } } mod b { pub fn foo() {} - mod foo { pub struct S; } + mod foo { + pub struct S; + } pub mod a { pub use super::foo; // This is OK since the value `foo` is visible enough. diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr index af2c97e77b..4388e2c276 100644 --- a/src/test/ui/imports/reexports.stderr +++ b/src/test/ui/imports/reexports.stderr @@ -1,34 +1,40 @@ error[E0364]: `foo` is private, and cannot be re-exported - --> $DIR/reexports.rs:6:17 + --> $DIR/reexports.rs:8:17 | LL | pub use super::foo; | ^^^^^^^^^^ | note: consider marking `foo` as `pub` in the imported module - --> $DIR/reexports.rs:6:17 + --> $DIR/reexports.rs:8:17 | LL | pub use super::foo; | ^^^^^^^^^^ -error: A non-empty glob must import something with the glob's visibility - --> $DIR/reexports.rs:7:17 - | -LL | pub use super::*; - | ^^^^^^^^ - error[E0603]: module `foo` is private - --> $DIR/reexports.rs:28:15 + --> $DIR/reexports.rs:33:15 | LL | use b::a::foo::S; | ^^^ error[E0603]: module `foo` is private - --> $DIR/reexports.rs:29:15 + --> $DIR/reexports.rs:34:15 | LL | use b::b::foo::S as T; | ^^^ -error: aborting due to 4 previous errors +warning: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/reexports.rs:9:17 + | +LL | pub use super::*; + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/reexports.rs:1:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0364, E0603. For more information about an error, try `rustc --explain E0364`. diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index c84226ef31..2f2ab20cdf 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -13,20 +13,6 @@ LL | use foo::*; = help: consider adding an explicit import of `panic` to disambiguate = help: or use `self::panic` to refer to this macro unambiguously -error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/shadow_builtin_macros.rs:20:14 - | -LL | fn f() { panic!(); } - | ^^^^^ ambiguous name - | - = note: `panic` could refer to a macro from prelude -note: `panic` could also refer to the macro imported here - --> $DIR/shadow_builtin_macros.rs:19:26 - | -LL | ::two_macros::m!(use foo::panic;); - | ^^^^^^^^^^ - = help: use `self::panic` to refer to this macro unambiguously - error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/shadow_builtin_macros.rs:33:5 | @@ -62,6 +48,20 @@ note: `n` could also refer to the macro imported here LL | #[macro_use(n)] | ^ +error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) + --> $DIR/shadow_builtin_macros.rs:20:14 + | +LL | fn f() { panic!(); } + | ^^^^^ ambiguous name + | + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:19:26 + | +LL | ::two_macros::m!(use foo::panic;); + | ^^^^^^^^^^ + = help: use `self::panic` to refer to this macro unambiguously + error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/unresolved-imports-used.rs b/src/test/ui/imports/unresolved-imports-used.rs index d1461e7b04..75cf880192 100644 --- a/src/test/ui/imports/unresolved-imports-used.rs +++ b/src/test/ui/imports/unresolved-imports-used.rs @@ -1,12 +1,18 @@ -// There should be *no* unused import errors. +// There should be *one* unused import error. #![deny(unused_imports)] mod qux { fn quz() {} + pub fn quy() {} } -use qux::quz; //~ ERROR function `quz` is private -use qux::bar; //~ ERROR unresolved import `qux::bar` -use foo::bar; //~ ERROR unresolved import `foo` +use qux::quz; //~ ERROR function `quz` is private +use qux::bar; //~ ERROR unresolved import `qux::bar` +use foo::bar; //~ ERROR unresolved import `foo` +use baz::*; //~ ERROR unresolved import `baz` +use qux::bar2; //~ ERROR unresolved import `qux::bar2` +use foo2::bar2;//~ ERROR unresolved import `foo2` +use baz2::*; //~ ERROR unresolved import `baz2` +use qux::quy; //~ ERROR unused import fn main() {} diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr index e8c827a617..b341e8e059 100644 --- a/src/test/ui/imports/unresolved-imports-used.stderr +++ b/src/test/ui/imports/unresolved-imports-used.stderr @@ -1,22 +1,58 @@ error[E0432]: unresolved import `qux::bar` - --> $DIR/unresolved-imports-used.rs:9:5 + --> $DIR/unresolved-imports-used.rs:10:5 | LL | use qux::bar; | ^^^^^^^^ no `bar` in `qux` +error[E0432]: unresolved import `qux::bar2` + --> $DIR/unresolved-imports-used.rs:13:5 + | +LL | use qux::bar2; + | ^^^^^^^^^ no `bar2` in `qux` + error[E0432]: unresolved import `foo` - --> $DIR/unresolved-imports-used.rs:10:5 + --> $DIR/unresolved-imports-used.rs:11:5 | LL | use foo::bar; | ^^^ maybe a missing crate `foo`? +error[E0432]: unresolved import `baz` + --> $DIR/unresolved-imports-used.rs:12:5 + | +LL | use baz::*; + | ^^^ maybe a missing crate `baz`? + +error[E0432]: unresolved import `foo2` + --> $DIR/unresolved-imports-used.rs:14:5 + | +LL | use foo2::bar2; + | ^^^^ maybe a missing crate `foo2`? + +error[E0432]: unresolved import `baz2` + --> $DIR/unresolved-imports-used.rs:15:5 + | +LL | use baz2::*; + | ^^^^ maybe a missing crate `baz2`? + error[E0603]: function `quz` is private - --> $DIR/unresolved-imports-used.rs:8:10 + --> $DIR/unresolved-imports-used.rs:9:10 | LL | use qux::quz; | ^^^ -error: aborting due to 3 previous errors +error: unused import: `qux::quy` + --> $DIR/unresolved-imports-used.rs:16:5 + | +LL | use qux::quy; + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/unresolved-imports-used.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/in-band-lifetimes/nested-items.rs b/src/test/ui/in-band-lifetimes/nested-items.rs new file mode 100644 index 0000000000..7de20712fb --- /dev/null +++ b/src/test/ui/in-band-lifetimes/nested-items.rs @@ -0,0 +1,20 @@ +// Test that the `'a` from the impl doesn't +// prevent us from creating a `'a` parameter +// on the `blah` function. +// +// check-pass + +#![feature(in_band_lifetimes)] + +struct Foo<'a> { + x: &'a u32 + +} + +impl Foo<'a> { + fn method(&self) { + fn blah(f: Foo<'a>) { } + } +} + +fn main() { } diff --git a/src/test/ui/inaccessible-test-modules.stderr b/src/test/ui/inaccessible-test-modules.stderr deleted file mode 100644 index b6a817e6b1..0000000000 --- a/src/test/ui/inaccessible-test-modules.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0432]: unresolved import `__test` - --> $DIR/inaccessible-test-modules.rs:5:5 - | -LL | use __test as x; - | ------^^^^^ - | | - | no `__test` in the root - | help: a similar name exists in the module: `test` - -error[E0432]: unresolved import `__test_reexports` - --> $DIR/inaccessible-test-modules.rs:6:5 - | -LL | use __test_reexports as y; - | ----------------^^^^^ - | | - | no `__test_reexports` in the root - | help: a similar name exists in the module: `__test_reexports` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/include-macros/data.bin b/src/test/ui/include-macros/data.bin new file mode 100644 index 0000000000..ce4e0b8311 --- /dev/null +++ b/src/test/ui/include-macros/data.bin @@ -0,0 +1,2 @@ +This file starts with BOM. +Lines are separated by \r\n. diff --git a/src/test/ui/include-macros/normalization.rs b/src/test/ui/include-macros/normalization.rs new file mode 100644 index 0000000000..889f08e606 --- /dev/null +++ b/src/test/ui/include-macros/normalization.rs @@ -0,0 +1,12 @@ +// run-pass + +fn main() { + assert_eq!( + &include_bytes!("data.bin")[..], + &b"\xEF\xBB\xBFThis file starts with BOM.\r\nLines are separated by \\r\\n.\r\n"[..], + ); + assert_eq!( + include_str!("data.bin"), + "\u{FEFF}This file starts with BOM.\r\nLines are separated by \\r\\n.\r\n", + ); +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs new file mode 100644 index 0000000000..7d75f254bf --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr new file mode 100644 index 0000000000..f67e45b01d --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -0,0 +1,19 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:2:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0282]: type annotations needed for `impl std::future::Future` + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9 + | +LL | let fut = async { + | --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs new file mode 100644 index 0000000000..05f62f3d8c --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -0,0 +1,15 @@ +// edition:2018 + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr new file mode 100644 index 0000000000..bf31fb85cf --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-async.rs:11:9 + | +LL | let fut = async { + | --- consider giving `fut` a type +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs new file mode 100644 index 0000000000..8f48483c25 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -0,0 +1,6 @@ +fn main() { + let x = |a: (), b: ()| { + Err(a)?; //~ ERROR type annotations needed for the closure + Ok(b) + }; +} diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr new file mode 100644 index 0000000000..5f30b5d993 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` + --> $DIR/cannot-infer-closure.rs:3:9 + | +LL | Err(a)?; + | ^^^^^^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let x = |a: (), b: ()| -> std::result::Result<(), _> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index 3159a4b67d..a2ad58a7e4 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -44,7 +44,7 @@ LL | struct Foo; | ----------- method `bar` not found for this ... LL | Foo.bar(); - | ^^^ + | ^^^ method not found in `Foo` error: aborting due to 6 previous errors diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr index 4554da7b79..55523bad6c 100644 --- a/src/test/ui/inline-asm-bad-operand.stderr +++ b/src/test/ui/inline-asm-bad-operand.stderr @@ -37,8 +37,8 @@ LL | asm!("mov sp, $0"::"r"(addr), error[E0669]: invalid value for constraint in inline assembly --> $DIR/inline-asm-bad-operand.rs:56:32 | -LL | "r"("hello e0669")); - | ^^^^^^^^^^^^^ +LL | ... "r"("hello e0669")); + | ^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/interior-mutability/interior-mutability.rs b/src/test/ui/interior-mutability/interior-mutability.rs index ddc882cccf..6968e3669c 100644 --- a/src/test/ui/interior-mutability/interior-mutability.rs +++ b/src/test/ui/interior-mutability/interior-mutability.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences use std::cell::Cell; use std::panic::catch_unwind; fn main() { diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index 31390bc6cc..b76fce2880 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -1,14 +1,18 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary - --> $DIR/interior-mutability.rs:5:5 + --> $DIR/interior-mutability.rs:7:5 | LL | catch_unwind(|| { x.set(23); }); | ^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + ::: $SRC_DIR/libstd/panic.rs:LL:COL + | +LL | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { + | ---------- required by this bound in `std::panic::catch_unwind` | = help: within `std::cell::Cell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::Cell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell` - = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35 x:&std::cell::Cell]` - = note: required by `std::panic::catch_unwind` + = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:7:18: 7:35 x:&std::cell::Cell]` error: aborting due to previous error diff --git a/src/test/ui/intrinsics-always-extern.rs b/src/test/ui/intrinsics-always-extern.rs new file mode 100644 index 0000000000..22951147d7 --- /dev/null +++ b/src/test/ui/intrinsics-always-extern.rs @@ -0,0 +1,16 @@ +#![feature(intrinsics)] + +trait Foo { + extern "rust-intrinsic" fn foo(&self); //~ ERROR intrinsic must +} + +impl Foo for () { + extern "rust-intrinsic" fn foo(&self) { //~ ERROR intrinsic must + } +} + +extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must +} + +fn main() { +} diff --git a/src/test/ui/intrinsics-always-extern.stderr b/src/test/ui/intrinsics-always-extern.stderr new file mode 100644 index 0000000000..24b6da1609 --- /dev/null +++ b/src/test/ui/intrinsics-always-extern.stderr @@ -0,0 +1,24 @@ +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:4:32 + | +LL | extern "rust-intrinsic" fn foo(&self); + | ^^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:8:43 + | +LL | extern "rust-intrinsic" fn foo(&self) { + | ___________________________________________^ +LL | | } + | |_____^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:12:36 + | +LL | extern "rust-intrinsic" fn hello() { + | ____________________________________^ +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/issues/issue-10291.stderr b/src/test/ui/issues/issue-10291.stderr index 5e63469da5..a836593e0d 100644 --- a/src/test/ui/issues/issue-10291.stderr +++ b/src/test/ui/issues/issue-10291.stderr @@ -20,3 +20,4 @@ LL | fn test<'x>(x: &'x isize) { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr index 6efbd8e40e..413daa6db6 100644 --- a/src/test/ui/issues/issue-10465.stderr +++ b/src/test/ui/issues/issue-10465.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for type `&b::B` in the current scope --> $DIR/issue-10465.rs:17:15 | LL | b.foo(); - | ^^^ + | ^^^ method not found in `&b::B` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs index 70b712c560..b6f3bb8ef0 100644 --- a/src/test/ui/issues/issue-11692-1.rs +++ b/src/test/ui/issues/issue-11692-1.rs @@ -1,3 +1,3 @@ fn main() { - print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope + print!(testo!()); //~ ERROR cannot find macro `testo` in this scope } diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr index bfd1647e8b..386463436b 100644 --- a/src/test/ui/issues/issue-11692-1.stderr +++ b/src/test/ui/issues/issue-11692-1.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `testo!` in this scope +error: cannot find macro `testo` in this scope --> $DIR/issue-11692-1.rs:2:12 | LL | print!(testo!()); diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs index 61be284d73..5957ed338f 100644 --- a/src/test/ui/issues/issue-11692-2.rs +++ b/src/test/ui/issues/issue-11692-2.rs @@ -1,3 +1,3 @@ fn main() { - concat!(test!()); //~ ERROR cannot find macro `test!` in this scope + concat!(test!()); //~ ERROR cannot find macro `test` in this scope } diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr index 740c3555e5..f021943da3 100644 --- a/src/test/ui/issues/issue-11692-2.stderr +++ b/src/test/ui/issues/issue-11692-2.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `test!` in this scope +error: cannot find macro `test` in this scope --> $DIR/issue-11692-2.rs:2:13 | LL | concat!(test!()); diff --git a/src/test/ui/issues/issue-12028.rs b/src/test/ui/issues/issue-12028.rs index d55354529a..7c2b0d69c8 100644 --- a/src/test/ui/issues/issue-12028.rs +++ b/src/test/ui/issues/issue-12028.rs @@ -17,8 +17,6 @@ trait StreamHasher { fn stream(&self) -> Self::S; } -////////////////////////////////////////////////////////////////////////////// - trait StreamHash: Hash { fn input_stream(&self, stream: &mut H::S); } diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index 64694c7a8d..24aa88c3fa 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,5 +1,5 @@ error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == ::S` - --> $DIR/issue-12028.rs:29:14 + --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); | ^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs index 63b5a4dd1b..77278ecda6 100644 --- a/src/test/ui/issues/issue-1251.rs +++ b/src/test/ui/issues/issue-1251.rs @@ -6,8 +6,6 @@ #![feature(rustc_private)] -#![crate_id="rust_get_test_int"] - mod rustrt { extern crate libc; diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr index 739f061236..df9f1dd011 100644 --- a/src/test/ui/issues/issue-13483.stderr +++ b/src/test/ui/issues/issue-13483.stderr @@ -1,10 +1,10 @@ -error: missing condition for `if` statemement +error: missing condition for `if` expression --> $DIR/issue-13483.rs:3:14 | LL | } else if { | ^ expected if condition here -error: missing condition for `if` statemement +error: missing condition for `if` expression --> $DIR/issue-13483.rs:10:14 | LL | } else if { diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr index 9026845b4e..3f2d0aa87a 100644 --- a/src/test/ui/issues/issue-13853.stderr +++ b/src/test/ui/issues/issue-13853.stderr @@ -9,12 +9,14 @@ LL | self.iter() | = note: expected type `I` found type `std::slice::Iter<'_, N>` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0599]: no method named `iter` found for type `&G` in the current scope --> $DIR/issue-13853.rs:27:23 | LL | for node in graph.iter() { - | ^^^^ + | ^^^^ method not found in `&G` error[E0308]: mismatched types --> $DIR/issue-13853.rs:37:13 diff --git a/src/test/ui/issues/issue-14309.rs b/src/test/ui/issues/issue-14309.rs index d0e532a264..328a4c982b 100644 --- a/src/test/ui/issues/issue-14309.rs +++ b/src/test/ui/issues/issue-14309.rs @@ -27,7 +27,7 @@ struct D { } extern "C" { - fn foo(x: A); //~ ERROR type `A` which is not FFI-safe + fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe fn bar(x: B); //~ ERROR type `A` fn baz(x: C); fn qux(x: A2); //~ ERROR type `A` diff --git a/src/test/ui/issues/issue-14309.stderr b/src/test/ui/issues/issue-14309.stderr index e0491093a7..f598e1f9e2 100644 --- a/src/test/ui/issues/issue-14309.stderr +++ b/src/test/ui/issues/issue-14309.stderr @@ -1,8 +1,8 @@ -error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:30:15 | LL | fn foo(x: A); - | ^ + | ^ not FFI-safe | note: lint level defined here --> $DIR/issue-14309.rs:1:9 @@ -10,6 +10,7 @@ note: lint level defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-14309.rs:4:1 | @@ -18,13 +19,14 @@ LL | | x: i32 LL | | } | |_^ -error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:31:15 | LL | fn bar(x: B); - | ^ + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-14309.rs:4:1 | @@ -33,13 +35,14 @@ LL | | x: i32 LL | | } | |_^ -error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:33:15 | LL | fn qux(x: A2); - | ^^ + | ^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-14309.rs:4:1 | @@ -48,13 +51,14 @@ LL | | x: i32 LL | | } | |_^ -error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:34:16 | LL | fn quux(x: B2); - | ^^ + | ^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-14309.rs:4:1 | @@ -63,13 +67,14 @@ LL | | x: i32 LL | | } | |_^ -error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:36:16 | LL | fn fred(x: D); - | ^ + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-14309.rs:4:1 | diff --git a/src/test/ui/issues/issue-15207.stderr b/src/test/ui/issues/issue-15207.stderr index 2d90eb80fc..25ce7cb5cc 100644 --- a/src/test/ui/issues/issue-15207.stderr +++ b/src/test/ui/issues/issue-15207.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `push` found for type `!` in the current scope --> $DIR/issue-15207.rs:3:15 | LL | break.push(1) - | ^^^^ + | ^^^^ method not found in `!` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs index d21c321b09..5307153cb4 100644 --- a/src/test/ui/issues/issue-15381.rs +++ b/src/test/ui/issues/issue-15381.rs @@ -2,8 +2,8 @@ fn main() { let values: Vec = vec![1,2,3,4,5,6,7,8]; for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { - //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered + //~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not println!("y={}", y); - //~^ ERROR borrow of possibly uninitialized variable: `y` + //~^ ERROR borrow of possibly-uninitialized variable: `y` } } diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr index a8495846b3..47a0d514ad 100644 --- a/src/test/ui/issues/issue-15381.stderr +++ b/src/test/ui/issues/issue-15381.stderr @@ -1,14 +1,14 @@ -error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered +error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered --> $DIR/issue-15381.rs:4:9 | LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { - | ^^^^^^^^ pattern `&[]` not covered + | ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered -error[E0381]: borrow of possibly uninitialized variable: `y` +error[E0381]: borrow of possibly-uninitialized variable: `y` --> $DIR/issue-15381.rs:6:26 | LL | println!("y={}", y); - | ^ use of possibly uninitialized `y` + | ^ use of possibly-uninitialized `y` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-15783.rs b/src/test/ui/issues/issue-15783.rs index 77eae914fa..5189f550cf 100644 --- a/src/test/ui/issues/issue-15783.rs +++ b/src/test/ui/issues/issue-15783.rs @@ -6,9 +6,9 @@ fn main() { let name = "Foo"; let x = Some(&[name]); let msg = foo(x); -//~^ ERROR mismatched types -//~| expected type `std::option::Option<&[&str]>` -//~| found type `std::option::Option<&[&str; 1]>` -//~| expected slice, found array of 1 elements + //~^ ERROR mismatched types + //~| expected type `std::option::Option<&[&str]>` + //~| found type `std::option::Option<&[&str; 1]>` + //~| expected slice, found array of 1 element assert_eq!(msg, 3); } diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr index 595fe4025a..1d54b2830d 100644 --- a/src/test/ui/issues/issue-15783.stderr +++ b/src/test/ui/issues/issue-15783.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-15783.rs:8:19 | LL | let msg = foo(x); - | ^ expected slice, found array of 1 elements + | ^ expected slice, found array of 1 element | = note: expected type `std::option::Option<&[&str]>` found type `std::option::Option<&[&str; 1]>` diff --git a/src/test/ui/issues/issue-16250.rs b/src/test/ui/issues/issue-16250.rs index bf01627adf..a3c6751ad8 100644 --- a/src/test/ui/issues/issue-16250.rs +++ b/src/test/ui/issues/issue-16250.rs @@ -3,7 +3,7 @@ pub struct Foo; extern { - pub fn foo(x: (Foo)); //~ ERROR unspecified layout + pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo` } fn main() { diff --git a/src/test/ui/issues/issue-16250.stderr b/src/test/ui/issues/issue-16250.stderr index f3686e82b0..5686ac3774 100644 --- a/src/test/ui/issues/issue-16250.stderr +++ b/src/test/ui/issues/issue-16250.stderr @@ -1,8 +1,8 @@ -error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `Foo`, which is not FFI-safe --> $DIR/issue-16250.rs:6:20 | LL | pub fn foo(x: (Foo)); - | ^^^ + | ^^^ not FFI-safe | note: lint level defined here --> $DIR/issue-16250.rs:1:9 @@ -11,6 +11,7 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]` = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/issue-16250.rs:3:1 | diff --git a/src/test/ui/issues/issue-16739.rs b/src/test/ui/issues/issue-16739.rs index 54ad8fd076..94da2ca5ca 100644 --- a/src/test/ui/issues/issue-16739.rs +++ b/src/test/ui/issues/issue-16739.rs @@ -16,8 +16,6 @@ impl FnOnce<()> for Foo { extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,)> for Foo { extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } @@ -27,8 +25,6 @@ impl FnOnce<(u32,)> for Foo { extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,u32)> for Foo { extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } diff --git a/src/test/ui/issues/issue-17651.rs b/src/test/ui/issues/issue-17651.rs index 7629a5a3be..08f352c11f 100644 --- a/src/test/ui/issues/issue-17651.rs +++ b/src/test/ui/issues/issue-17651.rs @@ -4,4 +4,5 @@ fn main() { (|| Box::new(*(&[0][..])))(); //~^ ERROR the size for values of type + //~| ERROR the size for values of type } diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index ce9af1524b..c3445024c3 100644 --- a/src/test/ui/issues/issue-17651.stderr +++ b/src/test/ui/issues/issue-17651.stderr @@ -1,3 +1,13 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/issue-17651.rs:5:18 + | +LL | (|| Box::new(*(&[0][..])))(); + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[{integer}]` + = note: to learn more, visit + = note: required by `std::boxed::Box::::new` + error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/issue-17651.rs:5:9 | @@ -6,8 +16,9 @@ LL | (|| Box::new(*(&[0][..])))(); | = help: the trait `std::marker::Sized` is not implemented for `[{integer}]` = note: to learn more, visit - = note: required by `std::boxed::Box::::new` + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-17740.rs b/src/test/ui/issues/issue-17740.rs index c131b89584..b47568400c 100644 --- a/src/test/ui/issues/issue-17740.rs +++ b/src/test/ui/issues/issue-17740.rs @@ -4,11 +4,11 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { - //~^ mismatched method receiver + //~^ mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch - //~| mismatched method receiver + //~| mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index 7ab0fa4d81..b8a0a06763 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { @@ -23,7 +23,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl <'a> Foo<'a>{ | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { diff --git a/src/test/ui/issues/issue-17905-2.rs b/src/test/ui/issues/issue-17905-2.rs index 259d945018..44279cc867 100644 --- a/src/test/ui/issues/issue-17905-2.rs +++ b/src/test/ui/issues/issue-17905-2.rs @@ -6,8 +6,8 @@ impl Pair< isize > { fn say(self: &Pair<&str, isize>) { -//~^ ERROR mismatched method receiver -//~| ERROR mismatched method receiver +//~^ ERROR mismatched `self` parameter type +//~| ERROR mismatched `self` parameter type println!("{:?}", self); } } diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index e3909e0c12..585bc9c148 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { @@ -21,7 +21,7 @@ note: ...does not necessarily outlive the lifetime '_ as defined on the impl at LL | &str, | ^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr index 6048344125..9b890be3c7 100644 --- a/src/test/ui/issues/issue-18159.stderr +++ b/src/test/ui/issues/issue-18159.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-18159.rs:2:9 | LL | let x; - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1871.stderr b/src/test/ui/issues/issue-1871.stderr index fecd689251..b774ca22dd 100644 --- a/src/test/ui/issues/issue-1871.stderr +++ b/src/test/ui/issues/issue-1871.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `honk` found for type `{integer}` in the current s --> $DIR/issue-1871.rs:7:9 | LL | f.honk() - | ^^^^ + | ^^^^ method not found in `{integer}` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 63c33b7f44..d5e7092801 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-18959.rs:11:1 | +LL | pub trait Foo { fn foo(&self, ext_thing: &T); } + | --- method `foo` has generic type parameters +... LL | fn foo(b: &dyn Bar) { | ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1920-1.stderr b/src/test/ui/issues/issue-1920-1.stderr index b3ac05031b..089968ede7 100644 --- a/src/test/ui/issues/issue-1920-1.stderr +++ b/src/test/ui/issues/issue-1920-1.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `foo::issue_1920::S: std::clone::Clone` is not satisfied - --> $DIR/issue-1920-1.rs:12:5 - | -LL | assert_clone::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `foo::issue_1920::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-1.rs:9:1 + --> $DIR/issue-1920-1.rs:12:20 | LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------ ----- required by this bound in `assert_clone` +... +LL | assert_clone::(); + | ^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `foo::issue_1920::S` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1920-2.stderr b/src/test/ui/issues/issue-1920-2.stderr index a000a87302..eaf34e076c 100644 --- a/src/test/ui/issues/issue-1920-2.stderr +++ b/src/test/ui/issues/issue-1920-2.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `bar::S: std::clone::Clone` is not satisfied - --> $DIR/issue-1920-2.rs:10:5 - | -LL | assert_clone::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `bar::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-2.rs:7:1 + --> $DIR/issue-1920-2.rs:10:20 | LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------ ----- required by this bound in `assert_clone` +... +LL | assert_clone::(); + | ^^^^^^ the trait `std::clone::Clone` is not implemented for `bar::S` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1920-3.stderr b/src/test/ui/issues/issue-1920-3.stderr index 62e47a6866..0550f5feba 100644 --- a/src/test/ui/issues/issue-1920-3.stderr +++ b/src/test/ui/issues/issue-1920-3.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `issue_1920::S: std::clone::Clone` is not satisfied - --> $DIR/issue-1920-3.rs:14:5 - | -LL | assert_clone::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `issue_1920::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-3.rs:11:1 + --> $DIR/issue-1920-3.rs:14:20 | LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------ ----- required by this bound in `assert_clone` +... +LL | assert_clone::(); + | ^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `issue_1920::S` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index 27e3ff57bf..92bfdf1f26 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Qiz` cannot be made into an object --> $DIR/issue-19380.rs:11:3 | +LL | fn qiz(); + | --- associated function `qiz` has no `self` parameter +... LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object - | - = note: method `qiz` has no receiver error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr index a43368be58..c15c5392fa 100644 --- a/src/test/ui/issues/issue-19521.stderr +++ b/src/test/ui/issues/issue-19521.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `homura` found for type `&'static str` in the curr --> $DIR/issue-19521.rs:2:8 | LL | "".homura()(); - | ^^^^^^ + | ^^^^^^ method not found in `&'static str` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index e5da0a9b0d..5415a45f7d 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:15 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:30 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ the trait `Bar` cannot be made into an object | - = note: method `foo` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr index 5e576f1158..fe920c1693 100644 --- a/src/test/ui/issues/issue-19692.stderr +++ b/src/test/ui/issues/issue-19692.stderr @@ -5,7 +5,7 @@ LL | struct Homura; | -------------- method `kaname` not found for this ... LL | let Some(ref madoka) = Some(homura.kaname()); - | ^^^^^^ + | ^^^^^^ method not found in `Homura` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19734.rs b/src/test/ui/issues/issue-19734.rs index b730e19a1e..fe4a327aef 100644 --- a/src/test/ui/issues/issue-19734.rs +++ b/src/test/ui/issues/issue-19734.rs @@ -4,5 +4,5 @@ struct Type; impl Type { undef!(); - //~^ ERROR cannot find macro `undef!` in this scope + //~^ ERROR cannot find macro `undef` in this scope } diff --git a/src/test/ui/issues/issue-19734.stderr b/src/test/ui/issues/issue-19734.stderr index fc1a7d0381..81757974de 100644 --- a/src/test/ui/issues/issue-19734.stderr +++ b/src/test/ui/issues/issue-19734.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `undef!` in this scope +error: cannot find macro `undef` in this scope --> $DIR/issue-19734.rs:6:5 | LL | undef!(); diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr index e271005e74..2754d6bdd8 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/issues/issue-20005.stderr @@ -1,6 +1,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-20005.rs:8:5 | +LL | trait From { + | --------------- required by `From` +... LL | / fn to( LL | | self LL | | ) -> >::Result where Dst: From { @@ -11,11 +14,6 @@ LL | | } = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit = help: consider adding a `where Self: std::marker::Sized` bound -note: required by `From` - --> $DIR/issue-20005.rs:1:1 - | -LL | trait From { - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr index 5ab23cb55b..4c464e6d4f 100644 --- a/src/test/ui/issues/issue-20225.stderr +++ b/src/test/ui/issues/issue-20225.stderr @@ -6,6 +6,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | = note: expected type `extern "rust-call" fn(&Foo, (&'a T,))` found type `extern "rust-call" fn(&Foo, (T,))` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:12:3 @@ -15,6 +17,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | = note: expected type `extern "rust-call" fn(&mut Foo, (&'a T,))` found type `extern "rust-call" fn(&mut Foo, (T,))` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:20:3 @@ -24,6 +28,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | = note: expected type `extern "rust-call" fn(Foo, (&'a T,))` found type `extern "rust-call" fn(Foo, (T,))` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 762816c5a9..72a8fe4283 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -9,6 +9,9 @@ LL | struct NoData; error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:8:1 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / impl Foo for T where NoData: Foo { LL | | LL | | fn answer(self) { @@ -146,15 +149,13 @@ LL | | } = note: required because of the requirements on the impl of `Foo` for `NoData>>` = note: required because of the requirements on the impl of `Foo` for `NoData>` = note: required because of the requirements on the impl of `Foo` for `NoData` -note: required by `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:10:3 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / fn answer(self) { LL | | LL | | let val: NoData = NoData; @@ -289,11 +290,6 @@ LL | | } = note: required because of the requirements on the impl of `Foo` for `NoData>>` = note: required because of the requirements on the impl of `Foo` for `NoData>` = note: required because of the requirements on the impl of `Foo` for `NoData` -note: required by `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-21160.rs b/src/test/ui/issues/issue-21160.rs index 46733566cf..dfb3974335 100644 --- a/src/test/ui/issues/issue-21160.rs +++ b/src/test/ui/issues/issue-21160.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences struct Bar; impl Bar { diff --git a/src/test/ui/issues/issue-21160.stderr b/src/test/ui/issues/issue-21160.stderr index e32343e968..9f88fa2fad 100644 --- a/src/test/ui/issues/issue-21160.stderr +++ b/src/test/ui/issues/issue-21160.stderr @@ -1,10 +1,13 @@ error[E0277]: the trait bound `Bar: std::hash::Hash` is not satisfied - --> $DIR/issue-21160.rs:8:12 + --> $DIR/issue-21160.rs:10:12 | LL | struct Foo(Bar); | ^^^ the trait `std::hash::Hash` is not implemented for `Bar` + | + ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL | - = note: required by `std::hash::Hash::hash` +LL | fn hash(&self, state: &mut H); + | - required by this bound in `std::hash::Hash::hash` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2149.stderr b/src/test/ui/issues/issue-2149.stderr index 1df32aafa7..8ce2ba0333 100644 --- a/src/test/ui/issues/issue-2149.stderr +++ b/src/test/ui/issues/issue-2149.stderr @@ -10,7 +10,7 @@ error[E0599]: no method named `bind` found for type `[&str; 1]` in the current s --> $DIR/issue-2149.rs:13:12 | LL | ["hi"].bind(|x| [x] ); - | ^^^^ + | ^^^^ method not found in `[&str; 1]` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `bind`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-2150.stderr b/src/test/ui/issues/issue-2150.stderr index 59000f3dd5..6e102ecb62 100644 --- a/src/test/ui/issues/issue-2150.stderr +++ b/src/test/ui/issues/issue-2150.stderr @@ -1,14 +1,17 @@ error: unreachable statement --> $DIR/issue-2150.rs:8:5 | +LL | panic!(); + | --------- any code following this expression is unreachable LL | for x in &v { i += 1; } - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/issue-2150.rs:1:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index 8e4e09b13a..4e5cace525 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `to_string` found for type `*const u8` in the curr --> $DIR/issue-21596.rs:4:22 | LL | println!("{}", z.to_string()); - | ^^^^^^^^^ + | ^^^^^^^^^ method not found in `*const u8` | = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr index 87c048fdf4..2bede9120c 100644 --- a/src/test/ui/issues/issue-21763.stderr +++ b/src/test/ui/issues/issue-21763.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/issue-21763.rs:9:5 | +LL | fn foo() {} + | --- ---- required by this bound in `foo` +... LL | foo::, Rc<()>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | @@ -9,11 +12,6 @@ LL | foo::, Rc<()>>>(); = note: required because of the requirements on the impl of `std::marker::Send` for `hashbrown::raw::RawTable<(std::rc::Rc<()>, std::rc::Rc<()>)>` = note: required because it appears within the type `hashbrown::map::HashMap, std::rc::Rc<()>, std::collections::hash_map::RandomState>` = note: required because it appears within the type `std::collections::HashMap, std::rc::Rc<()>>` -note: required by `foo` - --> $DIR/issue-21763.rs:6:1 - | -LL | fn foo() {} - | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr index 3111d3a474..20d02a9031 100644 --- a/src/test/ui/issues/issue-21837.stderr +++ b/src/test/ui/issues/issue-21837.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: Bound` is not satisfied --> $DIR/issue-21837.rs:8:9 | +LL | pub struct Foo(T); + | ---------------------------- required by `Foo` +... LL | impl Trait2 for Foo {} | ^^^^^^ the trait `Bound` is not implemented for `T` | = help: consider adding a `where T: Bound` bound -note: required by `Foo` - --> $DIR/issue-21837.rs:2:1 - | -LL | pub struct Foo(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index 85e59d7bed..a6cce7846e 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,6 +1,9 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-21974.rs:10:1 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) LL | | where &'a T : Foo, LL | | &'b T : Foo @@ -9,12 +12,6 @@ LL | | x.foo(); LL | | y.foo(); LL | | } | |_^ - | -note: required by `Foo` - --> $DIR/issue-21974.rs:6:1 - | -LL | trait Foo { - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr index d169fdfe2d..c3b419fe93 100644 --- a/src/test/ui/issues/issue-23589.stderr +++ b/src/test/ui/issues/issue-23589.stderr @@ -1,11 +1,11 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-23589.rs:2:15 + --> $DIR/issue-23589.rs:2:12 | LL | let v: Vec(&str) = vec!['1', '2']; - | ^^^^^^ - | | - | only `Fn` traits may use parentheses - | help: use angle brackets instead: `<&str>` + | ^^^^^^^^^ + | | + | only `Fn` traits may use parentheses + | help: use angle brackets instead: `Vec<&str>` error[E0308]: mismatched types --> $DIR/issue-23589.rs:2:29 diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr index ac64067db1..c2fe6d92b9 100644 --- a/src/test/ui/issues/issue-23966.stderr +++ b/src/test/ui/issues/issue-23966.stderr @@ -1,8 +1,8 @@ error[E0277]: expected a `std::ops::FnMut<(_, char)>` closure, found `()` - --> $DIR/issue-23966.rs:2:16 + --> $DIR/issue-23966.rs:2:32 | LL | "".chars().fold(|_, _| (), ()); - | ^^^^ expected an `FnMut<(_, char)>` closure, found `()` + | ^^ expected an `FnMut<(_, char)>` closure, found `()` | = help: the trait `std::ops::FnMut<(_, char)>` is not implemented for `()` diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr index 8e04c0ddcc..9658f6980b 100644 --- a/src/test/ui/issues/issue-24204.stderr +++ b/src/test/ui/issues/issue-24204.stderr @@ -1,16 +1,15 @@ error[E0271]: type mismatch resolving `<::A as MultiDispatch>::O == T` --> $DIR/issue-24204.rs:14:1 | +LL | trait Trait: Sized { + | ------------------ required by `Trait` +... LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter | = note: expected type `<::A as MultiDispatch>::O` found type `T` -note: required by `Trait` - --> $DIR/issue-24204.rs:7:1 - | -LL | trait Trait: Sized { - | ^^^^^^^^^^^^^^^^^^ + = note: you might be missing a type parameter or trait bound error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/issues/issue-24267-flow-exit.rs index a1b4d75d40..d6809ee414 100644 --- a/src/test/ui/issues/issue-24267-flow-exit.rs +++ b/src/test/ui/issues/issue-24267-flow-exit.rs @@ -9,11 +9,11 @@ pub fn main() { pub fn foo1() { let x: i32; loop { x = break; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` } pub fn foo2() { let x: i32; for _ in 0..10 { x = continue; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/issues/issue-24267-flow-exit.stderr index 3b4f27621f..4eb41ca24d 100644 --- a/src/test/ui/issues/issue-24267-flow-exit.stderr +++ b/src/test/ui/issues/issue-24267-flow-exit.stderr @@ -1,14 +1,14 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/issue-24267-flow-exit.rs:12:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/issue-24267-flow-exit.rs:18:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 4c6ac0180a..7ff019a30a 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>` --> $DIR/issue-24424.rs:4:1 | +LL | trait Trait0<'l0> {} + | ----------------- required by `Trait0` +LL | LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by `Trait0` - --> $DIR/issue-24424.rs:2:1 - | -LL | trait Trait0<'l0> {} - | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs index 48362d0bb6..7253d35ed2 100644 --- a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -5,8 +5,6 @@ // See further discussion on rust-lang/rust#24535, // rust-lang/rfcs#1006, and rust-lang/rfcs#107 -#![feature(bind_by_move_pattern_guards)] - fn main() { rust_issue_24535(); rfcs_issue_1006_1(); diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr index 435ab13eda..0a13a2bc33 100644 --- a/src/test/ui/issues/issue-25076.stderr +++ b/src/test/ui/issues/issue-25076.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `(): InOut<_>` is not satisfied - --> $DIR/issue-25076.rs:10:5 - | -LL | do_fold(bot(), ()); - | ^^^^^^^ the trait `InOut<_>` is not implemented for `()` - | -note: required by `do_fold` - --> $DIR/issue-25076.rs:5:1 + --> $DIR/issue-25076.rs:10:20 | LL | fn do_fold>(init: B, f: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------- --------------- required by this bound in `do_fold` +... +LL | do_fold(bot(), ()); + | ^^ the trait `InOut<_>` is not implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25385.stderr b/src/test/ui/issues/issue-25385.stderr index e170a9d383..ab4db7e42a 100644 --- a/src/test/ui/issues/issue-25385.stderr +++ b/src/test/ui/issues/issue-25385.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for type `i32` in the current scope --> $DIR/issue-25385.rs:2:23 | LL | ($e:expr) => { $e.foo() } - | ^^^ + | ^^^ method not found in `i32` ... LL | foo!(a); | -------- in this macro invocation @@ -11,7 +11,7 @@ error[E0599]: no method named `foo` found for type `i32` in the current scope --> $DIR/issue-25385.rs:10:15 | LL | foo!(1i32.foo()); - | ^^^ + | ^^^ method not found in `i32` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs index 17e7c1f977..c60e06c3ce 100644 --- a/src/test/ui/issues/issue-26448-2.rs +++ b/src/test/ui/issues/issue-26448-2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass pub struct Bar { items: Vec<&'static str>, diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs index e57352e57f..d48022c09f 100644 --- a/src/test/ui/issues/issue-26448-3.rs +++ b/src/test/ui/issues/issue-26448-3.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass pub struct Item { _inner: &'static str, diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs index 1ffb7f6fd4..82d8b9e9ed 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs @@ -5,8 +5,6 @@ // reject it. But I want to make sure that we continue to reject it // (under NLL) even when that conservaive check goes away. -#![feature(bind_by_move_pattern_guards)] - fn main() { let mut b = &mut true; match b { diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr index a8eb78b7cc..f0264b56ea 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard - --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25 + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ^^ - mutable borrow occurs due to use of `r` in closure diff --git a/src/test/ui/issues/issue-27697.rs b/src/test/ui/issues/issue-27697.rs index 83070012f5..12af8a8e87 100644 --- a/src/test/ui/issues/issue-27697.rs +++ b/src/test/ui/issues/issue-27697.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass use std::ops::Deref; diff --git a/src/test/ui/issues/issue-28098.rs b/src/test/ui/issues/issue-28098.rs index c4addaccef..62a90d90d1 100644 --- a/src/test/ui/issues/issue-28098.rs +++ b/src/test/ui/issues/issue-28098.rs @@ -1,6 +1,7 @@ fn main() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator @@ -16,6 +17,7 @@ pub fn other() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index 30f7819b96..8b724b9331 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -1,14 +1,14 @@ error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:2:13 + --> $DIR/issue-28098.rs:2:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^ `()` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `()` = note: required by `std::iter::Iterator::next` error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:5:14 + --> $DIR/issue-28098.rs:6:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -17,34 +17,42 @@ LL | for _ in false {} = note: required by `std::iter::IntoIterator::into_iter` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:8:13 + --> $DIR/issue-28098.rs:9:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^ `()` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `()` = note: required by `std::iter::Iterator::next` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:17:13 + --> $DIR/issue-28098.rs:2:13 | LL | let _ = Iterator::next(&mut ()); | ^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:18:28 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^ `()` is not an iterator + | + = help: the trait `std::iter::Iterator` is not implemented for `()` = note: required by `std::iter::Iterator::next` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:13 + --> $DIR/issue-28098.rs:22:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^ `()` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `()` = note: required by `std::iter::Iterator::next` error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:23:14 + --> $DIR/issue-28098.rs:25:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -52,6 +60,14 @@ LL | for _ in false {} = help: the trait `std::iter::Iterator` is not implemented for `bool` = note: required by `std::iter::IntoIterator::into_iter` -error: aborting due to 6 previous errors +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:18:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `std::iter::Iterator` is not implemented for `()` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-28105.rs b/src/test/ui/issues/issue-28105.rs index 6026cbb82a..1e8d2d6ccf 100644 --- a/src/test/ui/issues/issue-28105.rs +++ b/src/test/ui/issues/issue-28105.rs @@ -1,8 +1,8 @@ // Make sure that a continue span actually contains the keyword. fn main() { - continue //~ ERROR `continue` outside of loop + continue //~ ERROR `continue` outside of a loop ; - break //~ ERROR `break` outside of loop + break //~ ERROR `break` outside of a loop ; } diff --git a/src/test/ui/issues/issue-28105.stderr b/src/test/ui/issues/issue-28105.stderr index 0e1b90e652..42ed838d7c 100644 --- a/src/test/ui/issues/issue-28105.stderr +++ b/src/test/ui/issues/issue-28105.stderr @@ -1,14 +1,14 @@ -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/issue-28105.rs:4:5 | LL | continue - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-28105.rs:6:5 | LL | break - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index 4c1dfb8501..c9ede03003 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -5,7 +5,7 @@ LL | struct C { | -------- method `clone` not found for this ... LL | let _d = c.clone(); - | ^^^^^ + | ^^^^^ method not found in `C` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr index 3beb728978..c537c6118f 100644 --- a/src/test/ui/issues/issue-29124.stderr +++ b/src/test/ui/issues/issue-29124.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in th --> $DIR/issue-29124.rs:15:15 | LL | Obj::func.x(); - | ^ + | ^ method not found in `fn() -> Ret {Obj::func}` | = note: Obj::func is a function, perhaps you wish to call it @@ -10,7 +10,7 @@ error[E0599]: no method named `x` found for type `fn() -> Ret {func}` in the cur --> $DIR/issue-29124.rs:17:10 | LL | func.x(); - | ^ + | ^ method not found in `fn() -> Ret {func}` | = note: func is a function, perhaps you wish to call it diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index 3b42186b25..0dc9b0c9e1 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `S5<_>: Foo` --> $DIR/issue-29147.rs:21:13 | +LL | trait Foo { fn xxx(&self); } + | -------------- required by `Foo::xxx` +... LL | let _ = >::xxx; | ^^^^^^^^^^^^ - | -note: required by `Foo::xxx` - --> $DIR/issue-29147.rs:10:13 - | -LL | trait Foo { fn xxx(&self); } - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29181.stderr b/src/test/ui/issues/issue-29181.stderr index 0920142815..250b158ab8 100644 --- a/src/test/ui/issues/issue-29181.stderr +++ b/src/test/ui/issues/issue-29181.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `homura` found for type `{integer}` in the current --> $DIR/issue-29181.rs:6:7 | LL | 0.homura(); - | ^^^^^^ + | ^^^^^^ method not found in `{integer}` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index 58e28c1a9d..a6ccc4835f 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -6,6 +6,8 @@ LL | xx = y; | = note: expected type `T` found type `U` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 3ca8338882..6d03b78109 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -11,7 +11,7 @@ error[E0599]: no method named `collect` found for type `std::iter::Cloned $DIR/issue-31173.rs:14:10 | LL | .collect(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` | = note: the method `collect` exists but the following trait bounds were not satisfied: `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator` diff --git a/src/test/ui/issues/issue-31561.rs b/src/test/ui/issues/issue-31561.rs index 87b19fe5ea..813b2409cc 100644 --- a/src/test/ui/issues/issue-31561.rs +++ b/src/test/ui/issues/issue-31561.rs @@ -6,5 +6,5 @@ enum Thing { fn main() { let Thing::Foo(y) = Thing::Foo(1); - //~^ ERROR refutable pattern in local binding: `Bar` not covered + //~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered } diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr index 246137aeee..9ec26b024b 100644 --- a/src/test/ui/issues/issue-31561.stderr +++ b/src/test/ui/issues/issue-31561.stderr @@ -1,15 +1,17 @@ -error[E0005]: refutable pattern in local binding: `Bar` not covered +error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered --> $DIR/issue-31561.rs:8:9 | LL | / enum Thing { LL | | Foo(u8), LL | | Bar, + | | --- not covered LL | | Baz + | | --- not covered LL | | } | |_- `Thing` defined here ... LL | let Thing::Foo(y) = Thing::Foo(1); - | ^^^^^^^^^^^^^ pattern `Bar` not covered + | ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31776.rs b/src/test/ui/issues/issue-31776.rs index c0d2c91e57..c86623ce28 100644 --- a/src/test/ui/issues/issue-31776.rs +++ b/src/test/ui/issues/issue-31776.rs @@ -13,7 +13,7 @@ mod m { } } -// ------------------------------------------------------ +// Scenario 1 pub trait Tr { type A; @@ -28,7 +28,7 @@ fn f() { } } -// ------------------------------------------------------ +// Scenario 2 trait Tr1 { type A; @@ -49,8 +49,6 @@ mod m1 { } } -// ------------------------------------------------------ - fn main() { S.s(); // Privacy error, unless `fn s` is pub let a = S2.pull().field; // Privacy error unless `field: u8` is pub diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr index f8c418b25a..b56fa949ac 100644 --- a/src/test/ui/issues/issue-32004.stderr +++ b/src/test/ui/issues/issue-32004.stderr @@ -3,8 +3,9 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo | LL | Foo::Bar => {} | ^^^^^--- - | | - | help: a unit variant with a similar name exists: `Baz` + | | | + | | help: a unit variant with a similar name exists: `Baz` + | did you mean `Foo::Bar ( /* fields */ )`? error[E0532]: expected tuple struct/variant, found unit struct `S` --> $DIR/issue-32004.rs:16:9 diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 6256dc0c55..9c11a02923 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -8,6 +8,8 @@ LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} | = note: expected type `>::Out` found type `()` + = note: consider constraining the associated type `>::Out` to `()` or calling a method that returns `>::Out` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs index fad7bf55cf..f52e092312 100644 --- a/src/test/ui/issues/issue-32655.rs +++ b/src/test/ui/issues/issue-32655.rs @@ -1,6 +1,6 @@ macro_rules! foo ( () => ( - #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope + #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope struct T; ); ); @@ -12,7 +12,7 @@ macro_rules! bar ( foo!(); bar!( - #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope + #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope struct S; ); diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index e13bed0fbf..ca085b25c2 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -1,4 +1,4 @@ -error: cannot find attribute macro `derive_Clone` in this scope +error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:3:11 | LL | #[derive_Clone] @@ -7,7 +7,7 @@ LL | #[derive_Clone] LL | foo!(); | ------- in this macro invocation -error: cannot find attribute macro `derive_Clone` in this scope +error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:15:7 | LL | #[derive_Clone] diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index a31a74a07f..e3564e8670 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -12,14 +12,11 @@ LL | size_of_copy::(); error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 | +LL | fn size_of_copy() -> usize { mem::size_of::() } + | ------------ ---- required by this bound in `size_of_copy` +... LL | size_of_copy::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc` - | -note: required by `size_of_copy` - --> $DIR/issue-32963.rs:5:1 - | -LL | fn size_of_copy() -> usize { mem::size_of::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-32995-2.stderr b/src/test/ui/issues/issue-32995-2.stderr index 4a580b09bf..976e3064db 100644 --- a/src/test/ui/issues/issue-32995-2.stderr +++ b/src/test/ui/issues/issue-32995-2.stderr @@ -1,27 +1,27 @@ error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995-2.rs:4:28 + --> $DIR/issue-32995-2.rs:4:22 | LL | { fn f() {} } - | ^^ + | ^^^^^^^^ | = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995-2.rs:8:35 + --> $DIR/issue-32995-2.rs:8:29 | LL | { fn f() -> impl ::std::marker()::Send { } } - | ^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995-2.rs:16:19 + --> $DIR/issue-32995-2.rs:16:13 | LL | impl ::std::marker()::Copy for X {} - | ^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 diff --git a/src/test/ui/issues/issue-32995.stderr b/src/test/ui/issues/issue-32995.stderr index 59d93ece06..724e82a59d 100644 --- a/src/test/ui/issues/issue-32995.stderr +++ b/src/test/ui/issues/issue-32995.stderr @@ -1,63 +1,63 @@ error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:4:17 + --> $DIR/issue-32995.rs:4:12 | LL | let x: usize() = 1; - | ^^ + | ^^^^^^^ | = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:8:24 + --> $DIR/issue-32995.rs:8:19 | LL | let b: ::std::boxed()::Box<_> = Box::new(1); - | ^^ + | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:12:25 + --> $DIR/issue-32995.rs:12:20 | LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); - | ^^ + | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:16:36 + --> $DIR/issue-32995.rs:16:25 | LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); - | ^^ + | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:20:35 + --> $DIR/issue-32995.rs:20:29 | LL | let o : Box = Box::new(1); - | ^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:24:41 + --> $DIR/issue-32995.rs:24:35 | LL | let o : Box = Box::new(1); - | ^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:30:14 + --> $DIR/issue-32995.rs:30:13 | LL | let d : X() = Default::default(); - | ^^ + | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/issues/issue-33575.rs new file mode 100644 index 0000000000..09c499452a --- /dev/null +++ b/src/test/ui/issues/issue-33575.rs @@ -0,0 +1,4 @@ +fn main() { + let baz = ().foo(); //~ ERROR no method named `foo` found for type `()` in the current scope + ::from_str(&baz); // No complaints about `str` being unsized +} diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/issues/issue-33575.stderr new file mode 100644 index 0000000000..e6b74d262c --- /dev/null +++ b/src/test/ui/issues/issue-33575.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `foo` found for type `()` in the current scope + --> $DIR/issue-33575.rs:2:18 + | +LL | let baz = ().foo(); + | ^^^ method not found in `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 7f89caf92a..8d52e08374 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -45,7 +45,7 @@ error[E0599]: no method named `iter` found for type `()` in the current scope --> $DIR/issue-34334.rs:9:36 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | ^^^^ + | ^^^^ method not found in `()` error: aborting due to 7 previous errors diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index 99d99db93f..b381203856 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `is_subset` found for type `&std::collections::Has --> $DIR/issue-35677.rs:4:10 | LL | this.is_subset(other) - | ^^^^^^^^^ + | ^^^^^^^^^ method not found in `&std::collections::HashSet` | = note: the method `is_subset` exists but the following trait bounds were not satisfied: `T : std::cmp::Eq` diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs index 87092689a2..1102f3c464 100644 --- a/src/test/ui/issues/issue-36617.rs +++ b/src/test/ui/issues/issue-36617.rs @@ -1,3 +1,4 @@ #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions + //~| ERROR cannot determine resolution for the derive macro `Copy` fn main() {} diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr index 296fec46d8..b5db98f306 100644 --- a/src/test/ui/issues/issue-36617.stderr +++ b/src/test/ui/issues/issue-36617.stderr @@ -4,5 +4,13 @@ error: `derive` may only be applied to structs, enums and unions LL | #![derive(Copy)] | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]` -error: aborting due to previous error +error: cannot determine resolution for the derive macro `Copy` + --> $DIR/issue-36617.rs:1:11 + | +LL | #![derive(Copy)] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-36836.rs b/src/test/ui/issues/issue-36836.rs new file mode 100644 index 0000000000..99c5621315 --- /dev/null +++ b/src/test/ui/issues/issue-36836.rs @@ -0,0 +1,15 @@ +// Previously, in addition to the real cause of the problem as seen below, +// the compiler would tell the user: +// +// ``` +// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or +// predicates +// ``` +// +// With this test, we check that only the relevant error is emitted. + +trait Foo {} + +impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope + +fn main() {} diff --git a/src/test/ui/issues/issue-36836.stderr b/src/test/ui/issues/issue-36836.stderr new file mode 100644 index 0000000000..418194fac9 --- /dev/null +++ b/src/test/ui/issues/issue-36836.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-36836.rs:13:17 + | +LL | impl Foo for Bar {} + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-38591.rs b/src/test/ui/issues/issue-38591.rs index 7aa71f8b9e..2f594b48e6 100644 --- a/src/test/ui/issues/issue-38591.rs +++ b/src/test/ui/issues/issue-38591.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass struct S { t : T, diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr index 108c969cda..66680b9936 100644 --- a/src/test/ui/issues/issue-39175.stderr +++ b/src/test/ui/issues/issue-39175.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `exec` found for type `&mut std::process::Command` --> $DIR/issue-39175.rs:15:39 | LL | Command::new("echo").arg("hello").exec(); - | ^^^^ + | ^^^^ method not found in `&mut std::process::Command` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-39687.stderr b/src/test/ui/issues/issue-39687.stderr index 886de1d6fa..b1b3041ea0 100644 --- a/src/test/ui/issues/issue-39687.stderr +++ b/src/test/ui/issues/issue-39687.stderr @@ -1,8 +1,8 @@ error[E0229]: associated type bindings are not allowed here - --> $DIR/issue-39687.rs:4:16 + --> $DIR/issue-39687.rs:4:14 | LL | ::call; - | ^^ associated type not allowed here + | ^^^^ associated type not allowed here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index e4f1587064..f15f771fa9 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -1,17 +1,15 @@ error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` --> $DIR/issue-39970.rs:19:5 | +LL | fn visit() {} + | ---------- required by `Visit::visit` +... LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ expected &(), found () | = note: expected type `&()` found type `()` = note: required because of the requirements on the impl of `Visit` for `()` -note: required by `Visit::visit` - --> $DIR/issue-39970.rs:6:5 - | -LL | fn visit() {} - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr index 96b411bfb1..3fe47e249f 100644 --- a/src/test/ui/issues/issue-40827.stderr +++ b/src/test/ui/issues/issue-40827.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/issue-40827.rs:14:5 | +LL | fn f(_: T) {} + | - ---- required by this bound in `f` +... LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `std::rc::Rc` cannot be sent between threads safely | @@ -8,15 +11,13 @@ LL | f(Foo(Arc::new(Bar::B(None)))); = note: required because it appears within the type `Bar` = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc` = note: required because it appears within the type `Foo` -note: required by `f` - --> $DIR/issue-40827.rs:11:1 - | -LL | fn f(_: T) {} - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely --> $DIR/issue-40827.rs:14:5 | +LL | fn f(_: T) {} + | - ---- required by this bound in `f` +... LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `std::rc::Rc` cannot be shared between threads safely | @@ -24,11 +25,6 @@ LL | f(Foo(Arc::new(Bar::B(None)))); = note: required because it appears within the type `Bar` = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc` = note: required because it appears within the type `Foo` -note: required by `f` - --> $DIR/issue-40827.rs:11:1 - | -LL | fn f(_: T) {} - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-40845.rs b/src/test/ui/issues/issue-40845.rs index c9102f4417..a4ede6adfa 100644 --- a/src/test/ui/issues/issue-40845.rs +++ b/src/test/ui/issues/issue-40845.rs @@ -1,6 +1,6 @@ -trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope +trait T { m!(); } //~ ERROR cannot find macro `m` in this scope struct S; -impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope +impl S { m!(); } //~ ERROR cannot find macro `m` in this scope fn main() {} diff --git a/src/test/ui/issues/issue-40845.stderr b/src/test/ui/issues/issue-40845.stderr index a8be38ebf0..2744330a4e 100644 --- a/src/test/ui/issues/issue-40845.stderr +++ b/src/test/ui/issues/issue-40845.stderr @@ -1,10 +1,10 @@ -error: cannot find macro `m!` in this scope +error: cannot find macro `m` in this scope --> $DIR/issue-40845.rs:4:10 | LL | impl S { m!(); } | ^ -error: cannot find macro `m!` in this scope +error: cannot find macro `m` in this scope --> $DIR/issue-40845.rs:1:11 | LL | trait T { m!(); } diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index 359a234024..0e1d55c339 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -5,7 +5,7 @@ LL | pub struct Iterate { | ------------------------ method `iter` not found for this ... LL | println!("{:?}", a.iter().take(10).collect::>()); - | ^^^^ + | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index 6d3e8b5ba2..c729c05ff2 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -1,14 +1,14 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-43162.rs:3:5 | LL | break true; - | ^^^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^^^ cannot `break` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-43162.rs:7:5 | LL | break {}; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop error[E0308]: mismatched types --> $DIR/issue-43162.rs:1:13 diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr index e364650da4..33c3f18650 100644 --- a/src/test/ui/issues/issue-43189.stderr +++ b/src/test/ui/issues/issue-43189.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `a` found for type `()` in the current scope --> $DIR/issue-43189.rs:10:8 | LL | ().a(); - | ^ + | ^ method not found in `()` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index b5674105f7..2c57b8585d 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -1,41 +1,27 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-43623.rs:14:5 | +LL | pub fn break_me(f: F) + | -------- +LL | where T: for<'b> Trait<'b>, +LL | F: for<'b> FnMut(>::Assoc) { + | -------------------------------------- required by this bound in `break_me` LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | | expected signature of `for<'b> fn(>::Assoc) -> _` | found signature of `fn(_) -> _` - | -note: required by `break_me` - --> $DIR/issue-43623.rs:11:1 - | -LL | / pub fn break_me(f: F) -LL | | where T: for<'b> Trait<'b>, -LL | | F: for<'b> FnMut(>::Assoc) { -LL | | break_me::; -LL | | -LL | | -LL | | } - | |_^ error[E0271]: type mismatch resolving `for<'b> >::Assoc,)>>::Output == ()` --> $DIR/issue-43623.rs:14:5 | +LL | pub fn break_me(f: F) + | -------- +LL | where T: for<'b> Trait<'b>, +LL | F: for<'b> FnMut(>::Assoc) { + | ------------------------------ required by this bound in `break_me` LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime - | -note: required by `break_me` - --> $DIR/issue-43623.rs:11:1 - | -LL | / pub fn break_me(f: F) -LL | | where T: for<'b> Trait<'b>, -LL | | F: for<'b> FnMut(>::Assoc) { -LL | | break_me::; -LL | | -LL | | -LL | | } - | |_^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-43806.rs b/src/test/ui/issues/issue-43806.rs index cbfbfa35af..8c8cccfb2b 100644 --- a/src/test/ui/issues/issue-43806.rs +++ b/src/test/ui/issues/issue-43806.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![deny(unused_results)] diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr deleted file mode 100644 index df8e804c87..0000000000 --- a/src/test/ui/issues/issue-44415.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0` - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ - | -note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... - --> $DIR/issue-44415.rs:6:26 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing layout of `Foo`... - = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ - = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle -note: cycle used when processing `Foo` - --> $DIR/issue-44415.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs index 2d9111e9b3..8b1343b132 100644 --- a/src/test/ui/issues/issue-46101.rs +++ b/src/test/ui/issues/issue-46101.rs @@ -2,3 +2,5 @@ trait Foo {} #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro struct S; + +fn main() {} diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr index 772d4bfeb3..9c88d3b87c 100644 --- a/src/test/ui/issues/issue-46101.stderr +++ b/src/test/ui/issues/issue-46101.stderr @@ -4,11 +4,6 @@ error[E0433]: failed to resolve: partially resolved path in a derive macro LL | #[derive(Foo::Anything)] | ^^^^^^^^^^^^^ partially resolved path in a derive macro -error[E0601]: `main` function not found in crate `issue_46101` - | - = note: consider adding a `main` function to `$DIR/issue-46101.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0433, E0601. -For more information about an error, try `rustc --explain E0433`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/issues/issue-47706-trait.stderr b/src/test/ui/issues/issue-47706-trait.stderr index 5f8f856424..8a6a199148 100644 --- a/src/test/ui/issues/issue-47706-trait.stderr +++ b/src/test/ui/issues/issue-47706-trait.stderr @@ -1,10 +1,10 @@ error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments - --> $DIR/issue-47706-trait.rs:3:20 + --> $DIR/issue-47706-trait.rs:3:24 | LL | fn f(&self, _: ()) { | ------------------ takes 2 distinct arguments LL | None::<()>.map(Self::f); - | ^^^ expected function that takes a single 0-tuple as argument + | ^^^^^^^ expected function that takes a single 0-tuple as argument error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr index fa2e00cde4..6cde937346 100644 --- a/src/test/ui/issues/issue-47706.stderr +++ b/src/test/ui/issues/issue-47706.stderr @@ -1,30 +1,26 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments - --> $DIR/issue-47706.rs:11:18 + --> $DIR/issue-47706.rs:11:22 | LL | pub fn new(foo: Option, _: ()) -> Foo { | ------------------------------------------ takes 2 arguments ... LL | self.foo.map(Foo::new) - | ^^^ expected function that takes 1 argument + | ^^^^^^^^ expected function that takes 1 argument error[E0593]: function is expected to take 0 arguments, but it takes 1 argument - --> $DIR/issue-47706.rs:27:5 + --> $DIR/issue-47706.rs:27:9 | LL | Bar(i32), | -------- takes 1 argument ... +LL | fn foo(f: F) + | --- +LL | where +LL | F: Fn(), + | ---- required by this bound in `foo` +... LL | foo(Qux::Bar); - | ^^^ expected function that takes 0 arguments - | -note: required by `foo` - --> $DIR/issue-47706.rs:20:1 - | -LL | / fn foo(f: F) -LL | | where -LL | | F: Fn(), -LL | | { -LL | | } - | |_^ + | ^^^^^^^^ expected function that takes 0 arguments error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-48132.rs b/src/test/ui/issues/issue-48132.rs index ea325ea695..f564aefe78 100644 --- a/src/test/ui/issues/issue-48132.rs +++ b/src/test/ui/issues/issue-48132.rs @@ -3,6 +3,8 @@ // run-pass +#![allow(dead_code)] + struct Inner { iterator: I, item: V, diff --git a/src/test/ui/issues/issue-48179.rs b/src/test/ui/issues/issue-48179.rs index 90e9858d74..f81203dc41 100644 --- a/src/test/ui/issues/issue-48179.rs +++ b/src/test/ui/issues/issue-48179.rs @@ -1,7 +1,7 @@ // Regression test for #48132. This was failing due to problems around // the projection caching and dropck type enumeration. -// run-pass +// check-pass pub struct Container { value: Option, diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr index 99a9bf9903..84c10d8fbc 100644 --- a/src/test/ui/issues/issue-48728.stderr +++ b/src/test/ui/issues/issue-48728.stderr @@ -7,7 +7,7 @@ LL | #[derive(Clone)] LL | impl Clone for Node<[T]> { | ------------------------------------------- first implementation here | - = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions error: aborting due to previous error diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs index a5f05d2824..b7a541dd66 100644 --- a/src/test/ui/issues/issue-49040.rs +++ b/src/test/ui/issues/issue-49040.rs @@ -1,2 +1,3 @@ #![allow(unused_variables)]; //~ ERROR expected item, found `;` +//~^ ERROR `main` function fn foo() {} diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr index de78b8d3c1..4134d6aa54 100644 --- a/src/test/ui/issues/issue-49040.stderr +++ b/src/test/ui/issues/issue-49040.stderr @@ -5,8 +5,12 @@ LL | #![allow(unused_variables)]; | ^ help: remove this semicolon error[E0601]: `main` function not found in crate `issue_49040` + --> $DIR/issue-49040.rs:1:1 | - = note: consider adding a `main` function to `$DIR/issue-49040.rs` +LL | / #![allow(unused_variables)]; +LL | | +LL | | fn foo() {} + | |__^ consider adding a `main` function to `$DIR/issue-49040.rs` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs index 38074d5b05..752bb345b7 100644 --- a/src/test/ui/issues/issue-49074.rs +++ b/src/test/ui/issues/issue-49074.rs @@ -1,7 +1,7 @@ // Check that unknown attribute error is shown even if there are unresolved macros. #[marco_use] // typo -//~^ ERROR cannot find attribute macro `marco_use` in this scope +//~^ ERROR cannot find attribute `marco_use` in this scope mod foo { macro_rules! bar { () => (); @@ -9,5 +9,5 @@ mod foo { } fn main() { - bar!(); //~ ERROR cannot find macro `bar!` in this scope + bar!(); //~ ERROR cannot find macro `bar` in this scope } diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr index c557255ab5..bbfeb4ea94 100644 --- a/src/test/ui/issues/issue-49074.stderr +++ b/src/test/ui/issues/issue-49074.stderr @@ -1,10 +1,4 @@ -error: cannot find attribute macro `marco_use` in this scope - --> $DIR/issue-49074.rs:3:3 - | -LL | #[marco_use] // typo - | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` - -error: cannot find macro `bar!` in this scope +error: cannot find macro `bar` in this scope --> $DIR/issue-49074.rs:12:4 | LL | bar!(); @@ -12,5 +6,11 @@ LL | bar!(); | = help: have you added the `#[macro_use]` on the module/import? +error: cannot find attribute `marco_use` in this scope + --> $DIR/issue-49074.rs:3:3 + | +LL | #[marco_use] // typo + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` + error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-49934-errors.rs b/src/test/ui/issues/issue-49934-errors.rs new file mode 100644 index 0000000000..6fa5f01ffd --- /dev/null +++ b/src/test/ui/issues/issue-49934-errors.rs @@ -0,0 +1,13 @@ +fn foo<#[derive(Debug)] T>() { +//~^ ERROR `derive` may only be applied to structs, enums and unions +//~| ERROR expected an inert attribute, found a derive macro + match 0 { + #[derive(Debug)] + //~^ ERROR `derive` may only be applied to structs, enums and unions + //~| ERROR expected an inert attribute, found a derive macro + _ => (), + } +} + +fn main() { +} diff --git a/src/test/ui/issues/issue-49934-errors.stderr b/src/test/ui/issues/issue-49934-errors.stderr new file mode 100644 index 0000000000..8778d88d0e --- /dev/null +++ b/src/test/ui/issues/issue-49934-errors.stderr @@ -0,0 +1,26 @@ +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934-errors.rs:1:8 + | +LL | fn foo<#[derive(Debug)] T>() { + | ^^^^^^^^^^^^^^^^ + +error: expected an inert attribute, found a derive macro + --> $DIR/issue-49934-errors.rs:1:17 + | +LL | fn foo<#[derive(Debug)] T>() { + | ^^^^^ + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934-errors.rs:5:9 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: expected an inert attribute, found a derive macro + --> $DIR/issue-49934-errors.rs:5:18 + | +LL | #[derive(Debug)] + | ^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs index e75381afae..262f4931d4 100644 --- a/src/test/ui/issues/issue-49934.rs +++ b/src/test/ui/issues/issue-49934.rs @@ -1,15 +1,8 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(stmt_expr_attributes)] #![warn(unused_attributes)] //~ NOTE lint level defined here -fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute - match 0 { - #[derive(Debug)] //~ WARN unused attribute - _ => (), - } -} - fn main() { // fold_stmt (Item) #[allow(dead_code)] diff --git a/src/test/ui/issues/issue-49934.stderr b/src/test/ui/issues/issue-49934.stderr index 6ca751a47c..dbec379e3c 100644 --- a/src/test/ui/issues/issue-49934.stderr +++ b/src/test/ui/issues/issue-49934.stderr @@ -1,5 +1,5 @@ warning: `#[derive]` does nothing on macro invocations - --> $DIR/issue-49934.rs:20:5 + --> $DIR/issue-49934.rs:13:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ @@ -7,10 +7,10 @@ LL | #[derive(Debug)] = note: this may become a hard error in a future release warning: unused attribute - --> $DIR/issue-49934.rs:6:8 + --> $DIR/issue-49934.rs:19:5 | -LL | fn foo<#[derive(Debug)] T>() { - | ^^^^^^^^^^^^^^^^ +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/issue-49934.rs:4:9 @@ -19,31 +19,19 @@ LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-49934.rs:8:9 - | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-49934.rs:26:5 - | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-49934.rs:30:5 + --> $DIR/issue-49934.rs:23:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-49934.rs:34:13 + --> $DIR/issue-49934.rs:27:13 | LL | let _ = #[derive(Debug)] "Hello, world!"; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-49934.rs:39:9 + --> $DIR/issue-49934.rs:32:9 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 2c3a18be67..29fd15fb39 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut` found for type `std::option::Option --> $DIR/option-as_deref_mut.rs:4:33 | LL | let _result = &mut Some(42).as_deref_mut(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: `{integer} : std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50301.rs b/src/test/ui/issues/issue-50301.rs new file mode 100644 index 0000000000..47ee3e7ad7 --- /dev/null +++ b/src/test/ui/issues/issue-50301.rs @@ -0,0 +1,31 @@ +// Tests that HRTBs are correctly accepted -- https://github.com/rust-lang/rust/issues/50301 +// check-pass +trait Trait +where + for<'a> &'a Self::IntoIter: IntoIterator, +{ + type IntoIter; + fn get(&self) -> Self::IntoIter; +} + +struct Impl(Vec); + +impl Trait for Impl { + type IntoIter = ImplIntoIter; + fn get(&self) -> Self::IntoIter { + ImplIntoIter(self.0.clone()) + } +} + +struct ImplIntoIter(Vec); + +impl<'a> IntoIterator for &'a ImplIntoIter { + type Item = ::Item; + type IntoIter = std::iter::Cloned>; + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter().cloned() + } +} + +fn main() { +} diff --git a/src/test/ui/issues/issue-50415.rs b/src/test/ui/issues/issue-50415.rs index 20c7be772f..151b9fe442 100644 --- a/src/test/ui/issues/issue-50415.rs +++ b/src/test/ui/issues/issue-50415.rs @@ -1,11 +1,9 @@ // run-pass fn main() { - // -------- Simplified test case -------- - + // Simplified test case let _ = || 0..=1; - // -------- Original test case -------- - + // Original test case let full_length = 1024; let range = { // do some stuff, omit here diff --git a/src/test/ui/issues/issue-50576.stderr b/src/test/ui/issues/issue-50576.stderr index 95619eeed9..9fea141108 100644 --- a/src/test/ui/issues/issue-50576.stderr +++ b/src/test/ui/issues/issue-50576.stderr @@ -4,17 +4,17 @@ error[E0426]: use of undeclared label `'L` LL | |bool: [u8; break 'L]| 0; | ^^ undeclared label `'L` -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50576.rs:2:17 | LL | |bool: [u8; break 'L]| 0; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50576.rs:5:16 | LL | Vec::<[u8; break]>::new(); - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs index bf892a8daa..f0f1dc6c28 100644 --- a/src/test/ui/issues/issue-50577.rs +++ b/src/test/ui/issues/issue-50577.rs @@ -2,6 +2,5 @@ fn main() { enum Foo { Drop = assert_eq!(1, 1) //~^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } } diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr index 413c8c5c80..0c3ba2ea4f 100644 --- a/src/test/ui/issues/issue-50577.stderr +++ b/src/test/ui/issues/issue-50577.stderr @@ -1,13 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-50577.rs:3:16 - | -LL | Drop = assert_eq!(1, 1) - | ^^^^^^^^^^^^^^^^ expected isize, found () - | - = note: expected type `isize` - found type `()` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - error[E0317]: if may be missing an else clause --> $DIR/issue-50577.rs:3:16 | @@ -23,7 +13,6 @@ LL | Drop = assert_eq!(1, 1) = help: consider adding an `else` block that evaluates to the expected type = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0317. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/issues/issue-50581.stderr b/src/test/ui/issues/issue-50581.stderr index 01a5f9b3c4..35d6fc49ce 100644 --- a/src/test/ui/issues/issue-50581.stderr +++ b/src/test/ui/issues/issue-50581.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50581.rs:2:14 | LL | |_: [u8; break]| (); - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to previous error diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs index 616fd09907..5857a08159 100644 --- a/src/test/ui/issues/issue-5067.rs +++ b/src/test/ui/issues/issue-5067.rs @@ -54,7 +54,7 @@ macro_rules! foo { //~^ ERROR repetition matches empty token tree } -// --- Original Issue --- // +// Original Issue macro_rules! make_vec { (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); @@ -65,7 +65,7 @@ fn main() { let _ = make_vec![a 1, a 2, a 3]; } -// --- Minified Issue --- // +// Minified Issue macro_rules! m { ( $()* ) => {}; diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr index c98f78c51e..02475ea97e 100644 --- a/src/test/ui/issues/issue-50781.stderr +++ b/src/test/ui/issues/issue-50781.stderr @@ -1,8 +1,8 @@ error: the trait `X` cannot be made into an object - --> $DIR/issue-50781.rs:6:5 + --> $DIR/issue-50781.rs:6:8 | LL | fn foo(&self) where Self: Trait; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/issue-50781.rs:1:9 diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 97214fbdc5..5034e6d538 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for type `&dyn Foo` in the current sco --> $DIR/issue-5153.rs:10:27 | LL | (&5isize as &dyn Foo).foo(); - | ^^^ + | ^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `foo`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs index 54eff22893..13b914c033 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/issues/issue-52060.rs @@ -3,6 +3,5 @@ static A: &'static [u32] = &[1]; static B: [u32; 1] = [0; A.len()]; //~^ ERROR [E0013] -//~| ERROR `core::slice::::len` is not yet stable as a const fn fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 7c3f769554..2f90f7f9e0 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -4,14 +4,6 @@ error[E0013]: constants cannot refer to statics, use a constant instead LL | static B: [u32; 1] = [0; A.len()]; | ^ -error: `core::slice::::len` is not yet stable as a const fn - --> $DIR/issue-52060.rs:4:26 - | -LL | static B: [u32; 1] = [0; A.len()]; - | ^^^^^^^ - | - = help: add `#![feature(const_slice_len)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0013`. diff --git a/src/test/ui/issues/issue-52533.stderr b/src/test/ui/issues/issue-52533.stderr index 1ed740c421..5865480020 100644 --- a/src/test/ui/issues/issue-52533.stderr +++ b/src/test/ui/issues/issue-52533.stderr @@ -17,3 +17,4 @@ LL | foo(|a, b| b) error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr index 082ac91edb..3830ad4b1e 100644 --- a/src/test/ui/issues/issue-54062.stderr +++ b/src/test/ui/issues/issue-54062.stderr @@ -8,7 +8,7 @@ error[E0599]: no method named `unwrap` found for type `std::sys_common::mutex::M --> $DIR/issue-54062.rs:10:37 | LL | let _ = test.comps.inner.lock().unwrap(); - | ^^^^^^ + | ^^^^^^ method not found in `std::sys_common::mutex::MutexGuard<'_>` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 98637611b7..3ed2779164 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -1,38 +1,58 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` - = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` +LL | / trait Foo<'x, T> { +LL | | fn foo(self) -> &'x T; +LL | | } + | |_- trait `Foo` defined here +... +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Foo<'x, T> { +LL | | fn foo(self) -> &'x T; +LL | | } + | |_- trait `Foo` defined here +... +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0` - = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` + = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Foo<'x, T> { +LL | | fn foo(self) -> &'x T; +LL | | } + | |_- trait `Foo` defined here +... +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0` - = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` + = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Foo<'x, T> { +LL | | fn foo(self) -> &'x T; +LL | | } + | |_- trait `Foo` defined here +... +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0` - = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` + = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index c6d0805f3a..1b3f57ba18 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -1,11 +1,14 @@ error: implementation of `Deserialize` is not general enough --> $DIR/issue-54302.rs:13:5 | +LL | trait Deserialize<'de> {} + | ------------------------- trait `Deserialize` defined here +... LL | assert_deserialize_owned::<&'static str>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | - = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` - = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr index f25e18e5d9..f44c842187 100644 --- a/src/test/ui/issues/issue-55731.stderr +++ b/src/test/ui/issues/issue-55731.stderr @@ -1,11 +1,16 @@ error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/issue-55731.rs:48:5 | -LL | multi(Map { - | ^^^^^ +LL | / trait DistributedIteratorMulti { +LL | | type Item; +LL | | } + | |_- trait `DistributedIteratorMulti` defined here +... +LL | multi(Map { + | ^^^^^ implementation of `DistributedIteratorMulti` is not general enough | - = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0` - = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` + = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs index b6454e578e..b1dac26d65 100644 --- a/src/test/ui/issues/issue-56806.rs +++ b/src/test/ui/issues/issue-56806.rs @@ -1,7 +1,6 @@ pub trait Trait { fn dyn_instead_of_self(self: Box); - //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> + //~^ ERROR invalid `self` parameter type } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr index fae6a26720..a4f9aadcfe 100644 --- a/src/test/ui/issues/issue-56806.stderr +++ b/src/test/ui/issues/issue-56806.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> +error[E0307]: invalid `self` parameter type: std::boxed::Box<(dyn Trait + 'static)> --> $DIR/issue-56806.rs:2:34 | LL | fn dyn_instead_of_self(self: Box); | ^^^^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 1d2ff7669c..c4000c8a9d 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for type `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | LL | a.f(); - | ^ + | ^ method not found in `fn(&u8)` | = note: a is a function, perhaps you wish to call it = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/issues/issue-60057.rs b/src/test/ui/issues/issue-60057.rs index 3027d01c53..b52343adae 100644 --- a/src/test/ui/issues/issue-60057.rs +++ b/src/test/ui/issues/issue-60057.rs @@ -15,3 +15,5 @@ impl A { } } } + +fn main() {} diff --git a/src/test/ui/issues/issue-60057.stderr b/src/test/ui/issues/issue-60057.stderr index 6b967204ce..4d915fcd9f 100644 --- a/src/test/ui/issues/issue-60057.stderr +++ b/src/test/ui/issues/issue-60057.stderr @@ -10,11 +10,6 @@ error[E0425]: cannot find value `banana` in this scope LL | banana: banana | ^^^^^^ help: you might have meant to use the available field: `self.banana` -error[E0601]: `main` function not found in crate `issue_60057` - | - = note: consider adding a `main` function to `$DIR/issue-60057.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0425, E0601. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index a79b1959dc..69c1d85e4e 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -1,33 +1,29 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:14:5 + --> $DIR/issue-60283.rs:14:13 | +LL | pub fn foo(_: T, _: F) + | --- +LL | where T: for<'a> Trait<'a>, +LL | F: for<'a> FnMut(>::Item) {} + | ------------------------------------- required by this bound in `foo` +... LL | foo((), drop) - | ^^^ - | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(_) -> _` - | -note: required by `foo` - --> $DIR/issue-60283.rs:9:1 - | -LL | / pub fn foo(_: T, _: F) -LL | | where T: for<'a> Trait<'a>, -LL | | F: for<'a> FnMut(>::Item) {} - | |_________________________________________________^ + | ^^^^ + | | + | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(_) -> _` error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` --> $DIR/issue-60283.rs:14:5 | +LL | pub fn foo(_: T, _: F) + | --- +LL | where T: for<'a> Trait<'a>, +LL | F: for<'a> FnMut(>::Item) {} + | ----------------------------- required by this bound in `foo` +... LL | foo((), drop) | ^^^ expected bound lifetime parameter 'a, found concrete lifetime - | -note: required by `foo` - --> $DIR/issue-60283.rs:9:1 - | -LL | / pub fn foo(_: T, _: F) -LL | | where T: for<'a> Trait<'a>, -LL | | F: for<'a> FnMut(>::Item) {} - | |_________________________________________________^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs index 8fc09c89f7..de7d6a0d80 100644 --- a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs +++ b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs @@ -5,7 +5,7 @@ // aux-build:xcrate-issue-61711-b.rs // compile-flags:--extern xcrate_issue_61711_b -// run-pass +// build-pass fn f(_: F) { } fn main() { } diff --git a/src/test/ui/issues/issue-63983.rs b/src/test/ui/issues/issue-63983.rs new file mode 100644 index 0000000000..c1c79091fc --- /dev/null +++ b/src/test/ui/issues/issue-63983.rs @@ -0,0 +1,15 @@ +enum MyEnum { + Tuple(i32), + Struct{ s: i32 }, +} + +fn foo(en: MyEnum) { + match en { + MyEnum::Tuple => "", + //~^ ERROR expected unit struct/variant or constant, found tuple variant `MyEnum::Tuple` + MyEnum::Struct => "", + //~^ ERROR expected unit struct/variant or constant, found struct variant `MyEnum::Struct` + }; +} + +fn main() {} diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr new file mode 100644 index 0000000000..67acd1d57c --- /dev/null +++ b/src/test/ui/issues/issue-63983.stderr @@ -0,0 +1,15 @@ +error[E0532]: expected unit struct/variant or constant, found tuple variant `MyEnum::Tuple` + --> $DIR/issue-63983.rs:8:9 + | +LL | MyEnum::Tuple => "", + | ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple ( /* fields */ )`? + +error[E0532]: expected unit struct/variant or constant, found struct variant `MyEnum::Struct` + --> $DIR/issue-63983.rs:10:9 + | +LL | MyEnum::Struct => "", + | ^^^^^^^^^^^^^^ did you mean `MyEnum::Struct { /* fields */ }`? + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/issues/issue-64430.rs b/src/test/ui/issues/issue-64430.rs new file mode 100644 index 0000000000..0bc66e06e6 --- /dev/null +++ b/src/test/ui/issues/issue-64430.rs @@ -0,0 +1,14 @@ +// compile-flags:-C panic=abort + +#![no_std] +pub struct Foo; + +fn main() { + Foo.bar() + //~^ ERROR E0599 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop{} +} diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr new file mode 100644 index 0000000000..f1b2de8d8b --- /dev/null +++ b/src/test/ui/issues/issue-64430.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `bar` found for type `Foo` in the current scope + --> $DIR/issue-64430.rs:7:9 + | +LL | pub struct Foo; + | --------------- method `bar` not found for this +... +LL | Foo.bar() + | ^^^ method not found in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-64559.rs b/src/test/ui/issues/issue-64559.rs new file mode 100644 index 0000000000..71e054b5d9 --- /dev/null +++ b/src/test/ui/issues/issue-64559.rs @@ -0,0 +1,6 @@ +fn main() { + let orig = vec![true]; + for _val in orig {} + let _closure = || orig; + //~^ ERROR use of moved value: `orig` +} diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr new file mode 100644 index 0000000000..3c685dc8d0 --- /dev/null +++ b/src/test/ui/issues/issue-64559.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `orig` + --> $DIR/issue-64559.rs:4:20 + | +LL | let orig = vec![true]; + | ---- move occurs because `orig` has type `std::vec::Vec`, which does not implement the `Copy` trait +LL | for _val in orig {} + | ---- + | | + | value moved here + | help: consider borrowing to avoid moving into the for loop: `&orig` +LL | let _closure = || orig; + | ^^ ---- use occurs due to use in closure + | | + | value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/issues/issue-64593.rs b/src/test/ui/issues/issue-64593.rs new file mode 100644 index 0000000000..9e787f638a --- /dev/null +++ b/src/test/ui/issues/issue-64593.rs @@ -0,0 +1,12 @@ +// check-pass +#![deny(improper_ctypes)] + +pub struct Error(std::num::NonZeroU32); + +extern "Rust" { + fn foo(dest: &mut [u8]) -> Result<(), Error>; +} + +fn main() { + let _ = unsafe { foo(&mut []) }; +} diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs new file mode 100644 index 0000000000..b74ee1b0c6 --- /dev/null +++ b/src/test/ui/issues/issue-65611.rs @@ -0,0 +1,63 @@ +use std::mem::MaybeUninit; +use std::ops::Deref; + +pub unsafe trait Array { + /// The array’s element type + type Item; + #[doc(hidden)] + /// The smallest index type that indexes the array. + type Index: Index; + #[doc(hidden)] + fn as_ptr(&self) -> *const Self::Item; + #[doc(hidden)] + fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[doc(hidden)] + fn capacity() -> usize; +} + +pub trait Index : PartialEq + Copy { + fn to_usize(self) -> usize; + fn from(usize) -> Self; +} + +impl Index for usize { + fn to_usize(self) -> usize { self } + fn from(val: usize) -> Self { + val + } +} + +unsafe impl Array for [T; 1] { + type Item = T; + type Index = usize; + fn as_ptr(&self) -> *const T { self as *const _ as *const _ } + fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} + fn capacity() -> usize { 1 } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + panic!() + } +} + +pub struct ArrayVec { + xs: MaybeUninit, + len: usize, +} + +impl ArrayVec { + pub fn new() -> ArrayVec { + panic!() + } +} + +fn main() { + let mut buffer = ArrayVec::new(); + let x = buffer.last().unwrap().0.clone(); + //~^ ERROR type annotations needed + //~| ERROR no field `0` on type `&_` + buffer.reverse(); +} diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr new file mode 100644 index 0000000000..cb441c13c6 --- /dev/null +++ b/src/test/ui/issues/issue-65611.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> $DIR/issue-65611.rs:59:20 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^^^^ cannot infer type for `T` + | + = note: type must be known at this point + +error[E0609]: no field `0` on type `&_` + --> $DIR/issue-65611.rs:59:36 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-6919.rs b/src/test/ui/issues/issue-6919.rs index 11aed12087..6f1e1f9770 100644 --- a/src/test/ui/issues/issue-6919.rs +++ b/src/test/ui/issues/issue-6919.rs @@ -4,7 +4,6 @@ // pretty-expanded FIXME #23616 -#![crate_id="issue-6919"] extern crate issue6919_3; pub fn main() { diff --git a/src/test/ui/issues/issue-7246.stderr b/src/test/ui/issues/issue-7246.stderr index e049295e91..a11ce1654c 100644 --- a/src/test/ui/issues/issue-7246.stderr +++ b/src/test/ui/issues/issue-7246.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/issue-7246.rs:7:5 | +LL | return; + | ------ any code following this expression is unreachable LL | if *ptr::null() {}; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/issue-7246.rs:1:9 diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 611d280f77..4637814b27 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,3 +1,5 @@ +// compile-flags: -O + #![deny(const_err)] use std::{isize, i8, i16, i32, i64}; diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 31b1da4f80..7e5a22e651 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -1,245 +1,245 @@ error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:7:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-8460-const.rs:1:9 + --> $DIR/issue-8460-const.rs:3:9 | LL | #![deny(const_err)] | ^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:7:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:12:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:12:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:13:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:13:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:18:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:18:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:24:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:24:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:27:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:27:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:30:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:30:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:33:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:33:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:57:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:57:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:60:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:60:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:63:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:63:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:66:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:66:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs new file mode 100644 index 0000000000..c3f53e3298 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.rs @@ -0,0 +1,59 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +use std::{isize, i8, i16, i32, i64}; +use std::thread; + +fn main() { + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime +} diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr new file mode 100644 index 0000000000..b688ec1367 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.stderr @@ -0,0 +1,188 @@ +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:9:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-8460-const2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:11:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:34:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:36:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:38:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 30 previous errors + diff --git a/src/test/ui/iterators/bound.stderr b/src/test/ui/iterators/bound.stderr index 14057387c4..92a91ff4cb 100644 --- a/src/test/ui/iterators/bound.stderr +++ b/src/test/ui/iterators/bound.stderr @@ -1,16 +1,13 @@ error[E0277]: `u8` is not an iterator --> $DIR/bound.rs:2:10 | +LL | struct S(I); + | ------------------------- required by `S` LL | struct T(S); | ^^^^^ `u8` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` -note: required by `S` - --> $DIR/bound.rs:1:1 - | -LL | struct S(I); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs new file mode 100644 index 0000000000..d661203575 --- /dev/null +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -0,0 +1,16 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// ignore-wasm32-bare compiled with panic=abort by default +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + assert_eq!((0..MAX).by_ref().count(), MAX); + + let r = panic::catch_unwind(|| { + (0..=MAX).by_ref().count() + }); + assert!(r.is_err()); +} diff --git a/src/test/ui/iterators/iter-count-overflow-ndebug.rs b/src/test/ui/iterators/iter-count-overflow-ndebug.rs new file mode 100644 index 0000000000..b755bb554f --- /dev/null +++ b/src/test/ui/iterators/iter-count-overflow-ndebug.rs @@ -0,0 +1,11 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + assert_eq!((0..MAX).by_ref().count(), MAX); + assert_eq!((0..=MAX).by_ref().count(), 0); +} diff --git a/src/test/ui/iterators/iter-map-fold-type-length.rs b/src/test/ui/iterators/iter-map-fold-type-length.rs new file mode 100644 index 0000000000..8ce4fcd873 --- /dev/null +++ b/src/test/ui/iterators/iter-map-fold-type-length.rs @@ -0,0 +1,38 @@ +// run-pass +//! Check that type lengths don't explode with `Map` folds. +//! +//! The normal limit is a million, and this test used to exceed 1.5 million, but +//! now we can survive an even tighter limit. Still seems excessive though... +#![type_length_limit = "256000"] + +// Custom wrapper so Iterator methods aren't specialized. +struct Iter(I); + +impl Iterator for Iter +where + I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +fn main() { + let c = Iter(0i32..10) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .count(); + assert_eq!(c, 10); +} diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs new file mode 100644 index 0000000000..f1eded3170 --- /dev/null +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -0,0 +1,22 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// ignore-wasm32-bare compiled with panic=abort by default +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + let n = MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX)); + + let r = panic::catch_unwind(|| { + (0..).by_ref().position(|i| i > n) + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + (0..=n + 1).by_ref().position(|_| false) + }); + assert!(r.is_err()); +} diff --git a/src/test/ui/iterators/iter-position-overflow-ndebug.rs b/src/test/ui/iterators/iter-position-overflow-ndebug.rs new file mode 100644 index 0000000000..368f9c0c02 --- /dev/null +++ b/src/test/ui/iterators/iter-position-overflow-ndebug.rs @@ -0,0 +1,13 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + let n = MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX)); + assert_eq!((0..).by_ref().position(|i| i > n), Some(0)); + assert_eq!((0..=n + 1).by_ref().position(|_| false), None); +} diff --git a/src/test/ui/json-multiple.polonius.stderr b/src/test/ui/json-multiple.polonius.stderr new file mode 100644 index 0000000000..0e4d442f29 --- /dev/null +++ b/src/test/ui/json-multiple.polonius.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json-multiple.polonius/libjson_multiple.rlib","emit":"link"} diff --git a/src/test/ui/json-options.polonius.stderr b/src/test/ui/json-options.polonius.stderr new file mode 100644 index 0000000000..e21f6f85d1 --- /dev/null +++ b/src/test/ui/json-options.polonius.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json-options.polonius/libjson_options.rlib","emit":"link"} diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr index dffbdb7e48..0a1fb56771 100644 --- a/src/test/ui/json-short.stderr +++ b/src/test/ui/json-short.stderr @@ -11,9 +11,9 @@ fn main() { If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ -"},"level":"error","spans":[],"children":[{"message":"consider adding a `main` function to `$DIR/json-short.rs`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0601]: `main` function not found in crate `json_short` +"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":76,"byte_end":76,"line_start":2,"line_end":2,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:2:63: error[E0601]: `main` function not found in crate `json_short` "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error "} -{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`. +{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`. "} diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs index f9b6bad7c2..8a420f7203 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs @@ -1,3 +1,3 @@ fn main() { - let extern = 0; //~ ERROR expected pattern, found keyword `extern` + let extern = 0; //~ ERROR expected identifier, found keyword `extern` } diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr index d7b9ad2abe..73ac113f1b 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `extern` +error: expected identifier, found keyword `extern` --> $DIR/keyword-extern-as-identifier-pat.rs:2:9 | LL | let extern = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#extern = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index 929a807656..3ca9cf7e97 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -1,138 +1,107 @@ error[E0277]: the trait bound `&'static mut isize: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:27:5 + --> $DIR/kindck-copy.rs:27:19 | +LL | fn assert_copy() { } + | ----------- ---- required by this bound in `assert_copy` +... LL | assert_copy::<&'static mut isize>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'static mut isize` + | ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'static mut isize` | = help: the following implementations were found: -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `&'a mut isize: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:28:5 + --> $DIR/kindck-copy.rs:28:19 | +LL | fn assert_copy() { } + | ----------- ---- required by this bound in `assert_copy` +... LL | assert_copy::<&'a mut isize>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut isize` + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut isize` | = help: the following implementations were found: -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:31:5 - | -LL | assert_copy::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:31:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::>(); + | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:32:5 - | -LL | assert_copy::(); - | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:32:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::(); + | ^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` error[E0277]: the trait bound `std::vec::Vec: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:33:5 - | -LL | assert_copy:: >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:33:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy:: >(); + | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec` error[E0277]: the trait bound `std::boxed::Box<&'a mut isize>: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:34:5 - | -LL | assert_copy::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<&'a mut isize>` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:34:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::>(); + | ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<&'a mut isize>` error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:42:5 | +LL | fn assert_copy() { } + | ----------- ---- required by this bound in `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:43:5 | +LL | fn assert_copy() { } + | ----------- ---- required by this bound in `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `&'a mut (dyn Dummy + std::marker::Send + 'a): std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:46:5 - | -LL | assert_copy::<&'a mut (dyn Dummy + Send)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:46:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::<&'a mut (dyn Dummy + Send)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)` error[E0277]: the trait bound `MyNoncopyStruct: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:64:5 - | -LL | assert_copy::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MyNoncopyStruct` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:64:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::(); + | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MyNoncopyStruct` error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied - --> $DIR/kindck-copy.rs:67:5 - | -LL | assert_copy::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 + --> $DIR/kindck-copy.rs:67:19 | LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------- ---- required by this bound in `assert_copy` +... +LL | assert_copy::>(); + | ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` error: aborting due to 11 previous errors diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr index bd971c9037..8e98911324 100644 --- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied - --> $DIR/kindck-impl-type-params-2.rs:13:5 + --> $DIR/kindck-impl-type-params-2.rs:13:16 | +LL | fn take_param(foo: &T) { } + | ---------- --- required by this bound in `take_param` +... LL | take_param(&x); - | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` + | ^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` | = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` -note: required by `take_param` - --> $DIR/kindck-impl-type-params-2.rs:9:1 - | -LL | fn take_param(foo: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr index 1e719e2608..27901d0692 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:18:5 + --> $DIR/kindck-inherited-copy-bound.rs:18:16 | +LL | fn take_param(foo: &T) { } + | ---------- --- required by this bound in `take_param` +... LL | take_param(&x); - | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` + | ^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` | = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` -note: required by `take_param` - --> $DIR/kindck-inherited-copy-bound.rs:14:1 - | -LL | fn take_param(foo: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/kindck-inherited-copy-bound.rs:24:19 diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index 2aacd2741d..40b67f8fe8 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -1,16 +1,14 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/kindck-nonsendable-1.rs:9:5 | +LL | fn bar(_: F) { } + | --- ---- required by this bound in `bar` +... LL | bar(move|| foo(x)); | ^^^ `std::rc::Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]` -note: required by `bar` - --> $DIR/kindck-nonsendable-1.rs:5:1 - | -LL | fn bar(_: F) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-send-object.stderr b/src/test/ui/kindck/kindck-send-object.stderr index c9aadd85a5..8708537f86 100644 --- a/src/test/ui/kindck/kindck-send-object.stderr +++ b/src/test/ui/kindck/kindck-send-object.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely --> $DIR/kindck-send-object.rs:12:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::<&'static (dyn Dummy + 'static)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)` -note: required by `assert_send` - --> $DIR/kindck-send-object.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Dummy` cannot be sent between threads safely --> $DIR/kindck-send-object.rs:17:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn Dummy` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `assert_send` - --> $DIR/kindck-send-object.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-send-object1.nll.stderr b/src/test/ui/kindck/kindck-send-object1.nll.stderr index 998dc90456..f882e06ed2 100644 --- a/src/test/ui/kindck/kindck-send-object1.nll.stderr +++ b/src/test/ui/kindck/kindck-send-object1.nll.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely --> $DIR/kindck-send-object1.rs:10:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>` = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-send-object1.stderr b/src/test/ui/kindck/kindck-send-object1.stderr index 757b41ab6c..436b92637a 100644 --- a/src/test/ui/kindck/kindck-send-object1.stderr +++ b/src/test/ui/kindck/kindck-send-object1.stderr @@ -1,16 +1,14 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely --> $DIR/kindck-send-object1.rs:10:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0477]: the type `&'a (dyn Dummy + std::marker::Sync + 'a)` does not fulfill the required lifetime --> $DIR/kindck-send-object1.rs:14:5 @@ -23,17 +21,15 @@ LL | assert_send::<&'a (dyn Dummy + Sync)>(); error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>` = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/kindck/kindck-send-object2.stderr b/src/test/ui/kindck/kindck-send-object2.stderr index c1c9db9da8..6cb82edf26 100644 --- a/src/test/ui/kindck/kindck-send-object2.stderr +++ b/src/test/ui/kindck/kindck-send-object2.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely --> $DIR/kindck-send-object2.rs:7:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::<&'static dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)` -note: required by `assert_send` - --> $DIR/kindck-send-object2.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Dummy` cannot be sent between threads safely --> $DIR/kindck-send-object2.rs:12:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn Dummy` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `assert_send` - --> $DIR/kindck-send-object2.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-send-owned.stderr b/src/test/ui/kindck/kindck-send-owned.stderr index 75c757dc54..c740349542 100644 --- a/src/test/ui/kindck/kindck-send-owned.stderr +++ b/src/test/ui/kindck/kindck-send-owned.stderr @@ -1,17 +1,15 @@ error[E0277]: `*mut u8` cannot be sent between threads safely --> $DIR/kindck-send-owned.rs:12:5 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `*mut u8` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<*mut u8>` = note: required because it appears within the type `std::boxed::Box<*mut u8>` -note: required by `assert_send` - --> $DIR/kindck-send-owned.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-send-unsafe.stderr b/src/test/ui/kindck/kindck-send-unsafe.stderr index 2fbb07a0df..05ed51d0f1 100644 --- a/src/test/ui/kindck/kindck-send-unsafe.stderr +++ b/src/test/ui/kindck/kindck-send-unsafe.stderr @@ -1,15 +1,13 @@ error[E0277]: `*mut &'a isize` cannot be sent between threads safely - --> $DIR/kindck-send-unsafe.rs:6:5 + --> $DIR/kindck-send-unsafe.rs:6:19 | +LL | fn assert_send() { } + | ----------- ---- required by this bound in `assert_send` +... LL | assert_send::<*mut &'a isize>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely + | ^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `*mut &'a isize` -note: required by `assert_send` - --> $DIR/kindck-send-unsafe.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lang-item-missing-generator.rs b/src/test/ui/lang-item-missing-generator.rs new file mode 100644 index 0000000000..0c32954292 --- /dev/null +++ b/src/test/ui/lang-item-missing-generator.rs @@ -0,0 +1,19 @@ +// error-pattern: requires `generator` lang_item +#![feature(no_core, lang_items, unboxed_closures)] +#![no_core] + +#[lang = "sized"] pub trait Sized { } + +#[lang = "fn_once"] +#[rustc_paren_sugar] +pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +pub fn abc() -> impl FnOnce(f32) { + |_| {} +} + +fn main() {} diff --git a/src/test/ui/lang-item-missing-generator.stderr b/src/test/ui/lang-item-missing-generator.stderr new file mode 100644 index 0000000000..fa13bf0b12 --- /dev/null +++ b/src/test/ui/lang-item-missing-generator.stderr @@ -0,0 +1,8 @@ +error: requires `generator` lang_item + --> $DIR/lang-item-missing-generator.rs:15:17 + | +LL | pub fn abc() -> impl FnOnce(f32) { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs index 9b905d4883..5a71d6efed 100644 --- a/src/test/ui/lifetime-before-type-params.rs +++ b/src/test/ui/lifetime-before-type-params.rs @@ -7,3 +7,5 @@ fn third() {} //~^ ERROR lifetime parameters must be declared prior to type parameters fn fourth<'a, T, 'b, U, 'c, V>() {} //~^ ERROR lifetime parameters must be declared prior to type parameters + +fn main() {} diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr index ffc6784baf..76d7d0f024 100644 --- a/src/test/ui/lifetime-before-type-params.stderr +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -22,10 +22,5 @@ error: lifetime parameters must be declared prior to type parameters LL | fn fourth<'a, T, 'b, U, 'c, V>() {} | --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` -error[E0601]: `main` function not found in crate `lifetime_before_type_params` - | - = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index 2370084b07..ea0d0ccbc5 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -6,7 +6,7 @@ trait Future { use std::error::Error; fn foo() -> impl Future> { -//~^ ERROR missing lifetime +//~^ ERROR not satisfied Ok(()) } diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 06b317ce95..228582d000 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,11 +1,11 @@ -error[E0106]: missing lifetime specifier - --> $DIR/lifetime-elision-return-type-trait.rs:8:44 +error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisfied + --> $DIR/lifetime-elision-return-type-trait.rs:8:13 | LL | fn foo() -> impl Future> { - | ^^^^^^^^^ help: consider giving it a 'static lifetime: `dyn Error + 'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>` | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + = note: the return type of a function must have a statically known size error: aborting due to previous error -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr index 779e2eb8b9..2ed4d6d440 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr @@ -12,11 +12,11 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-3.rs:2:5 | LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | - - let's call the lifetime of this reference `'1` + | - - let's call the lifetime of this reference `'3` | | - | let's call the lifetime of this reference `'2` + | let's call the lifetime of this reference `'4` LL | z.push((x,y)); - | ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4` error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/empty-lint-attributes.rs b/src/test/ui/lint/empty-lint-attributes.rs index 1f0a9538d8..9a0ec25332 100644 --- a/src/test/ui/lint/empty-lint-attributes.rs +++ b/src/test/ui/lint/empty-lint-attributes.rs @@ -1,6 +1,6 @@ #![feature(lint_reasons)] -// run-pass +// check-pass // Empty (and reason-only) lint attributes are legal—although we may want to // lint them in the future (Issue #55112). diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index eda9e2cdfa..7dcbdd0863 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,25 +1,77 @@ -// build-pass (FIXME(62277): could be check-pass?) +#![feature(box_patterns, stmt_expr_attributes)] + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete #![allow(ellipsis_inclusive_range_patterns)] #![allow(unreachable_patterns)] #![allow(unused_variables)] -#![warn(unused_parens)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let (a) = 0; //~ ERROR unnecessary parentheses around pattern + for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + + let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. +} + +fn or_patterns_will_lint() { + if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern + if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} fn main() { match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1...2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn e @ (3...4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1...2) => {} // Ambiguous range pattern should not warn - &(1...2) => {} // Ambiguous range pattern should not warn + (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn } match &1 { @@ -28,19 +80,19 @@ fn main() { } match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1..=2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1..=2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn e @ (3..=4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1..=2) => {} // Ambiguous range pattern should not warn - &(1..=2) => {} // Ambiguous range pattern should not warn + (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn } match &1 { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 3b31219895..675dd4f07d 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -1,78 +1,160 @@ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:10:9 +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/issue-54538-unused-parens-lint.rs:3:12 | -LL | (_) => {} +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:12:9 + | +LL | let (a) = 0; | ^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/issue-54538-unused-parens-lint.rs:6:9 + --> $DIR/issue-54538-unused-parens-lint.rs:9:9 | -LL | #![warn(unused_parens)] +LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:11:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 + | +LL | for (a) in 0..1 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:14:12 + | +LL | if let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:15:15 + | +LL | while let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:16:12 + | +LL | fn foo((a): u8) {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:17:14 + | +LL | let _ = |(a): u8| 0; + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:45:12 + | +LL | if let (0 | 1) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:46:13 + | +LL | if let ((0 | 1),) = (0,) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:47:13 + | +LL | if let [(0 | 1)] = [0] {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:48:16 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:50:15 + | +LL | if let TS((0 | 1)) = TS(0) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:52:20 + | +LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:62:9 + | +LL | (_) => {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:63:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:12:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:64:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:13:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:65:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:19:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:71:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:20:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:72:10 | LL | &(_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:31:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:83:9 | LL | (_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:32:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:84:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:33:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:85:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:34:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:86:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:40:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:92:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:41:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:93:10 | LL | &(_) => {} | ^^^ help: remove these parentheses +error: aborting due to 24 previous errors + diff --git a/src/test/ui/lint/lint-attr-non-item-node.stderr b/src/test/ui/lint/lint-attr-non-item-node.stderr index 6eb72c098d..0d428c256e 100644 --- a/src/test/ui/lint/lint-attr-non-item-node.stderr +++ b/src/test/ui/lint/lint-attr-non-item-node.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/lint-attr-non-item-node.rs:7:9 | +LL | break; + | ----- any code following this expression is unreachable LL | "unreachable"; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/lint-attr-non-item-node.rs:4:12 diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs index 45eeffff7a..3898e67a07 100644 --- a/src/test/ui/lint/lint-ctypes-enum.rs +++ b/src/test/ui/lint/lint-ctypes-enum.rs @@ -1,4 +1,5 @@ #![feature(transparent_enums, transparent_unions)] +#![feature(ptr_internals)] #![deny(improper_ctypes)] #![allow(dead_code)] @@ -35,35 +36,37 @@ struct Rust(T); extern { fn zf(x: Z); - fn uf(x: U); //~ ERROR enum has no representation hint - fn bf(x: B); //~ ERROR enum has no representation hint - fn tf(x: T); //~ ERROR enum has no representation hint + fn uf(x: U); //~ ERROR `extern` block uses type `U` + fn bf(x: B); //~ ERROR `extern` block uses type `B` + fn tf(x: T); //~ ERROR `extern` block uses type `T` fn repr_c(x: ReprC); fn repr_u8(x: U8); fn repr_isize(x: Isize); fn option_ref(x: Option<&'static u8>); fn option_fn(x: Option); fn nonnull(x: Option>); + fn unique(x: Option>); + //~^ ERROR `extern` block uses type `std::option::Option>` fn nonzero_u8(x: Option); fn nonzero_u16(x: Option); fn nonzero_u32(x: Option); fn nonzero_u64(x: Option); fn nonzero_u128(x: Option); - //~^ ERROR 128-bit integers don't currently have a known stable ABI + //~^ ERROR `extern` block uses type `u128` fn nonzero_usize(x: Option); fn nonzero_i8(x: Option); fn nonzero_i16(x: Option); fn nonzero_i32(x: Option); fn nonzero_i64(x: Option); fn nonzero_i128(x: Option); - //~^ ERROR 128-bit integers don't currently have a known stable ABI + //~^ ERROR `extern` block uses type `i128` fn nonzero_isize(x: Option); fn transparent_struct(x: Option>); fn transparent_enum(x: Option>); fn transparent_union(x: Option>); - //~^ ERROR enum has no representation hint - fn repr_rust(x: Option>); //~ ERROR enum has no representation hint - fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint + //~^ ERROR `extern` block uses type + fn repr_rust(x: Option>); //~ ERROR `extern` block uses type + fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type } -pub fn main() { } +pub fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr index 2a60cd12d9..81939e6ee2 100644 --- a/src/test/ui/lint/lint-ctypes-enum.stderr +++ b/src/test/ui/lint/lint-ctypes-enum.stderr @@ -1,82 +1,101 @@ -error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:38:13 +error: `extern` block uses type `U`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:39:13 | LL | fn uf(x: U); - | ^ + | ^ not FFI-safe | note: lint level defined here - --> $DIR/lint-ctypes-enum.rs:2:9 + --> $DIR/lint-ctypes-enum.rs:3:9 | LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint note: type defined here - --> $DIR/lint-ctypes-enum.rs:8:1 + --> $DIR/lint-ctypes-enum.rs:9:1 | LL | enum U { A } | ^^^^^^^^^^^^ -error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:39:13 +error: `extern` block uses type `B`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:40:13 | LL | fn bf(x: B); - | ^ + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint note: type defined here - --> $DIR/lint-ctypes-enum.rs:9:1 + --> $DIR/lint-ctypes-enum.rs:10:1 | LL | enum B { C, D } | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:40:13 +error: `extern` block uses type `T`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:41:13 | LL | fn tf(x: T); - | ^ + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint note: type defined here - --> $DIR/lint-ctypes-enum.rs:10:1 + --> $DIR/lint-ctypes-enum.rs:11:1 | LL | enum T { E, F, G } | ^^^^^^^^^^^^^^^^^^ -error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI - --> $DIR/lint-ctypes-enum.rs:51:23 +error: `extern` block uses type `std::option::Option>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:48:17 + | +LL | fn unique(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:54:23 | LL | fn nonzero_u128(x: Option); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI - --> $DIR/lint-ctypes-enum.rs:58:23 +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:61:23 | LL | fn nonzero_i128(x: Option); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:63:28 +error: `extern` block uses type `std::option::Option>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:66:28 | LL | fn transparent_union(x: Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint -error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:65:20 +error: `extern` block uses type `std::option::Option>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:68:20 | LL | fn repr_rust(x: Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint -error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:66:20 +error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:69:20 | LL | fn no_result(x: Result<(), num::NonZeroI32>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs index a3d9b6febd..e20503a395 100644 --- a/src/test/ui/lint/lint-ctypes.rs +++ b/src/test/ui/lint/lint-ctypes.rs @@ -1,7 +1,7 @@ -#![deny(improper_ctypes)] #![feature(rustc_private)] #![allow(private_in_public)] +#![deny(improper_ctypes)] extern crate libc; @@ -54,12 +54,13 @@ extern { pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone` pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` - pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields - pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData + pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` + pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); + //~^ ERROR uses type `ZeroSizeWithPhantomData` pub fn zero_size_phantom_toplevel() - -> ::std::marker::PhantomData; //~ ERROR: composed only of PhantomData - pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific - pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific + -> ::std::marker::PhantomData; //~ ERROR uses type `std::marker::PhantomData` + pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()` + pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()` pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box` pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128` pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str` diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr index c78463beb6..e533a767b3 100644 --- a/src/test/ui/lint/lint-ctypes.stderr +++ b/src/test/ui/lint/lint-ctypes.stderr @@ -1,170 +1,201 @@ -error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes.rs:46:28 | LL | pub fn ptr_type1(size: *const Foo); - | ^^^^^^^^^^ + | ^^^^^^^^^^ not FFI-safe | note: lint level defined here - --> $DIR/lint-ctypes.rs:1:9 + --> $DIR/lint-ctypes.rs:4:9 | LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/lint-ctypes.rs:24:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes.rs:47:28 | LL | pub fn ptr_type2(size: *const Foo); - | ^^^^^^^^^^ + | ^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout note: type defined here --> $DIR/lint-ctypes.rs:24:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent +error: `extern` block uses type `[u32]`, which is not FFI-safe --> $DIR/lint-ctypes.rs:48:26 | LL | pub fn slice_type(p: &[u32]); - | ^^^^^^ + | ^^^^^^ not FFI-safe | = help: consider using a raw pointer instead + = note: slices have no C equivalent -error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent +error: `extern` block uses type `str`, which is not FFI-safe --> $DIR/lint-ctypes.rs:49:24 | LL | pub fn str_type(p: &str); - | ^^^^ + | ^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent -error: `extern` block uses type `std::boxed::Box` which is not FFI-safe: this struct has unspecified layout +error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe --> $DIR/lint-ctypes.rs:50:24 | LL | pub fn box_type(p: Box); - | ^^^^^^^^ + | ^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout -error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent +error: `extern` block uses type `char`, which is not FFI-safe --> $DIR/lint-ctypes.rs:51:25 | LL | pub fn char_type(p: char); - | ^^^^ + | ^^^^ not FFI-safe | = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent -error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI +error: `extern` block uses type `i128`, which is not FFI-safe --> $DIR/lint-ctypes.rs:52:25 | LL | pub fn i128_type(p: i128); - | ^^^^ + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI +error: `extern` block uses type `u128`, which is not FFI-safe --> $DIR/lint-ctypes.rs:53:25 | LL | pub fn u128_type(p: u128); - | ^^^^ + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent +error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe --> $DIR/lint-ctypes.rs:54:26 | LL | pub fn trait_type(p: &dyn Clone); - | ^^^^^^^^^^ + | ^^^^^^^^^^ not FFI-safe + | + = note: trait objects have no C equivalent -error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe --> $DIR/lint-ctypes.rs:55:26 | LL | pub fn tuple_type(p: (i32, i32)); - | ^^^^^^^^^^ + | ^^^^^^^^^^ not FFI-safe | = help: consider using a struct instead + = note: tuples have unspecified layout -error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe --> $DIR/lint-ctypes.rs:56:27 | LL | pub fn tuple_type2(p: I32Pair); - | ^^^^^^^ + | ^^^^^^^ not FFI-safe | = help: consider using a struct instead + = note: tuples have unspecified layout -error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields +error: `extern` block uses type `ZeroSize`, which is not FFI-safe --> $DIR/lint-ctypes.rs:57:25 | LL | pub fn zero_size(p: ZeroSize); - | ^^^^^^^^ + | ^^^^^^^^ not FFI-safe | = help: consider adding a member to this struct + = note: this struct has no fields note: type defined here --> $DIR/lint-ctypes.rs:20:1 | LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ -error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData +error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe --> $DIR/lint-ctypes.rs:58:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: type defined here + --> $DIR/lint-ctypes.rs:43:1 + | +LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `extern` block uses type `std::marker::PhantomData` which is not FFI-safe: composed only of PhantomData - --> $DIR/lint-ctypes.rs:60:12 +error: `extern` block uses type `std::marker::PhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:61:12 | LL | -> ::std::marker::PhantomData; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` -error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention - --> $DIR/lint-ctypes.rs:61:23 +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:62:23 | LL | pub fn fn_type(p: RustFn); - | ^^^^^^ + | ^^^^^^ not FFI-safe | = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention -error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention - --> $DIR/lint-ctypes.rs:62:24 +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:63:24 | LL | pub fn fn_type2(p: fn()); - | ^^^^ + | ^^^^ not FFI-safe | = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention -error: `extern` block uses type `std::boxed::Box` which is not FFI-safe: this struct has unspecified layout - --> $DIR/lint-ctypes.rs:63:28 +error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:64:28 | LL | pub fn fn_contained(p: RustBadRet); - | ^^^^^^^^^^ + | ^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout -error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI - --> $DIR/lint-ctypes.rs:64:32 +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:65:32 | LL | pub fn transparent_i128(p: TransparentI128); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent - --> $DIR/lint-ctypes.rs:65:31 +error: `extern` block uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:66:31 | LL | pub fn transparent_str(p: TransparentStr); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent -error: `extern` block uses type `std::boxed::Box` which is not FFI-safe: this struct has unspecified layout - --> $DIR/lint-ctypes.rs:66:30 +error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:67:30 | LL | pub fn transparent_fn(p: TransparentBadFn); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout error: aborting due to 20 previous errors diff --git a/src/test/ui/lint/lint-dead-code-const-and-self.rs b/src/test/ui/lint/lint-dead-code-const-and-self.rs new file mode 100644 index 0000000000..1a7b3f43cd --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-const-and-self.rs @@ -0,0 +1,35 @@ +// check-pass + +#![deny(dead_code)] + +const TLC: usize = 4; + +trait Tr { fn doit(&self); } + +impl Tr for [usize; TLC] { + fn doit(&self) { + println!("called 4"); + } +} + +struct X; +struct Y; +struct Z; + +trait Foo { + type Ty; + fn foo() -> Self::Ty; +} + +impl Foo for X { + type Ty = Z; + fn foo() -> Self::Ty { + unimplemented!() + } +} + +fn main() { + let s = [0,1,2,3]; + s.doit(); + X::foo(); +} diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs new file mode 100644 index 0000000000..15b04496ba --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs @@ -0,0 +1,6 @@ +// build-pass +#![deny(unused)] + +pub enum E {} + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs b/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs new file mode 100644 index 0000000000..834681d77e --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs @@ -0,0 +1,5 @@ +#![deny(unused)] + +enum E {} //~ ERROR enum is never used + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr b/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr new file mode 100644 index 0000000000..4e3bebfc48 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr @@ -0,0 +1,15 @@ +error: enum is never used: `E` + --> $DIR/lint-dead-code-empty-unused-enum.rs:3:1 + | +LL | enum E {} + | ^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-empty-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.rs b/src/test/ui/lint/lint-dead-code-unused-enum.rs new file mode 100644 index 0000000000..e57fac259c --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-enum.rs @@ -0,0 +1,11 @@ +#![deny(unused)] + +struct F; //~ ERROR struct is never constructed +struct B; //~ ERROR struct is never constructed + +enum E { //~ ERROR enum is never used + Foo(F), + Bar(B), +} + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.stderr b/src/test/ui/lint/lint-dead-code-unused-enum.stderr new file mode 100644 index 0000000000..ea711e7b05 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-enum.stderr @@ -0,0 +1,27 @@ +error: struct is never constructed: `F` + --> $DIR/lint-dead-code-unused-enum.rs:3:1 + | +LL | struct F; + | ^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: struct is never constructed: `B` + --> $DIR/lint-dead-code-unused-enum.rs:4:1 + | +LL | struct B; + | ^^^^^^^^^ + +error: enum is never used: `E` + --> $DIR/lint-dead-code-unused-enum.rs:6:1 + | +LL | enum E { + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs new file mode 100644 index 0000000000..3a9061340e --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs @@ -0,0 +1,14 @@ +// build-pass +#![deny(unused)] + +pub struct F; +pub struct B; + +pub enum E { + Foo(F), + Bar(B), +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.rs b/src/test/ui/lint/lint-dead-code-unused-variant.rs new file mode 100644 index 0000000000..69ab29042e --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant.rs @@ -0,0 +1,13 @@ +#![deny(unused)] + +struct F; +struct B; + +enum E { + Foo(F), + Bar(B), //~ ERROR variant is never constructed +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.stderr b/src/test/ui/lint/lint-dead-code-unused-variant.stderr new file mode 100644 index 0000000000..919996ec30 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant.stderr @@ -0,0 +1,15 @@ +error: variant is never constructed: `Bar` + --> $DIR/lint-dead-code-unused-variant.rs:8:5 + | +LL | Bar(B), + | ^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-unused-variant.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-qualification.rs b/src/test/ui/lint/lint-qualification.rs index 1b24191a11..0cace0ca03 100644 --- a/src/test/ui/lint/lint-qualification.rs +++ b/src/test/ui/lint/lint-qualification.rs @@ -1,5 +1,5 @@ #![deny(unused_qualifications)] -#[allow(deprecated)] +#![allow(deprecated)] mod foo { pub fn bar() {} diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr index 8132a66df8..62380135b3 100644 --- a/src/test/ui/lint/lint-stability-deprecated.stderr +++ b/src/test/ui/lint/lint-stability-deprecated.stderr @@ -67,14 +67,14 @@ LL | deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:57:9 | -LL | Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:59:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedStruct': text --> $DIR/lint-stability-deprecated.rs:106:17 @@ -181,14 +181,14 @@ LL | ::trait_deprecated_unstable(&foo); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:155:9 | -LL | Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:157:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedTrait': text --> $DIR/lint-stability-deprecated.rs:185:10 @@ -421,20 +421,20 @@ LL | ::trait_deprecated_unstable(&foo); warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:53:13 | -LL | foo.method_deprecated_unstable_text(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:54:9 | -LL | Foo::method_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:55:9 | -LL | ::method_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:56:13 @@ -445,8 +445,8 @@ LL | foo.trait_deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:58:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text --> $DIR/lint-stability-deprecated.rs:107:13 @@ -505,8 +505,8 @@ LL | foo.trait_deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:156:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text --> $DIR/lint-stability-deprecated.rs:173:13 diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 2957f93111..1af44ecf36 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure)] async fn baz_async( mut a: i32, diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs index a1660d2351..6850e99924 100644 --- a/src/test/ui/lint/lint-unused-variables.rs +++ b/src/test/ui/lint/lint-unused-variables.rs @@ -1,7 +1,7 @@ // compile-flags: --cfg something // edition:2018 -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure)] #![deny(unused_variables)] async fn foo_async( @@ -29,6 +29,11 @@ impl RefStruct { b: i32, //~^ ERROR unused variable: `b` ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} } trait RefTrait { fn bar( @@ -37,6 +42,11 @@ trait RefTrait { b: i32, //~^ ERROR unused variable: `b` ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} } impl RefTrait for RefStruct { fn bar( @@ -45,6 +55,11 @@ impl RefTrait for RefStruct { b: i32, //~^ ERROR unused variable: `b` ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} } fn main() { diff --git a/src/test/ui/lint/lint-unused-variables.stderr b/src/test/ui/lint/lint-unused-variables.stderr index 7ed5669e33..f8419bf506 100644 --- a/src/test/ui/lint/lint-unused-variables.stderr +++ b/src/test/ui/lint/lint-unused-variables.stderr @@ -17,19 +17,25 @@ LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `a` - --> $DIR/lint-unused-variables.rs:53:9 + --> $DIR/lint-unused-variables.rs:68:9 | LL | a: i32, | ^ help: consider prefixing with an underscore: `_a` error: unused variable: `b` - --> $DIR/lint-unused-variables.rs:59:9 + --> $DIR/lint-unused-variables.rs:74:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `b` - --> $DIR/lint-unused-variables.rs:37:9 + --> $DIR/lint-unused-variables.rs:42:9 + | +LL | b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:47:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` @@ -47,10 +53,22 @@ LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `b` - --> $DIR/lint-unused-variables.rs:45:9 + --> $DIR/lint-unused-variables.rs:34:9 + | +LL | b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:55:9 + | +LL | b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:60:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` -error: aborting due to 8 previous errors +error: aborting due to 11 previous errors diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs new file mode 100644 index 0000000000..25d5f8ec68 --- /dev/null +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +#![deny(improper_ctypes)] + +type A = impl Fn(); + +pub fn ret_closure() -> A { + || {} +} + +extern "C" { + pub fn a(_: A); + //~^ ERROR `extern` block uses type `A`, which is not FFI-safe +} + +fn main() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr new file mode 100644 index 0000000000..136d564d1a --- /dev/null +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/opaque-ty-ffi-unsafe.rs:12:17 + | +LL | pub fn a(_: A); + | ^ not FFI-safe + | +note: lint level defined here + --> $DIR/opaque-ty-ffi-unsafe.rs:3:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs new file mode 100644 index 0000000000..5a94ccd746 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type="proc-macro"] +#![crate_name="redundant_semi_proc_macro"] +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn should_preserve_spans(_attr: TokenStream, item: TokenStream) -> TokenStream { + eprintln!("{:?}", item); + item +} diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs new file mode 100644 index 0000000000..f207b23573 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -0,0 +1,19 @@ +// aux-build:redundant-semi-proc-macro-def.rs + +#![deny(redundant_semicolon)] +extern crate redundant_semi_proc_macro; +use redundant_semi_proc_macro::should_preserve_spans; + +#[should_preserve_spans] +fn span_preservation() { + let tst = 123;; //~ ERROR unnecessary trailing semicolon + match tst { + // Redundant semicolons are parsed as empty tuple exprs + // for the lint, so ensure the lint doesn't affect + // empty tuple exprs explicitly in source. + 123 => (), + _ => () + };;; //~ ERROR unnecessary trailing semicolons +} + +fn main() {} diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr new file mode 100644 index 0000000000..5f289c0914 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -0,0 +1,21 @@ +TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] +error: unnecessary trailing semicolon + --> $DIR/redundant-semi-proc-macro.rs:9:19 + | +LL | let tst = 123;; + | ^ help: remove this semicolon + | +note: lint level defined here + --> $DIR/redundant-semi-proc-macro.rs:3:9 + | +LL | #![deny(redundant_semicolon)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolons + --> $DIR/redundant-semi-proc-macro.rs:16:7 + | +LL | };;; + | ^^ help: remove these semicolons + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index d816479bbb..5cf62b8691 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -2,11 +2,13 @@ // This test checks that calling `mem::{uninitialized,zeroed}` with certain types results // in a lint. -#![feature(never_type)] +#![feature(never_type, rustc_attrs)] #![allow(deprecated)] #![deny(invalid_value)] use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; +use std::num::NonZeroU32; enum Void {} @@ -16,6 +18,11 @@ struct RefPair((&'static i32, i32)); struct Wrap { wrapped: T } enum WrapEnum { Wrapped(T) } +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + #[allow(unused)] fn generic() { unsafe { @@ -29,6 +36,7 @@ fn generic() { fn main() { unsafe { + // Things that cannot even be zero. let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized @@ -56,11 +64,28 @@ fn main() { let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - // Some types that should work just fine. + let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + + // Some more types that should work just fine. let _val: Option<&'static i32> = mem::zeroed(); let _val: Option = mem::zeroed(); let _val: MaybeUninit<&'static i32> = mem::zeroed(); - let _val: bool = mem::zeroed(); let _val: i32 = mem::zeroed(); } } diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 1b15fc2152..a36a32a39a 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:22:32 + --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:23:32 + --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:25:38 + --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:26:38 + --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:32:23 + --> $DIR/uninitialized-zeroed.rs:40:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:33:23 + --> $DIR/uninitialized-zeroed.rs:41:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:35:30 + --> $DIR/uninitialized-zeroed.rs:43:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:36:30 + --> $DIR/uninitialized-zeroed.rs:44:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:38:26 + --> $DIR/uninitialized-zeroed.rs:46:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:39:26 + --> $DIR/uninitialized-zeroed.rs:47:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:34 + --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:34 + --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:25 + --> $DIR/uninitialized-zeroed.rs:52:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:25 + --> $DIR/uninitialized-zeroed.rs:53:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:47:26 + --> $DIR/uninitialized-zeroed.rs:55:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:48:26 + --> $DIR/uninitialized-zeroed.rs:56:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:50:32 + --> $DIR/uninitialized-zeroed.rs:58:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:51:32 + --> $DIR/uninitialized-zeroed.rs:59:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:53:36 + --> $DIR/uninitialized-zeroed.rs:61:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:54:36 + --> $DIR/uninitialized-zeroed.rs:62:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:56:42 + --> $DIR/uninitialized-zeroed.rs:64:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:57:42 + --> $DIR/uninitialized-zeroed.rs:65:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,10 +280,102 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 22 previous errors +error: the type `std::ptr::NonNull` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:67:34 + | +LL | let _val: NonNull = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::ptr::NonNull must be non-null + +error: the type `std::ptr::NonNull` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:68:34 + | +LL | let _val: NonNull = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::ptr::NonNull must be non-null + +error: the type `bool` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:72:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: Booleans must be `true` or `false` + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:75:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | +note: Characters must be a valid unicode codepoint (in this struct field) + --> $DIR/uninitialized-zeroed.rs:18:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:78:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: NonBig must be initialized inside its custom valid range + +error: the type `&'static i32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:81:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `&'static [i32]` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:82:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `std::num::NonZeroU32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:83:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::num::NonZeroU32 must be non-null + +error: aborting due to 30 previous errors diff --git a/src/test/ui/lint/unreachable-async-fn.rs b/src/test/ui/lint/unreachable-async-fn.rs new file mode 100644 index 0000000000..eedd877fe7 --- /dev/null +++ b/src/test/ui/lint/unreachable-async-fn.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2018 + +#[allow(dead_code)] +async fn foo () { // unreachable lint doesn't trigger + unimplemented!() +} + +fn main() {} diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index c7c53abcf4..678c88849b 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -412,7 +412,7 @@ mod foo { { "message": "For more information about this error, try `rustc --explain E0412`.", "code": null, - "level": "", + "level": "failure-note", "spans": [], "children": [], "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr index 40a677c08f..6ea20081e5 100644 --- a/src/test/ui/liveness/liveness-unused.stderr +++ b/src/test/ui/liveness/liveness-unused.stderr @@ -1,8 +1,10 @@ warning: unreachable statement --> $DIR/liveness-unused.rs:92:9 | +LL | continue; + | -------- any code following this expression is unreachable LL | drop(*x as i32); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/liveness-unused.rs:1:9 diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs index b8f76fbe57..b242ec4296 100644 --- a/src/test/ui/loops/loop-proper-liveness.rs +++ b/src/test/ui/loops/loop-proper-liveness.rs @@ -6,7 +6,7 @@ fn test1() { 'a: loop { x = loop { break 'a }; } - println!("{:?}", x); //~ ERROR borrow of possibly uninitialized variable + println!("{:?}", x); //~ ERROR borrow of possibly-uninitialized variable } // test2 and test3 should not fail. diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr index c87720659f..d55f9ff31e 100644 --- a/src/test/ui/loops/loop-proper-liveness.stderr +++ b/src/test/ui/loops/loop-proper-liveness.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/loop-proper-liveness.rs:9:22 | LL | println!("{:?}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr index 5760cb9a8f..b7a930b61c 100644 --- a/src/test/ui/lto-duplicate-symbols.stderr +++ b/src/test/ui/lto-duplicate-symbols.stderr @@ -1,6 +1,6 @@ warning: Linking globals named 'foo': symbol multiply defined! -error: failed to load bc of "lto_duplicate_symbols1.3a1fbbbh-cgu.0": +error: failed to load bc of "lto_duplicate_symbols2.3a1fbbbh-cgu.0": error: aborting due to previous error diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/lub-if.stderr index bb772d4c6c..26f756c918 100644 --- a/src/test/ui/lub-if.stderr +++ b/src/test/ui/lub-if.stderr @@ -26,3 +26,4 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/lub-match.stderr index 090af25143..0cb0a23c6f 100644 --- a/src/test/ui/lub-match.stderr +++ b/src/test/ui/lub-match.stderr @@ -26,3 +26,4 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs index b50ed7ca92..c460db36f1 100644 --- a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs +++ b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs @@ -6,7 +6,7 @@ extern crate proc_macro; -use proc_macro::{quote, Span, TokenStream}; +use proc_macro::{quote, Span, TokenStream, TokenTree}; fn assert_same_span(a: Span, b: Span) { assert_eq!(a.start(), b.start()); @@ -24,12 +24,22 @@ pub fn make_foo(_: TokenStream) -> TokenStream { }; // Check that all spans are equal. - let mut span = None; + // FIXME: `quote!` gives def-site spans to idents and literals, + // but leaves (default) call-site spans on groups and punctuation. + let mut span_call = None; + let mut span_def = None; for tt in result.clone() { - match span { - None => span = Some(tt.span()), - Some(span) => assert_same_span(tt.span(), span), + match tt { + TokenTree::Ident(..) | TokenTree::Literal(..) => match span_def { + None => span_def = Some(tt.span()), + Some(span) => assert_same_span(tt.span(), span), + } + TokenTree::Punct(..) | TokenTree::Group(..) => match span_call { + None => span_call = Some(tt.span()), + Some(span) => assert_same_span(tt.span(), span), + } } + } result diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 015e05ed9b..96054de801 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s --> $DIR/macro-backtrace-invalid-internals.rs:5:13 | LL | 1.fake() - | ^^^^ + | ^^^^ method not found in `{integer}` ... LL | fake_method_stmt!(); | -------------------- in this macro invocation @@ -42,7 +42,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s --> $DIR/macro-backtrace-invalid-internals.rs:23:13 | LL | 1.fake() - | ^^^^ + | ^^^^ method not found in `{integer}` ... LL | let _ = fake_method_expr!(); | ------------------- in this macro invocation diff --git a/src/test/ui/macros/macro-expansion-tests.stderr b/src/test/ui/macros/macro-expansion-tests.stderr index 4ad9ade95a..8b3f7ca881 100644 --- a/src/test/ui/macros/macro-expansion-tests.stderr +++ b/src/test/ui/macros/macro-expansion-tests.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `m!` in this scope +error: cannot find macro `m` in this scope --> $DIR/macro-expansion-tests.rs:7:21 | LL | fn g() -> i32 { m!() } @@ -6,7 +6,7 @@ LL | fn g() -> i32 { m!() } | = help: have you added the `#[macro_use]` on the module/import? -error: cannot find macro `m!` in this scope +error: cannot find macro `m` in this scope --> $DIR/macro-expansion-tests.rs:15:21 | LL | fn g() -> i32 { m!() } diff --git a/src/test/ui/macros/macro-in-fn.rs b/src/test/ui/macros/macro-in-fn.rs new file mode 100644 index 0000000000..d354fe4a7d --- /dev/null +++ b/src/test/ui/macros/macro-in-fn.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(decl_macro)] + +pub fn moo() { + pub macro ABC() {{}} +} + +fn main() {} diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr index 967f4f3c4a..ce2e1985b3 100644 --- a/src/test/ui/macros/macro-name-typo.stderr +++ b/src/test/ui/macros/macro-name-typo.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `printlx!` in this scope +error: cannot find macro `printlx` in this scope --> $DIR/macro-name-typo.rs:2:5 | LL | printlx!("oh noes!"); diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs index 597053d625..68eb350a95 100644 --- a/src/test/ui/macros/macro-path-prelude-fail-3.rs +++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs @@ -1,3 +1,3 @@ fn main() { - inline!(); //~ ERROR cannot find macro `inline!` in this scope + inline!(); //~ ERROR cannot find macro `inline` in this scope } diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr index 96b8a24cff..ec00760de6 100644 --- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr +++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `inline!` in this scope +error: cannot find macro `inline` in this scope --> $DIR/macro-path-prelude-fail-3.rs:2:5 | LL | inline!(); diff --git a/src/test/ui/macros/macro-reexport-removed.rs b/src/test/ui/macros/macro-reexport-removed.rs index b69a1fa4df..874c94d08e 100644 --- a/src/test/ui/macros/macro-reexport-removed.rs +++ b/src/test/ui/macros/macro-reexport-removed.rs @@ -2,7 +2,7 @@ #![feature(macro_reexport)] //~ ERROR feature has been removed -#[macro_reexport(macro_one)] //~ ERROR cannot find attribute macro `macro_reexport` in this scope +#[macro_reexport(macro_one)] //~ ERROR cannot find attribute `macro_reexport` in this scope extern crate two_macros; fn main() {} diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr index 25778fba68..4bec70850a 100644 --- a/src/test/ui/macros/macro-reexport-removed.stderr +++ b/src/test/ui/macros/macro-reexport-removed.stderr @@ -10,7 +10,7 @@ note: subsumed by `pub use` LL | #![feature(macro_reexport)] | ^^^^^^^^^^^^^^ -error: cannot find attribute macro `macro_reexport` in this scope +error: cannot find attribute `macro_reexport` in this scope --> $DIR/macro-reexport-removed.rs:5:3 | LL | #[macro_reexport(macro_one)] diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr index 28f727d6a5..8b4e90a579 100644 --- a/src/test/ui/macros/macro-use-wrong-name.stderr +++ b/src/test/ui/macros/macro-use-wrong-name.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `macro_two!` in this scope +error: cannot find macro `macro_two` in this scope --> $DIR/macro-use-wrong-name.rs:7:5 | LL | macro_two!(); diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr index 9239b2a51e..01c8ebea62 100644 --- a/src/test/ui/macros/macro_undefined.stderr +++ b/src/test/ui/macros/macro_undefined.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `k!` in this scope +error: cannot find macro `k` in this scope --> $DIR/macro_undefined.rs:11:5 | LL | k!(); diff --git a/src/test/ui/macros/restricted-shadowing-modern.rs b/src/test/ui/macros/restricted-shadowing-modern.rs index a8818507d7..1151a829eb 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.rs +++ b/src/test/ui/macros/restricted-shadowing-modern.rs @@ -95,8 +95,6 @@ macro include() { m!() } - // ----------------------------------------------------------- - fn check1() { macro m() {} { diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index d147debeb5..12075d42b9 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -1,5 +1,5 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:106:17 + --> $DIR/restricted-shadowing-modern.rs:104:17 | LL | m!(); | ^ ambiguous name @@ -16,7 +16,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:101:9 + --> $DIR/restricted-shadowing-modern.rs:99:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:149:33 + --> $DIR/restricted-shadowing-modern.rs:147:33 | LL | macro gen_invoc() { m!() } | ^ ambiguous name @@ -42,7 +42,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:145:9 + --> $DIR/restricted-shadowing-modern.rs:143:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:158:13 + --> $DIR/restricted-shadowing-modern.rs:156:13 | LL | m!(); | ^ ambiguous name @@ -68,7 +68,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:155:9 + --> $DIR/restricted-shadowing-modern.rs:153:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:174:13 + --> $DIR/restricted-shadowing-modern.rs:172:13 | LL | m!(); | ^ ambiguous name @@ -103,7 +103,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:192:17 + --> $DIR/restricted-shadowing-modern.rs:190:17 | LL | m!(); | ^ ambiguous name @@ -129,7 +129,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:235:33 + --> $DIR/restricted-shadowing-modern.rs:233:33 | LL | macro gen_invoc() { m!() } | ^ ambiguous name diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index aee1b4c9c5..0eef4a2a67 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -17,8 +17,15 @@ LL | $(= $z:tt)* error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments --> $DIR/same-sequence-span.rs:20:1 | -LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments +LL | proc_macro_sequence::make_foo!(); + | ^-------------------------------- + | | + | _in this macro invocation + | | +LL | | +LL | | +LL | | fn main() {} +... | | = note: allowed there are: `=>`, `,` or `;` @@ -26,7 +33,10 @@ error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragmen --> $DIR/same-sequence-span.rs:20:1 | LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not allowed after `expr` fragments + | in this macro invocation | = note: allowed there are: `=>`, `,` or `;` diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 287f7b297d..202a9235ad 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,5 +5,5 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `{ $crate :: io :: _print (format_args_nl ! ("Hello, World!")) ; }` + = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }` diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs index d7ed512819..f75d08813c 100644 --- a/src/test/ui/main-wrong-location.rs +++ b/src/test/ui/main-wrong-location.rs @@ -1,4 +1,5 @@ mod m { +//~^ ERROR `main` function not found // An inferred main entry point (that doesn't use #[main]) // must appear at the top of the crate fn main() { } diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index b30931f2f2..e301c2ff09 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -1,11 +1,21 @@ error[E0601]: `main` function not found in crate `main_wrong_location` + --> $DIR/main-wrong-location.rs:1:1 | - = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. -note: here is a function named 'main' - --> $DIR/main-wrong-location.rs:4:5 +LL | / mod m { +LL | | +LL | | // An inferred main entry point (that doesn't use #[main]) +LL | | // must appear at the top of the crate +LL | | fn main() { } +LL | | } + | |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`) + | +note: here is a function named `main` + --> $DIR/main-wrong-location.rs:5:5 | LL | fn main() { } | ^^^^^^^^^^^^^ + = note: you have one or more functions named `main` not defined at the crate level + = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-regressions.stderr b/src/test/ui/malformed/malformed-regressions.stderr index eebb6f0623..164668f562 100644 --- a/src/test/ui/malformed/malformed-regressions.stderr +++ b/src/test/ui/malformed/malformed-regressions.stderr @@ -26,8 +26,7 @@ LL | #[inline = ""] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...")]` +warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]` --> $DIR/malformed-regressions.rs:6:1 | LL | #[link] @@ -36,8 +35,7 @@ LL | #[link] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...")]` +warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]` --> $DIR/malformed-regressions.rs:7:1 | LL | #[link = ""] diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr index f4a52a65af..4508870746 100644 --- a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied - --> $DIR/overlap-marker-trait.rs:27:5 - | -LL | is_marker::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` - | -note: required by `is_marker` - --> $DIR/overlap-marker-trait.rs:15:1 + --> $DIR/overlap-marker-trait.rs:27:17 | LL | fn is_marker() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------- ------ required by this bound in `is_marker` +... +LL | is_marker::(); + | ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` error: aborting due to previous error diff --git a/src/test/ui/match/match-no-arms-unreachable-after.stderr b/src/test/ui/match/match-no-arms-unreachable-after.stderr index 65dcc6ee46..66e5c91ad2 100644 --- a/src/test/ui/match/match-no-arms-unreachable-after.stderr +++ b/src/test/ui/match/match-no-arms-unreachable-after.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/match-no-arms-unreachable-after.rs:8:5 | +LL | match v { } + | ----------- any code following this expression is unreachable LL | let x = 2; - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/match-no-arms-unreachable-after.rs:2:9 diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 663cd2cd24..c2298d6fbb 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -1,6 +1,9 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields --> $DIR/match-pattern-field-mismatch.rs:10:11 | +LL | Rgb(usize, usize, usize), + | ------------------------ tuple variant defined here +... LL | Color::Rgb(_, _) => { } | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs index 49e0dfaa3e..52120360be 100644 --- a/src/test/ui/match/match-ref-mut-stability.rs +++ b/src/test/ui/match/match-ref-mut-stability.rs @@ -3,8 +3,6 @@ // run-pass -#![feature(bind_by_move_pattern_guards)] - // Test that z always point to the same temporary. fn referent_stability() { let p; diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr index ad8569b480..77df9921b7 100644 --- a/src/test/ui/match/match-unresolved-one-arm.stderr +++ b/src/test/ui/match/match-unresolved-one-arm.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/match-unresolved-one-arm.rs:4:9 | LL | let x = match () { - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr index 2f1bbb7621..a3523bb689 100644 --- a/src/test/ui/match/match-vec-mismatch.stderr +++ b/src/test/ui/match/match-vec-mismatch.stderr @@ -10,7 +10,7 @@ error[E0529]: expected an array or slice, found `std::string::String` LL | ['f', 'o', ..] => {} | ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String` -error[E0527]: pattern requires 1 elements but array has 3 +error[E0527]: pattern requires 1 element but array has 3 --> $DIR/match-vec-mismatch.rs:20:9 | LL | [0] => {}, diff --git a/src/test/ui/match/non-exhaustive-defined-here.rs b/src/test/ui/match/non-exhaustive-defined-here.rs new file mode 100644 index 0000000000..6f009acbdf --- /dev/null +++ b/src/test/ui/match/non-exhaustive-defined-here.rs @@ -0,0 +1,72 @@ +// Test the "defined here" and "not covered" diagnostic hints. +// We also make sure that references are peeled off from the scrutinee type +// so that the diagnostics work better with default binding modes. + +#[derive(Clone)] +enum E { +//~^ `E` defined here +//~| `E` defined here +//~| `E` defined here +//~| `E` defined here +//~| `E` defined here +//~| `E` defined here + A, + B, + //~^ not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered + C + //~^ not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered +} + +fn by_val(e: E) { + let e1 = e.clone(); + match e1 { //~ ERROR non-exhaustive patterns: `B` and `C` not covered + E::A => {} + } + + let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered +} + +fn by_ref_once(e: &E) { + match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered + E::A => {} + } + + let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered +} + +fn by_ref_thrice(e: & &mut &E) { + match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered +} + +enum Opt { +//~^ `Opt` defined here +//~| `Opt` defined here + Some(u8), + None, + //~^ not covered +} + +fn ref_pat(e: Opt) { + match e {//~ ERROR non-exhaustive patterns: `None` not covered + Opt::Some(ref _x) => {} + } + + let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered +} + +fn main() {} diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/match/non-exhaustive-defined-here.stderr new file mode 100644 index 0000000000..25b8bbdab2 --- /dev/null +++ b/src/test/ui/match/non-exhaustive-defined-here.stderr @@ -0,0 +1,170 @@ +error[E0004]: non-exhaustive patterns: `B` and `C` not covered + --> $DIR/non-exhaustive-defined-here.rs:32:11 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | match e1 { + | ^^ patterns `B` and `C` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0005]: refutable pattern in local binding: `B` and `C` not covered + --> $DIR/non-exhaustive-defined-here.rs:36:9 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | let E::A = e; + | ^^^^ patterns `B` and `C` not covered + +error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered + --> $DIR/non-exhaustive-defined-here.rs:40:11 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | match e { + | ^ patterns `&B` and `&C` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered + --> $DIR/non-exhaustive-defined-here.rs:44:9 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | let E::A = e; + | ^^^^ patterns `&B` and `&C` not covered + +error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered + --> $DIR/non-exhaustive-defined-here.rs:48:11 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | match e { + | ^ patterns `&&mut &B` and `&&mut &C` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered + --> $DIR/non-exhaustive-defined-here.rs:52:9 + | +LL | / enum E { +LL | | +LL | | +LL | | +... | +LL | | B, + | | - not covered +... | +LL | | C + | | - not covered +... | +LL | | +LL | | } + | |_- `E` defined here +... +LL | let E::A = e; + | ^^^^ patterns `&&mut &B` and `&&mut &C` not covered + +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/non-exhaustive-defined-here.rs:65:11 + | +LL | / enum Opt { +LL | | +LL | | +LL | | Some(u8), +LL | | None, + | | ---- not covered +LL | | +LL | | } + | |_- `Opt` defined here +... +LL | match e { + | ^ pattern `None` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0005]: refutable pattern in local binding: `None` not covered + --> $DIR/non-exhaustive-defined-here.rs:69:9 + | +LL | / enum Opt { +LL | | +LL | | +LL | | Some(u8), +LL | | None, + | | ---- not covered +LL | | +LL | | } + | |_- `Opt` defined here +... +LL | let Opt::Some(ref _x) = e; + | ^^^^^^^^^^^^^^^^^ pattern `None` not covered + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b8ae4c34dc..94c27b7d17 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -32,7 +32,7 @@ LL | pub struct Foo; | --------------- method `take` not found for this ... LL | .take() - | ^^^^ + | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: `&mut Foo : std::iter::Iterator` diff --git a/src/test/ui/methods/method-projection.rs b/src/test/ui/methods/method-projection.rs index cf33d53968..21d983f192 100644 --- a/src/test/ui/methods/method-projection.rs +++ b/src/test/ui/methods/method-projection.rs @@ -2,9 +2,6 @@ // Test that we can use method notation to call methods based on a // projection bound from a trait. Issue #20469. -/////////////////////////////////////////////////////////////////////////// - - trait MakeString { fn make_string(&self) -> String; } @@ -21,8 +18,6 @@ impl MakeString for usize { } } -/////////////////////////////////////////////////////////////////////////// - trait Foo { type F: MakeString; @@ -33,8 +28,6 @@ fn foo(f: &F) -> String { f.get().make_string() } -/////////////////////////////////////////////////////////////////////////// - struct SomeStruct { field: isize, } @@ -47,8 +40,6 @@ impl Foo for SomeStruct { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeOtherStruct { field: usize, } diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr index 8662bb7795..88c1efdbb9 100644 --- a/src/test/ui/mismatched_types/E0631.stderr +++ b/src/test/ui/mismatched_types/E0631.stderr @@ -1,60 +1,48 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:7:5 | +LL | fn foo(_: F) {} + | --- --------- required by this bound in `foo` +... LL | foo(|_: isize| {}); | ^^^ ---------- found signature of `fn(isize) -> _` | | | expected signature of `fn(usize) -> _` - | -note: required by `foo` - --> $DIR/E0631.rs:3:1 - | -LL | fn foo(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:8:5 | +LL | fn bar>(_: F) {} + | --- --------- required by this bound in `bar` +... LL | bar(|_: isize| {}); | ^^^ ---------- found signature of `fn(isize) -> _` | | | expected signature of `fn(usize) -> _` - | -note: required by `bar` - --> $DIR/E0631.rs:4:1 - | -LL | fn bar>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in function arguments - --> $DIR/E0631.rs:9:5 + --> $DIR/E0631.rs:9:9 | +LL | fn foo(_: F) {} + | --- --------- required by this bound in `foo` +... LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | foo(f); - | ^^^ expected signature of `fn(usize) -> _` - | -note: required by `foo` - --> $DIR/E0631.rs:3:1 - | -LL | fn foo(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected signature of `fn(usize) -> _` error[E0631]: type mismatch in function arguments - --> $DIR/E0631.rs:10:5 + --> $DIR/E0631.rs:10:9 | +LL | fn bar>(_: F) {} + | --- --------- required by this bound in `bar` +LL | fn main() { LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | bar(f); - | ^^^ expected signature of `fn(usize) -> _` - | -note: required by `bar` - --> $DIR/E0631.rs:4:1 - | -LL | fn bar>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected signature of `fn(usize) -> _` error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 25d5d25ec1..ed2b3f0c3c 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -45,16 +45,13 @@ LL | [1, 2, 3].sort_by(|tuple, tuple2| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:13:5 | +LL | fn f>(_: F) {} + | - --------- required by this bound in `f` +... LL | f(|| panic!()); | ^ -- takes 0 arguments | | | expected closure that takes 1 argument - | -note: required by `f` - --> $DIR/closure-arg-count.rs:3:1 - | -LL | fn f>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | LL | f(|_| panic!()); @@ -63,16 +60,13 @@ LL | f(|_| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:5 | +LL | fn f>(_: F) {} + | - --------- required by this bound in `f` +... LL | f( move || panic!()); | ^ ---------- takes 0 arguments | | | expected closure that takes 1 argument - | -note: required by `f` - --> $DIR/closure-arg-count.rs:3:1 - | -LL | fn f>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | LL | f( move |_| panic!()); @@ -111,51 +105,47 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments - --> $DIR/closure-arg-count.rs:24:53 + --> $DIR/closure-arg-count.rs:24:57 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); - | ^^^ expected function that takes a single 2-tuple as argument + | ^^^ expected function that takes a single 2-tuple as argument ... LL | fn foo() {} | -------- takes 0 arguments error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:27:53 + --> $DIR/closure-arg-count.rs:27:57 | LL | let bar = |i, x, y| i; | --------- takes 3 distinct arguments LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); - | ^^^ expected closure that takes a single 2-tuple as argument + | ^^^ expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:29:53 + --> $DIR/closure-arg-count.rs:29:57 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); - | ^^^ expected function that takes a single 2-tuple as argument + | ^^^ expected function that takes a single 2-tuple as argument ... LL | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments error[E0593]: function is expected to take 1 argument, but it takes 2 arguments - --> $DIR/closure-arg-count.rs:32:41 + --> $DIR/closure-arg-count.rs:32:45 | LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); - | ^^^ expected function that takes 1 argument + | ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument error[E0593]: function is expected to take 0 arguments, but it takes 1 argument - --> $DIR/closure-arg-count.rs:35:5 + --> $DIR/closure-arg-count.rs:35:10 | LL | call(Foo); - | ^^^^ expected function that takes 0 arguments + | ^^^ expected function that takes 0 arguments ... +LL | fn call(_: F) where F: FnOnce() -> R {} + | ---- ------------- required by this bound in `call` LL | struct Foo(u8); | --------------- takes 1 argument - | -note: required by `call` - --> $DIR/closure-arg-count.rs:42:1 - | -LL | fn call(_: F) where F: FnOnce() -> R {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index d4ccf8d451..85cad61210 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -23,31 +23,25 @@ LL | a.iter().map(|_: (u16, u16)| 45); | expected signature of `fn(&(u32, u32)) -> _` error[E0631]: type mismatch in function arguments - --> $DIR/closure-arg-type-mismatch.rs:10:5 - | -LL | baz(f); - | ^^^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` - | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 + --> $DIR/closure-arg-type-mismatch.rs:10:9 | LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --- ------------- required by this bound in `baz` +LL | fn _test<'a>(f: fn(*mut &'a u32)) { +LL | baz(f); + | ^ + | | + | expected signature of `for<'r> fn(*mut &'r u32) -> _` + | found signature of `fn(*mut &'a u32) -> _` error[E0271]: type mismatch resolving `for<'r> >::Output == ()` --> $DIR/closure-arg-type-mismatch.rs:10:5 | +LL | fn baz(_: F) {} + | --- ------------- required by this bound in `baz` +LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^ expected bound lifetime parameter, found concrete lifetime - | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 - | -LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 7161f69790..fd2b9f3c66 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,30 +1,26 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` --> $DIR/closure-mismatch.rs:8:5 | +LL | fn baz(_: T) {} + | --- --- required by this bound in `baz` +... LL | baz(|_| ()); | ^^^ expected bound lifetime parameter, found concrete lifetime | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments --> $DIR/closure-mismatch.rs:8:5 | +LL | fn baz(_: T) {} + | --- --- required by this bound in `baz` +... LL | baz(|_| ()); | ^^^ ------ found signature of `fn(_) -> _` | | | expected signature of `for<'r> fn(&'r ()) -> _` | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index c15d6620e1..1a82dd53ed 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -1,32 +1,26 @@ error[E0631]: type mismatch in function arguments - --> $DIR/fn-variance-1.rs:11:5 + --> $DIR/fn-variance-1.rs:11:15 | LL | fn takes_mut(x: &mut isize) { } | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _` +LL | +LL | fn apply(t: T, f: F) where F: FnOnce(T) { + | ----- --------- required by this bound in `apply` ... LL | apply(&3, takes_mut); - | ^^^^^ expected signature of `fn(&{integer}) -> _` - | -note: required by `apply` - --> $DIR/fn-variance-1.rs:5:1 - | -LL | fn apply(t: T, f: F) where F: FnOnce(T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ expected signature of `fn(&{integer}) -> _` error[E0631]: type mismatch in function arguments - --> $DIR/fn-variance-1.rs:15:5 + --> $DIR/fn-variance-1.rs:15:19 | LL | fn takes_imm(x: &isize) { } | ----------------------- found signature of `for<'r> fn(&'r isize) -> _` ... -LL | apply(&mut 3, takes_imm); - | ^^^^^ expected signature of `fn(&mut {integer}) -> _` - | -note: required by `apply` - --> $DIR/fn-variance-1.rs:5:1 - | LL | fn apply(t: T, f: F) where F: FnOnce(T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- --------- required by this bound in `apply` +... +LL | apply(&mut 3, takes_imm); + | ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _` error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index f030670161..4a9afb9d24 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -6,6 +6,8 @@ LL | Some(true) | = note: expected type `bool` (type parameter) found type `bool` (bool) + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 3f87ef74b8..89c7b09811 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `count` found for type `std::iter::Filter $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^ + | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` | = note: the method `count` exists but the following trait bounds were not satisfied: `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator` diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 9721dc8ba4..865092e4e9 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `unwrap` found for type `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | a.unwrap(); - | ^^^^^^ + | ^^^^^^ method not found in `std::result::Result<(), Foo>` | = note: the method `unwrap` exists but the following trait bounds were not satisfied: `Foo : std::fmt::Debug` diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 88bea979b9..2bd4d33844 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -5,7 +5,8 @@ use std::ops::FnMut; fn to_fn_mut>(f: F) -> F { f } fn call_itisize>(y: isize, mut f: F) -> isize { -//~^ NOTE required by `call_it` +//~^ NOTE required by this bound in `call_it` +//~| NOTE f(2, y) } diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 47aa3c21f5..2daf4781c7 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -1,17 +1,14 @@ error[E0631]: type mismatch in closure arguments - --> $DIR/unboxed-closures-vtable-mismatch.rs:15:13 + --> $DIR/unboxed-closures-vtable-mismatch.rs:16:24 | +LL | fn call_itisize>(y: isize, mut f: F) -> isize { + | ------- ------------------------- required by this bound in `call_it` +... LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); | ----------------------------- found signature of `fn(usize, isize) -> _` LL | LL | let z = call_it(3, f); - | ^^^^^^^ expected signature of `fn(isize, isize) -> _` - | -note: required by `call_it` - --> $DIR/unboxed-closures-vtable-mismatch.rs:7:1 - | -LL | fn call_itisize>(y: isize, mut f: F) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected signature of `fn(isize, isize) -> _` error: aborting due to previous error diff --git a/src/test/ui/missing/missing-macro-use.rs b/src/test/ui/missing/missing-macro-use.rs index dff4c94fcf..d494c4471a 100644 --- a/src/test/ui/missing/missing-macro-use.rs +++ b/src/test/ui/missing/missing-macro-use.rs @@ -4,5 +4,5 @@ extern crate two_macros; pub fn main() { macro_two!(); - //~^ ERROR cannot find macro `macro_two!` in this scope + //~^ ERROR cannot find macro `macro_two` in this scope } diff --git a/src/test/ui/missing/missing-macro-use.stderr b/src/test/ui/missing/missing-macro-use.stderr index 01a7beb3b0..711e249d2b 100644 --- a/src/test/ui/missing/missing-macro-use.stderr +++ b/src/test/ui/missing/missing-macro-use.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `macro_two!` in this scope +error: cannot find macro `macro_two` in this scope --> $DIR/missing-macro-use.rs:6:5 | LL | macro_two!(); diff --git a/src/test/ui/missing/missing-main.stderr b/src/test/ui/missing/missing-main.stderr index 34b03ada3d..6a35f5117e 100644 --- a/src/test/ui/missing/missing-main.stderr +++ b/src/test/ui/missing/missing-main.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `missing_main` + --> $DIR/missing-main.rs:2:1 | - = note: consider adding a `main` function to `$DIR/missing-main.rs` +LL | fn mian() { } + | ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs` error: aborting due to previous error diff --git a/src/test/ui/missing/missing-semicolon-warning.stderr b/src/test/ui/missing/missing-semicolon-warning.stderr index b3f3ebc855..b4001aba28 100644 --- a/src/test/ui/missing/missing-semicolon-warning.stderr +++ b/src/test/ui/missing/missing-semicolon-warning.stderr @@ -7,7 +7,7 @@ LL | $( let x = $e1 )*; LL | fn main() { m!(0, 0; 0, 0); } | --------------- in this macro invocation | - = note: This was erroneously allowed and will become a hard error in a future release + = note: this was erroneously allowed and will become a hard error in a future release warning: expected `;`, found `println` --> $DIR/missing-semicolon-warning.rs:7:12 @@ -18,5 +18,5 @@ LL | $( println!("{}", $e2) )*; LL | fn main() { m!(0, 0; 0, 0); } | --------------- in this macro invocation | - = note: This was erroneously allowed and will become a hard error in a future release + = note: this was erroneously allowed and will become a hard error in a future release diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs index 16a18da4a4..2d0ff58526 100644 --- a/src/test/ui/moves/move-into-dead-array-1.rs +++ b/src/test/ui/moves/move-into-dead-array-1.rs @@ -11,5 +11,5 @@ fn main() { fn foo(i: usize) { let mut a: [D; 4]; - a[i] = d(); //~ ERROR use of possibly uninitialized variable: `a` + a[i] = d(); //~ ERROR use of possibly-uninitialized variable: `a` } diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr index 33da0e54a1..5f20ccfedd 100644 --- a/src/test/ui/moves/move-into-dead-array-1.stderr +++ b/src/test/ui/moves/move-into-dead-array-1.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/move-into-dead-array-1.rs:14:5 | LL | a[i] = d(); - | ^^^^ use of possibly uninitialized `a` + | ^^^^ use of possibly-uninitialized `a` error: aborting due to previous error diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr index 1268e487f3..0290efc3d9 100644 --- a/src/test/ui/mut/mutable-enum-indirect.stderr +++ b/src/test/ui/mut/mutable-enum-indirect.stderr @@ -1,17 +1,15 @@ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/mutable-enum-indirect.rs:17:5 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(&x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `&Foo`, the trait `std::marker::Sync` is not implemented for `NoSync` = note: required because it appears within the type `Foo` = note: required because it appears within the type `&Foo` -note: required by `bar` - --> $DIR/mutable-enum-indirect.rs:13:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr index d1f7d13937..71a06fce4b 100644 --- a/src/test/ui/mutexguard-sync.stderr +++ b/src/test/ui/mutexguard-sync.stderr @@ -1,16 +1,14 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely - --> $DIR/mutexguard-sync.rs:11:5 + --> $DIR/mutexguard-sync.rs:11:15 | +LL | fn test_sync(_t: T) {} + | --------- ---- required by this bound in `test_sync` +... LL | test_sync(guard); - | ^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely + | ^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::MutexGuard<'_, std::cell::Cell>` -note: required by `test_sync` - --> $DIR/mutexguard-sync.rs:5:1 - | -LL | fn test_sync(_t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index ef2d0d87f0..aa21928aae 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -67,532 +67,400 @@ LL | use namespace_mix::xm8::V; | error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:33:5 - | -LL | check(m1::S{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:33:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m1::S{}); + | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `c::S: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:35:5 - | -LL | check(m2::S{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::S` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:35:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m2::S{}); + | ^^^^^^^ the trait `Impossible` is not implemented for `c::S` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:36:5 - | -LL | check(m2::S); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:36:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m2::S); + | ^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:39:5 - | -LL | check(xm1::S{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:39:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm1::S{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:41:5 - | -LL | check(xm2::S{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:41:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm2::S{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:42:5 - | -LL | check(xm2::S); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:42:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm2::S); + | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:55:5 - | -LL | check(m3::TS{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:55:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m3::TS{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:56:5 - | -LL | check(m3::TS); - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:56:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m3::TS); + | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` error[E0277]: the trait bound `c::TS: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:57:5 - | -LL | check(m4::TS{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::TS` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:57:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m4::TS{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:58:5 - | -LL | check(m4::TS); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:58:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m4::TS); + | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:61:5 - | -LL | check(xm3::TS{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:61:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm3::TS{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:62:5 - | -LL | check(xm3::TS); - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:62:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm3::TS); + | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:63:5 - | -LL | check(xm4::TS{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:63:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm4::TS{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:64:5 - | -LL | check(xm4::TS); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:64:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm4::TS); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:77:5 - | -LL | check(m5::US{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:77:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m5::US{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `c::US: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:78:5 - | -LL | check(m5::US); - | ^^^^^ the trait `Impossible` is not implemented for `c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:78:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m5::US); + | ^^^^^^ the trait `Impossible` is not implemented for `c::US` error[E0277]: the trait bound `c::US: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:79:5 - | -LL | check(m6::US{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:79:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m6::US{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::US` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:80:5 - | -LL | check(m6::US); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:80:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m6::US); + | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:83:5 - | -LL | check(xm5::US{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:83:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm5::US{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:84:5 - | -LL | check(xm5::US); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:84:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm5::US); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:85:5 - | -LL | check(xm6::US{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:85:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm6::US{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:86:5 - | -LL | check(xm6::US); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:86:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm6::US); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:99:5 - | -LL | check(m7::V{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:99:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m7::V{}); + | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:101:5 - | -LL | check(m8::V{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:101:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m8::V{}); + | ^^^^^^^ the trait `Impossible` is not implemented for `c::E` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:102:5 - | -LL | check(m8::V); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:102:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m8::V); + | ^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:105:5 - | -LL | check(xm7::V{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:105:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm7::V{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:107:5 - | -LL | check(xm8::V{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:107:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm8::V{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:108:5 - | -LL | check(xm8::V); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:108:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm8::V); + | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:121:5 - | -LL | check(m9::TV{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:121:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m9::TV{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:122:5 - | -LL | check(m9::TV); - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:122:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(m9::TV); + | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` error[E0277]: the trait bound `c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:123:5 - | -LL | check(mA::TV{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:123:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mA::TV{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:124:5 - | -LL | check(mA::TV); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:124:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mA::TV); + | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:127:5 - | -LL | check(xm9::TV{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:127:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm9::TV{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:128:5 - | -LL | check(xm9::TV); - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:128:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xm9::TV); + | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:129:5 - | -LL | check(xmA::TV{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:129:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmA::TV{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:130:5 - | -LL | check(xmA::TV); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:130:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmA::TV); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:143:5 - | -LL | check(mB::UV{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:143:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mB::UV{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:144:5 - | -LL | check(mB::UV); - | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:144:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mB::UV); + | ^^^^^^ the trait `Impossible` is not implemented for `c::E` error[E0277]: the trait bound `c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:145:5 - | -LL | check(mC::UV{}); - | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:145:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mC::UV{}); + | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` error[E0277]: the trait bound `c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:146:5 - | -LL | check(mC::UV); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:146:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(mC::UV); + | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:149:5 - | -LL | check(xmB::UV{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:149:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmB::UV{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:150:5 - | -LL | check(xmB::UV); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:150:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmB::UV); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:151:5 - | -LL | check(xmC::UV{}); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:151:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmC::UV{}); + | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied - --> $DIR/namespace-mix.rs:152:5 - | -LL | check(xmC::UV); - | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 + --> $DIR/namespace-mix.rs:152:11 | LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ---------- required by this bound in `check` +... +LL | check(xmC::UV); + | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` error: aborting due to 48 previous errors diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr index 779780a90a..b887d580e6 100644 --- a/src/test/ui/never-assign-dead-code.stderr +++ b/src/test/ui/never-assign-dead-code.stderr @@ -1,8 +1,10 @@ warning: unreachable statement --> $DIR/never-assign-dead-code.rs:10:5 | +LL | let x: ! = panic!("aah"); + | ------------- any code following this expression is unreachable LL | drop(x); - | ^^^^^^^^ + | ^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/never-assign-dead-code.rs:5:9 @@ -10,12 +12,15 @@ note: lint level defined here LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -warning: unreachable expression +warning: unreachable call --> $DIR/never-assign-dead-code.rs:10:5 | LL | drop(x); - | ^^^^^^^ + | ^^^^ - any code following this expression is unreachable + | | + | unreachable call warning: unused variable: `x` --> $DIR/never-assign-dead-code.rs:9:9 diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs index 906ea32b9c..1983e13db0 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs @@ -26,13 +26,13 @@ impl Drop for D { fn cannot_partially_init_adt_with_drop() { let d: D; d.x = 10; - //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_init_mutable_adt_with_drop() { let mut d: D; d.x = 10; - //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_reinit_adt_with_drop() { @@ -45,13 +45,13 @@ fn cannot_partially_reinit_adt_with_drop() { fn cannot_partially_init_inner_adt_via_outer_with_drop() { let d: D; d.s.y = 20; - //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() { let mut d: D; d.s.y = 20; - //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_reinit_inner_adt_via_outer_with_drop() { diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr index 153d9bdf32..1b66e034d3 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign of possibly uninitialized variable: `d` +error[E0381]: assign of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5 | LL | d.x = 10; - | ^^^^^^^^ use of possibly uninitialized `d` + | ^^^^^^^^ use of possibly-uninitialized `d` -error[E0381]: assign of possibly uninitialized variable: `d` +error[E0381]: assign of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:34:5 | LL | d.x = 10; - | ^^^^^^^^ use of possibly uninitialized `d` + | ^^^^^^^^ use of possibly-uninitialized `d` error[E0382]: assign of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:41:5 @@ -20,17 +20,17 @@ LL | drop(d); LL | d.x = 10; | ^^^^^^^^ value assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `d` +error[E0381]: assign to part of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:47:5 | LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly uninitialized `d.s` + | ^^^^^^^^^^ use of possibly-uninitialized `d.s` -error[E0381]: assign to part of possibly uninitialized variable: `d` +error[E0381]: assign to part of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:53:5 | LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly uninitialized `d.s` + | ^^^^^^^^^^ use of possibly-uninitialized `d.s` error[E0382]: assign to part of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:60:5 diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index 633cbdba2d..7da47c85f5 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -97,14 +97,14 @@ macro_rules! use_part { fn test_0000_local_fully_init_and_use_struct() { let s: S; s.x = 10; s.y = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_fully!(struct s); } fn test_0001_local_fully_init_and_use_tuple() { let t: T; t.0 = 10; t.1 = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_fully!(tuple t); } @@ -125,14 +125,14 @@ fn test_0011_local_fully_reinit_and_use_tuple() { fn test_0100_local_partial_init_and_use_struct() { let s: S; s.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_part!(struct s); } fn test_0101_local_partial_init_and_use_tuple() { let t: T; t.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_part!(tuple t); } @@ -153,14 +153,14 @@ fn test_0111_local_partial_reinit_and_use_tuple() { fn test_0200_local_void_init_and_use_struct() { let s: S; s.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_part!(struct s); } fn test_0201_local_void_init_and_use_tuple() { let t: Tvoid; t.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_part!(tuple t); } @@ -176,14 +176,14 @@ fn test_0201_local_void_init_and_use_tuple() { fn test_1000_field_fully_init_and_use_struct() { let q: Q>; q.r.f.x = 10; q.r.f.y = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_fully!(struct q.r.f); } fn test_1001_field_fully_init_and_use_tuple() { let q: Q; q.r.f.0 = 10; q.r.f.1 = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_fully!(tuple q.r.f); } @@ -204,14 +204,14 @@ fn test_1011_field_fully_reinit_and_use_tuple() { fn test_1100_field_partial_init_and_use_struct() { let q: Q>; q.r.f.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(struct q.r.f); } fn test_1101_field_partial_init_and_use_tuple() { let q: Q; q.r.f.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(tuple q.r.f); } @@ -232,14 +232,14 @@ fn test_1111_field_partial_reinit_and_use_tuple() { fn test_1200_field_void_init_and_use_struct() { let mut q: Q>; q.r.f.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(struct q.r.f); } fn test_1201_field_void_init_and_use_tuple() { let mut q: Q; q.r.f.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(tuple q.r.f); } diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr index 1cdf728a5e..3214789832 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:99:5 | LL | s.x = 10; s.y = Box::new(20); - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:106:5 | LL | t.0 = 10; t.1 = Box::new(20); - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:113:5 @@ -30,17 +30,17 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; t.1 = Box::new(20); | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:127:5 | LL | s.x = 10; - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:134:5 | LL | t.0 = 10; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:141:5 @@ -62,29 +62,29 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:155:5 | LL | s.x = 10; - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:162:5 | LL | t.0 = 10; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:178:5 | LL | q.r.f.x = 10; q.r.f.y = Box::new(20); - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:185:5 | LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `q.r` --> $DIR/issue-21232-partial-init-and-use.rs:192:5 @@ -106,17 +106,17 @@ LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); | = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:206:5 | LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:213:5 | LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `q.r` --> $DIR/issue-21232-partial-init-and-use.rs:220:5 @@ -138,17 +138,17 @@ LL | q.r.f.0 = 10; | = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:234:5 | LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:241:5 | LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `c` --> $DIR/issue-21232-partial-init-and-use.rs:259:13 diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr index b982915800..90a35177f4 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.stderr @@ -20,3 +20,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/issue-55288.rs b/src/test/ui/nll/issue-55288.rs index c7b6ac5924..aab2dc267d 100644 --- a/src/test/ui/nll/issue-55288.rs +++ b/src/test/ui/nll/issue-55288.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass struct Slice(&'static [&'static [u8]]); diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr index 50debc6386..4ec16ba055 100644 --- a/src/test/ui/nll/issue-55401.stderr +++ b/src/test/ui/nll/issue-55401.stderr @@ -13,3 +13,4 @@ LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs index 1399694a79..32e45184a9 100644 --- a/src/test/ui/nll/issue-57960.rs +++ b/src/test/ui/nll/issue-57960.rs @@ -30,7 +30,6 @@ fn digits(x: u8) -> u32 { OneDigit::FIRST..=OneDigit::LAST => 1, TwoDigits::FIRST..=TwoDigits::LAST => 2, ThreeDigits::FIRST..=ThreeDigits::LAST => 3, - _ => unreachable!(), } } diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 94e4a76386..2e6d675fb6 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -1,8 +1,6 @@ // Test that we have enough false edges to avoid exposing the exact matching // algorithm in borrow checking. -#![feature(bind_by_move_pattern_guards)] - fn guard_always_precedes_arm(y: i32) { let mut x; // x should always be initialized, as the only way to reach the arm is @@ -20,7 +18,7 @@ fn guard_may_be_skipped(y: i32) { match y { _ if { x = 2; true } => 1, _ if { - x; //~ ERROR use of possibly uninitialized variable: `x` + x; //~ ERROR use of possibly-uninitialized variable: `x` false } => 2, _ => 3, diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index b1e0fa7397..06fe564ac6 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,11 +1,11 @@ -error[E0381]: use of possibly uninitialized variable: `x` - --> $DIR/match-cfg-fake-edges.rs:23:13 +error[E0381]: use of possibly-uninitialized variable: `x` + --> $DIR/match-cfg-fake-edges.rs:21:13 | LL | x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error[E0382]: use of moved value: `x` - --> $DIR/match-cfg-fake-edges.rs:37:13 + --> $DIR/match-cfg-fake-edges.rs:35:13 | LL | let x = String::new(); | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 601c46ff86..81ae19ebf8 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,8 +5,6 @@ // Test that we don't allow mutating the value being matched on in a way that // changes which patterns it matches, until we have chosen an arm. -#![feature(bind_by_move_pattern_guards)] - fn ok_mutation_in_guard(mut q: i32) { match q { // OK, mutation doesn't change which patterns g matches diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr index b2951fd339..48e3a7c699 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.stderr +++ b/src/test/ui/nll/match-guards-partially-borrow.stderr @@ -1,5 +1,5 @@ error[E0510]: cannot assign `q` in match guard - --> $DIR/match-guards-partially-borrow.rs:57:13 + --> $DIR/match-guards-partially-borrow.rs:55:13 | LL | match q { | - value is immutable in match guard @@ -8,7 +8,7 @@ LL | q = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `r` in match guard - --> $DIR/match-guards-partially-borrow.rs:69:13 + --> $DIR/match-guards-partially-borrow.rs:67:13 | LL | match r { | - value is immutable in match guard @@ -17,7 +17,7 @@ LL | r = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `t` in match guard - --> $DIR/match-guards-partially-borrow.rs:93:13 + --> $DIR/match-guards-partially-borrow.rs:91:13 | LL | match t { | - value is immutable in match guard @@ -26,7 +26,7 @@ LL | t = true; | ^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x.0` in match guard - --> $DIR/match-guards-partially-borrow.rs:107:22 + --> $DIR/match-guards-partially-borrow.rs:105:22 | LL | match x { | - value is immutable in match guard @@ -35,7 +35,7 @@ LL | Some(ref mut r) => *r = None, | ^^^^^^^^^ cannot mutably borrow error[E0506]: cannot assign to `t` because it is borrowed - --> $DIR/match-guards-partially-borrow.rs:119:13 + --> $DIR/match-guards-partially-borrow.rs:117:13 | LL | s if { | - borrow of `t` occurs here @@ -46,7 +46,7 @@ LL | } => (), // What value should `s` have in the arm? | - borrow later used here error[E0510]: cannot assign `y` in match guard - --> $DIR/match-guards-partially-borrow.rs:130:13 + --> $DIR/match-guards-partially-borrow.rs:128:13 | LL | match *y { | -- value is immutable in match guard @@ -55,7 +55,7 @@ LL | y = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `z` in match guard - --> $DIR/match-guards-partially-borrow.rs:141:13 + --> $DIR/match-guards-partially-borrow.rs:139:13 | LL | match z { | - value is immutable in match guard @@ -64,7 +64,7 @@ LL | z = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `a` in match guard - --> $DIR/match-guards-partially-borrow.rs:153:13 + --> $DIR/match-guards-partially-borrow.rs:151:13 | LL | match a { | - value is immutable in match guard @@ -73,7 +73,7 @@ LL | a = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `b` in match guard - --> $DIR/match-guards-partially-borrow.rs:164:13 + --> $DIR/match-guards-partially-borrow.rs:162:13 | LL | match b { | - value is immutable in match guard diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr index 9f804dfb3d..284a910a01 100644 --- a/src/test/ui/nll/match-on-borrowed.stderr +++ b/src/test/ui/nll/match-on-borrowed.stderr @@ -34,11 +34,11 @@ LL | true => (), LL | x; | - borrow later used here -error[E0381]: use of possibly uninitialized variable: `n` +error[E0381]: use of possibly-uninitialized variable: `n` --> $DIR/match-on-borrowed.rs:92:11 | LL | match n {} - | ^ use of possibly uninitialized `n` + | ^ use of possibly-uninitialized `n` error: aborting due to 4 previous errors diff --git a/src/test/ui/nll/normalization-bounds.rs b/src/test/ui/nll/normalization-bounds.rs index 5d2825ef2d..bb6d981e01 100644 --- a/src/test/ui/nll/normalization-bounds.rs +++ b/src/test/ui/nll/normalization-bounds.rs @@ -1,6 +1,6 @@ // Check that lifetime bounds get checked the right way around with NLL enabled. -//run-pass +// check-pass trait Visitor<'d> { type Value; diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs index 6d5bdfa4da..3b06b0db37 100644 --- a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs +++ b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs @@ -1,11 +1,11 @@ // Check that mutable promoted length zero arrays don't check for conflicting // access -// run-pass +// check-pass pub fn main() { let mut x: Vec<&[i32; 0]> = Vec::new(); - for i in 0..10 { + for _ in 0..10 { x.push(&[]); } } diff --git a/src/test/ui/nll/self-assign-ref-mut.rs b/src/test/ui/nll/self-assign-ref-mut.rs new file mode 100644 index 0000000000..1ca4cf3a77 --- /dev/null +++ b/src/test/ui/nll/self-assign-ref-mut.rs @@ -0,0 +1,20 @@ +// Check that `*y` isn't borrowed after `y = y`. + +// check-pass + +fn main() { + let mut x = 1; + { + let mut y = &mut x; + y = y; + y; + } + x; + { + let mut y = &mut x; + y = y; + y = y; + y; + } + x; +} diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr index f49d68458b..0a8ad4221c 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr @@ -13,3 +13,4 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr index 451bcf41e4..d596aaf098 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr @@ -13,3 +13,4 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr index d129e55e1e..80ff9a043d 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr @@ -13,3 +13,4 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/user-annotations/issue-55219.rs b/src/test/ui/nll/user-annotations/issue-55219.rs index 4d18e96cc1..1474136638 100644 --- a/src/test/ui/nll/user-annotations/issue-55219.rs +++ b/src/test/ui/nll/user-annotations/issue-55219.rs @@ -3,7 +3,7 @@ // The `Self::HASH_LEN` here expands to a "self-type" where `T` is not // known. This unbound inference variable was causing an ICE. // -// run-pass +// check-pass pub struct Foo(T); diff --git a/src/test/ui/nll/user-annotations/normalize-self-ty.rs b/src/test/ui/nll/user-annotations/normalize-self-ty.rs index a06229a020..df905c8786 100644 --- a/src/test/ui/nll/user-annotations/normalize-self-ty.rs +++ b/src/test/ui/nll/user-annotations/normalize-self-ty.rs @@ -2,7 +2,7 @@ // the inherent impl requires normalization to be equal to the // user-provided type. // -// run-pass +// check-pass trait Mirror { type Me; @@ -15,7 +15,7 @@ impl Mirror for T { struct Foo(A, B); impl Foo::Me> { - fn m(b: A) { } + fn m(_: A) { } } fn main() { diff --git a/src/test/ui/no-send-res-ports.rs b/src/test/ui/no-send-res-ports.rs index e10f447365..01fc29713a 100644 --- a/src/test/ui/no-send-res-ports.rs +++ b/src/test/ui/no-send-res-ports.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences use std::thread; use std::rc::Rc; diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index 515b948cc7..dc186f7c85 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -1,14 +1,18 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely - --> $DIR/no-send-res-ports.rs:25:5 + --> $DIR/no-send-res-ports.rs:27:5 | LL | thread::spawn(move|| { | ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | + ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL | - = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` +LL | F: FnOnce() -> T, F: Send + 'static, T: Send + 'static + | ---- required by this bound in `std::thread::spawn` + | + = help: within `[closure@$DIR/no-send-res-ports.rs:27:19: 31:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `Port<()>` = note: required because it appears within the type `main::Foo` - = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6 x:main::Foo]` - = note: required by `std::thread::spawn` + = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:27:19: 31:6 x:main::Foo]` error: aborting due to previous error diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr index 71e3aee919..8a4b2e9c7a 100644 --- a/src/test/ui/no_send-enum.stderr +++ b/src/test/ui/no_send-enum.stderr @@ -1,16 +1,14 @@ error[E0277]: `NoSend` cannot be sent between threads safely --> $DIR/no_send-enum.rs:16:5 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(x); | ^^^ `NoSend` cannot be sent between threads safely | = help: within `Foo`, the trait `std::marker::Send` is not implemented for `NoSend` = note: required because it appears within the type `Foo` -note: required by `bar` - --> $DIR/no_send-enum.rs:12:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr index 2028cf7737..bd646d0509 100644 --- a/src/test/ui/no_send-rc.stderr +++ b/src/test/ui/no_send-rc.stderr @@ -1,15 +1,13 @@ error[E0277]: `std::rc::Rc<{integer}>` cannot be sent between threads safely - --> $DIR/no_send-rc.rs:7:5 + --> $DIR/no_send-rc.rs:7:9 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(x); - | ^^^ `std::rc::Rc<{integer}>` cannot be sent between threads safely + | ^ `std::rc::Rc<{integer}>` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<{integer}>` -note: required by `bar` - --> $DIR/no_send-rc.rs:3:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr index ca4ae054fd..4823852c2f 100644 --- a/src/test/ui/no_send-struct.stderr +++ b/src/test/ui/no_send-struct.stderr @@ -1,15 +1,13 @@ error[E0277]: `Foo` cannot be sent between threads safely - --> $DIR/no_send-struct.rs:15:5 + --> $DIR/no_send-struct.rs:15:9 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(x); - | ^^^ `Foo` cannot be sent between threads safely + | ^ `Foo` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `Foo` -note: required by `bar` - --> $DIR/no_send-struct.rs:11:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr index 64d791d026..f42228ef6a 100644 --- a/src/test/ui/no_share-enum.stderr +++ b/src/test/ui/no_share-enum.stderr @@ -1,16 +1,14 @@ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/no_share-enum.rs:14:5 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `NoSync` = note: required because it appears within the type `Foo` -note: required by `bar` - --> $DIR/no_share-enum.rs:10:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr index fc4bcfb5b3..620b5427b9 100644 --- a/src/test/ui/no_share-struct.stderr +++ b/src/test/ui/no_share-struct.stderr @@ -1,15 +1,13 @@ error[E0277]: `Foo` cannot be shared between threads safely - --> $DIR/no_share-struct.rs:12:5 + --> $DIR/no_share-struct.rs:12:9 | +LL | fn bar(_: T) {} + | --- ---- required by this bound in `bar` +... LL | bar(x); - | ^^^ `Foo` cannot be shared between threads safely + | ^ `Foo` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `Foo` -note: required by `bar` - --> $DIR/no_share-struct.rs:8:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr index 4041e1935d..b05c29c0d4 100644 --- a/src/test/ui/non-copyable-void.stderr +++ b/src/test/ui/non-copyable-void.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for type `libc::c_void` in the curre --> $DIR/non-copyable-void.rs:11:23 | LL | let _z = (*y).clone(); - | ^^^^^ + | ^^^^^ method not found in `libc::c_void` error: aborting due to previous error diff --git a/src/test/ui/non-interger-atomic.rs b/src/test/ui/non-integer-atomic.rs similarity index 100% rename from src/test/ui/non-interger-atomic.rs rename to src/test/ui/non-integer-atomic.rs diff --git a/src/test/ui/non-interger-atomic.stderr b/src/test/ui/non-integer-atomic.stderr similarity index 83% rename from src/test/ui/non-interger-atomic.stderr rename to src/test/ui/non-integer-atomic.stderr index 7d1130d238..b3cf788d83 100644 --- a/src/test/ui/non-interger-atomic.stderr +++ b/src/test/ui/non-integer-atomic.stderr @@ -1,95 +1,95 @@ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:13:5 + --> $DIR/non-integer-atomic.rs:13:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:18:5 + --> $DIR/non-integer-atomic.rs:18:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:23:5 + --> $DIR/non-integer-atomic.rs:23:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:28:5 + --> $DIR/non-integer-atomic.rs:28:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:33:5 + --> $DIR/non-integer-atomic.rs:33:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:38:5 + --> $DIR/non-integer-atomic.rs:38:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:43:5 + --> $DIR/non-integer-atomic.rs:43:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:48:5 + --> $DIR/non-integer-atomic.rs:48:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:53:5 + --> $DIR/non-integer-atomic.rs:53:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:58:5 + --> $DIR/non-integer-atomic.rs:58:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:63:5 + --> $DIR/non-integer-atomic.rs:63:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:68:5 + --> $DIR/non-integer-atomic.rs:68:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:73:5 + --> $DIR/non-integer-atomic.rs:73:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:78:5 + --> $DIR/non-integer-atomic.rs:78:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:83:5 + --> $DIR/non-integer-atomic.rs:83:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:88:5 + --> $DIR/non-integer-atomic.rs:88:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index eb47a33a72..c1c5021138 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -5,7 +5,7 @@ LL | struct Foo { | ---------- method `clone` not found for this ... LL | let _y = x.clone(); - | ^^^^^ + | ^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/not-panic/not-panic-safe-2.stderr b/src/test/ui/not-panic/not-panic-safe-2.stderr index 4db127a463..6668d2d0db 100644 --- a/src/test/ui/not-panic/not-panic-safe-2.stderr +++ b/src/test/ui/not-panic/not-panic-safe-2.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-2.rs:10:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc>` -note: required by `assert` - --> $DIR/not-panic-safe-2.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-2.rs:10:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::>>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc>` -note: required by `assert` - --> $DIR/not-panic-safe-2.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-3.stderr b/src/test/ui/not-panic/not-panic-safe-3.stderr index 1f87f20f2e..c23b08fc9e 100644 --- a/src/test/ui/not-panic/not-panic-safe-3.stderr +++ b/src/test/ui/not-panic/not-panic-safe-3.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-3.rs:10:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc>` -note: required by `assert` - --> $DIR/not-panic-safe-3.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-3.rs:10:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::>>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc>` -note: required by `assert` - --> $DIR/not-panic-safe-3.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-4.stderr b/src/test/ui/not-panic/not-panic-safe-4.stderr index 24f6490029..916804a834 100644 --- a/src/test/ui/not-panic/not-panic-safe-4.stderr +++ b/src/test/ui/not-panic/not-panic-safe-4.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-4.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-4.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-4.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::<&RefCell>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-4.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-5.stderr b/src/test/ui/not-panic/not-panic-safe-5.stderr index a603acb2f1..d5c189723f 100644 --- a/src/test/ui/not-panic/not-panic-safe-5.stderr +++ b/src/test/ui/not-panic/not-panic-safe-5.stderr @@ -1,16 +1,14 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-5.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<*const UnsafeCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*const std::cell::UnsafeCell` -note: required by `assert` - --> $DIR/not-panic-safe-5.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/not-panic/not-panic-safe-6.stderr b/src/test/ui/not-panic/not-panic-safe-6.stderr index a4c75ec7c6..c8013a836a 100644 --- a/src/test/ui/not-panic/not-panic-safe-6.stderr +++ b/src/test/ui/not-panic/not-panic-safe-6.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-6.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-6.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-6.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::<*mut RefCell>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-6.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index 2d12e697d5..aa18b92304 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -1,15 +1,13 @@ error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary --> $DIR/not-panic-safe.rs:9:5 | +LL | fn assert() {} + | ------ ---------- required by this bound in `assert` +... LL | assert::<&mut i32>(); | ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary | = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32` -note: required by `assert` - --> $DIR/not-panic-safe.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/not-sync.stderr b/src/test/ui/not-sync.stderr index d102528bc6..8bb4ce2e2c 100644 --- a/src/test/ui/not-sync.stderr +++ b/src/test/ui/not-sync.stderr @@ -1,80 +1,68 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely - --> $DIR/not-sync.rs:8:5 + --> $DIR/not-sync.rs:8:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely + | ^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::RefCell` cannot be shared between threads safely - --> $DIR/not-sync.rs:10:5 + --> $DIR/not-sync.rs:10:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely + | ^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely - --> $DIR/not-sync.rs:13:5 + --> $DIR/not-sync.rs:13:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be shared between threads safely + | ^^^^^^^ `std::rc::Rc` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Weak` cannot be shared between threads safely - --> $DIR/not-sync.rs:15:5 + --> $DIR/not-sync.rs:15:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^^^ `std::rc::Weak` cannot be shared between threads safely + | ^^^^^^^^^ `std::rc::Weak` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Weak` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::sync::mpsc::Receiver` cannot be shared between threads safely - --> $DIR/not-sync.rs:18:5 + --> $DIR/not-sync.rs:18:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Receiver` cannot be shared between threads safely + | ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::sync::mpsc::Sender` cannot be shared between threads safely - --> $DIR/not-sync.rs:20:5 + --> $DIR/not-sync.rs:20:12 | +LL | fn test() {} + | ---- ---- required by this bound in `test` +... LL | test::>(); - | ^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender` cannot be shared between threads safely + | ^^^^^^^^^^^ `std::sync::mpsc::Sender` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr index 288ce9682c..7ac199d094 100644 --- a/src/test/ui/object-does-not-impl-trait.stderr +++ b/src/test/ui/object-does-not-impl-trait.stderr @@ -1,14 +1,10 @@ error[E0277]: the trait bound `std::boxed::Box: Foo` is not satisfied - --> $DIR/object-does-not-impl-trait.rs:6:35 - | -LL | fn take_object(f: Box) { take_foo(f); } - | ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box` - | -note: required by `take_foo` - --> $DIR/object-does-not-impl-trait.rs:5:1 + --> $DIR/object-does-not-impl-trait.rs:6:44 | LL | fn take_foo(f: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | -------- --- required by this bound in `take_foo` +LL | fn take_object(f: Box) { take_foo(f); } + | ^ the trait `Foo` is not implemented for `std::boxed::Box` error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs new file mode 100644 index 0000000000..7337383e29 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs @@ -0,0 +1,27 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr new file mode 100644 index 0000000000..9dbf7a78ed --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs new file mode 100644 index 0000000000..2a7415174f --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs @@ -0,0 +1,30 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: 'a + ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'a`. Or, we *should*, but the +// current code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + + // If it weren't for the conservative path above, we'd expect an + // error here. + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr new file mode 100644 index 0000000000..d069f52ce4 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs new file mode 100644 index 0000000000..51be999a63 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs @@ -0,0 +1,23 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +fn is_static(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar(x: &str) -> &dyn Foo { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr new file mode 100644 index 0000000000..9c7b6b98f2 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36 + | +LL | fn bar(x: &str) -> &dyn Foo { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs new file mode 100644 index 0000000000..339f3356bd --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs @@ -0,0 +1,28 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'static`, and not `&'x dyn Foo`. +fn bar(x: &str) -> &dyn Foo { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 0c7e4e991a..2df628ecf8 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `owned` found for type `&dyn Foo` in the current s --> $DIR/object-pointer-types.rs:11:7 | LL | x.owned(); - | ^^^^^ + | ^^^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `owned`, perhaps you need to implement it: @@ -12,7 +12,7 @@ error[E0599]: no method named `owned` found for type `&mut dyn Foo` in the curre --> $DIR/object-pointer-types.rs:17:7 | LL | x.owned(); - | ^^^^^ + | ^^^^^ method not found in `&mut dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `owned`, perhaps you need to implement it: @@ -22,7 +22,7 @@ error[E0599]: no method named `managed` found for type `std::boxed::Box<(dyn Foo --> $DIR/object-pointer-types.rs:23:7 | LL | x.managed(); - | ^^^^^^^ + | ^^^^^^^ method not found in `std::boxed::Box<(dyn Foo + 'static)>` error: aborting due to 3 previous errors diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr index 55f9e3f9f1..7d5aa00356 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-associated-consts.rs:9:1 | +LL | const X: usize; + | - the trait cannot contain associated consts like `X` +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: the trait cannot contain associated consts like `X` error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.stderr index d66cdb9844..b25e0052e4 100644 --- a/src/test/ui/object-safety/object-safety-generics.stderr +++ b/src/test/ui/object-safety/object-safety-generics.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:14:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:19:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr index c0c471c2b1..971e79cb02 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:17:1 | +LL | fn bar(&self, x: &Self); + | --- method `bar` references the `Self` type in its parameters or return type +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:22:1 | +LL | fn bar(&self) -> Self; + | --- method `bar` references the `Self` type in its parameters or return type +... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr index da8dd657c2..0de783f60e 100644 --- a/src/test/ui/object-safety/object-safety-no-static.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/object-safety-no-static.rs:8:1 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | fn foo_implicit(b: Box) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: method `foo` has no receiver error: aborting due to previous error diff --git a/src/test/ui/obsolete-in-place/bad.rs b/src/test/ui/obsolete-in-place/bad.rs index 3530862f76..a491bb21a5 100644 --- a/src/test/ui/obsolete-in-place/bad.rs +++ b/src/test/ui/obsolete-in-place/bad.rs @@ -2,7 +2,7 @@ fn foo() { let (x, y) = (0, 0); - x <- y; //~ ERROR expected one of + x <- y; //~ ERROR unexpected token: `<-` } fn main() { diff --git a/src/test/ui/obsolete-in-place/bad.stderr b/src/test/ui/obsolete-in-place/bad.stderr index 373b7ea421..8a731b6240 100644 --- a/src/test/ui/obsolete-in-place/bad.stderr +++ b/src/test/ui/obsolete-in-place/bad.stderr @@ -1,8 +1,12 @@ -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `<-` +error: unexpected token: `<-` --> $DIR/bad.rs:5:7 | LL | x <- y; - | ^^ expected one of 8 possible tokens here + | ^^ +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | x < - y; + | ^^^ error: expected expression, found keyword `in` --> $DIR/bad.rs:10:5 diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 5d5db21f72..f0651c4cde 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -1,21 +1,41 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/multiple-impls.rs:33:5 + --> $DIR/multiple-impls.rs:33:18 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^ trait message + | ^^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:36:18 | LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------------------- required by `Index::index` +... +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:39:18 + | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 | LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | ^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` @@ -26,19 +46,6 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:36:5 - | -LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo - | - = help: the trait `Index>` is not implemented for `[i32]` error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:5 @@ -47,19 +54,6 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:39:5 - | -LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar - | - = help: the trait `Index>` is not implemented for `[i32]` error: aborting due to 6 previous errors diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 79cf22f609..f19fa8a07f 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -1,21 +1,19 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/on-impl.rs:22:5 + --> $DIR/on-impl.rs:22:25 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/on-impl.rs:9:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 | LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr index ece8dee0af..8fe7ed4a20 100644 --- a/src/test/ui/on-unimplemented/on-trait.stderr +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -1,28 +1,24 @@ error[E0277]: the trait bound `std::option::Option>: MyFromIterator<&u8>` is not satisfied --> $DIR/on-trait.rs:28:30 | +LL | fn collect, B: MyFromIterator>(it: I) -> B { + | ------- ----------------- required by this bound in `collect` +... LL | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() | ^^^^^^^ a collection of type `std::option::Option>` cannot be built from an iterator over elements of type `&u8` | = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option>` -note: required by `collect` - --> $DIR/on-trait.rs:22:1 - | -LL | fn collect, B: MyFromIterator>(it: I) -> B { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: Bar::Foo` is not satisfied --> $DIR/on-trait.rs:31:21 | +LL | fn foobar>() -> T { + | ------ --------------- required by this bound in `foobar` +... LL | let x: String = foobar(); | ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` | = help: the trait `Bar::Foo` is not implemented for `std::string::String` -note: required by `foobar` - --> $DIR/on-trait.rs:12:1 - | -LL | fn foobar>() -> T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/or-patterns/already-bound-name.rs b/src/test/ui/or-patterns/already-bound-name.rs new file mode 100644 index 0000000000..3ebf59c643 --- /dev/null +++ b/src/test/ui/or-patterns/already-bound-name.rs @@ -0,0 +1,46 @@ +// This test ensures that the "already bound identifier in a product pattern" +// correctly accounts for or-patterns. + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete + +enum E { A(T, T), B(T) } + +use E::*; + +fn main() { + let (a, a) = (0, 1); // Standard duplication without an or-pattern. + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let (a, A(a, _) | B(a)) = (0, A(1, 2)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + + let (A(a, _) | B(a), a) = (A(0, 1), 2); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let A(a, a) | B(a) = A(0, 1); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let B(a) | A(a, a) = A(0, 1); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + match A(0, 1) { + B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. + //~^ ERROR identifier `a` is bound more than once in the same pattern + } + + let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR mismatched types + + let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR variable `a` is not bound in all patterns + + let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern +} diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr new file mode 100644 index 0000000000..360699a873 --- /dev/null +++ b/src/test/ui/or-patterns/already-bound-name.stderr @@ -0,0 +1,105 @@ +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:12:13 + | +LL | let (a, a) = (0, 1); // Standard duplication without an or-pattern. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:15:15 + | +LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:15:25 + | +LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:19:26 + | +LL | let (A(a, _) | B(a), a) = (A(0, 1), 2); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:22:14 + | +LL | let A(a, a) | B(a) = A(0, 1); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:25:21 + | +LL | let B(a) | A(a, a) = A(0, 1); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:29:21 + | +LL | B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:33:36 + | +LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:33:46 + | +LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:38:36 + | +LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:38:46 + | +LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/already-bound-name.rs:38:9 + | +LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + | ^^^^ pattern doesn't bind `a` - variable not in all patterns + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:43:49 + | +LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:43:59 + | +LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + | ^ used in a pattern more than once + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/already-bound-name.rs:4:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/already-bound-name.rs:33:31 + | +LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + | ^ expected integer, found enum `E` + | + = note: expected type `{integer}` + found type `E<{integer}>` + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0308, E0408, E0416. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/consistent-bindings.rs b/src/test/ui/or-patterns/consistent-bindings.rs new file mode 100644 index 0000000000..0eb539dca4 --- /dev/null +++ b/src/test/ui/or-patterns/consistent-bindings.rs @@ -0,0 +1,46 @@ +// Check that or-patterns with consistent bindings across arms are allowed. + +// edition:2018 + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete + +fn main() { + // One level: + let Ok(a) | Err(a) = Ok(0); + let Ok(ref a) | Err(ref a) = Ok(0); + let Ok(ref mut a) | Err(ref mut a) = Ok(0); + + // Two levels: + enum Tri { V1(S), V2(T), V3(U) } + use Tri::*; + + let Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b))) + : Result<_, Result<_, _>> + = Ok((V1(1), 1)); + + let Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b))) + : Result<_, Result<_, _>> + = Ok((V1(1), 1)); + + // Three levels: + let ( + a, + Err((ref mut b, ref c, d)) | + Ok(( + Ok( + V1((ref c, d)) | + V2((d, ref c)) | + V3((ref c, Ok((_, d)) | Err((d, _)))) + ) | + Err((ref c, d)), + ref mut b + )) + ) = + (1, Ok((Ok(V3((1, Ok((1, 1))))), 1))); + + // FIXME(or_patterns; Centril | dlrobertson): remove this line below and + // change this test to check-pass once MIR can handle or-patterns with bindings. + let () = 0; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/or-patterns/consistent-bindings.stderr b/src/test/ui/or-patterns/consistent-bindings.stderr new file mode 100644 index 0000000000..7f5e670c25 --- /dev/null +++ b/src/test/ui/or-patterns/consistent-bindings.stderr @@ -0,0 +1,20 @@ +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/consistent-bindings.rs:5:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/consistent-bindings.rs:44:9 + | +LL | let () = 0; + | ^^ expected integer, found () + | + = note: expected type `{integer}` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs new file mode 100644 index 0000000000..de8e1bba55 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs @@ -0,0 +1,8 @@ +// Test feature gating for a sole leading `|` in `let`. + +fn main() {} + +#[cfg(FALSE)] +fn gated_leading_vert_in_let() { + for | A in 0 {} //~ ERROR or-patterns syntax is experimental +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr new file mode 100644 index 0000000000..f520409e8b --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns-leading-for.rs:7:9 + | +LL | for | A in 0 {} + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs new file mode 100644 index 0000000000..a4ea4e25d8 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs @@ -0,0 +1,8 @@ +// Test feature gating for a sole leading `|` in `let`. + +fn main() {} + +#[cfg(FALSE)] +fn gated_leading_vert_in_let() { + let | A; //~ ERROR or-patterns syntax is experimental +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr new file mode 100644 index 0000000000..30fd6a1a95 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 + | +LL | let | A; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs new file mode 100644 index 0000000000..e638838147 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.rs @@ -0,0 +1,52 @@ +fn main() {} + +pub fn example(x: Option) { + match x { + Some(0 | 1 | 2) => {} + //~^ ERROR: or-patterns syntax is experimental + _ => {} + } +} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!((p | q)); //~ ERROR or-patterns syntax is experimental +accept_pat!((p | q,)); //~ ERROR or-patterns syntax is experimental +accept_pat!(TS(p | q)); //~ ERROR or-patterns syntax is experimental +accept_pat!(NS { f: p | q }); //~ ERROR or-patterns syntax is experimental +accept_pat!([p | q]); //~ ERROR or-patterns syntax is experimental + +// Non-macro tests: + +#[cfg(FALSE)] +fn or_patterns() { + // Gated: + + let | A | B; //~ ERROR or-patterns syntax is experimental + let A | B; //~ ERROR or-patterns syntax is experimental + for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental + for A | B in 0 {} //~ ERROR or-patterns syntax is experimental + fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental + let _ = |(A | B): u8| (); //~ ERROR or-patterns syntax is experimental + let (A | B); //~ ERROR or-patterns syntax is experimental + let (A | B,); //~ ERROR or-patterns syntax is experimental + let A(B | C); //~ ERROR or-patterns syntax is experimental + let E::V(B | C); //~ ERROR or-patterns syntax is experimental + let S { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental + let E::V { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental + let [A | B]; //~ ERROR or-patterns syntax is experimental + + // Top level of `while`, `if`, and `match` arms are allowed: + + while let | A = 0 {} + while let A | B = 0 {} + if let | A = 0 {} + if let A | B = 0 {} + match 0 { + | A => {}, + A | B => {}, + } +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr new file mode 100644 index 0000000000..aae6644dac --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr @@ -0,0 +1,174 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:5:14 + | +LL | Some(0 | 1 | 2) => {} + | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:28:11 + | +LL | let | A | B; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:29:9 + | +LL | let A | B; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:30:11 + | +LL | for | A | B in 0 {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:31:9 + | +LL | for A | B in 0 {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:32:13 + | +LL | fn fun((A | B): _) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:33:15 + | +LL | let _ = |(A | B): u8| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:34:10 + | +LL | let (A | B); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:35:10 + | +LL | let (A | B,); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:36:11 + | +LL | let A(B | C); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:37:14 + | +LL | let E::V(B | C); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:38:17 + | +LL | let S { f1: B | C, f2 }; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:39:20 + | +LL | let E::V { f1: B | C, f2 }; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:40:10 + | +LL | let [A | B]; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:16:14 + | +LL | accept_pat!((p | q)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:17:14 + | +LL | accept_pat!((p | q,)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:18:16 + | +LL | accept_pat!(TS(p | q)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:19:21 + | +LL | accept_pat!(NS { f: p | q }); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:20:14 + | +LL | accept_pat!([p | q]); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to 19 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed new file mode 100644 index 0000000000..08730fe8b0 --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed @@ -0,0 +1,14 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.rs b/src/test/ui/or-patterns/fn-param-wrap-parens.rs new file mode 100644 index 0000000000..ed667e0e66 --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.rs @@ -0,0 +1,14 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr new file mode 100644 index 0000000000..2c6e4d9838 --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr @@ -0,0 +1,8 @@ +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/fn-param-wrap-parens.rs:14:9 + | +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` + +error: aborting due to previous error + diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs new file mode 100644 index 0000000000..44836893ea --- /dev/null +++ b/src/test/ui/or-patterns/inconsistent-modes.rs @@ -0,0 +1,28 @@ +// This test ensures that or patterns require binding mode consistency across arms. + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete + +#![allow(non_camel_case_types)] +fn main() { + // One level: + let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); + //~^ ERROR variable `a` is bound in inconsistent ways + let Ok(ref mut a) | Err(a): Result = Ok(0); + //~^ ERROR variable `a` is bound in inconsistent ways + let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); + //~^ ERROR variable `a` is bound in inconsistent ways + //~| ERROR mismatched types + let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + //~^ ERROR variable `a` is bound in inconsistent ways + //~| ERROR variable `b` is bound in inconsistent ways + //~| ERROR mismatched types + + // Two levels: + let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); + //~^ ERROR variable `a` is bound in inconsistent ways + + // Three levels: + let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1); + //~^ ERROR variable `a` is bound in inconsistent ways +} diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr new file mode 100644 index 0000000000..0a36ed5548 --- /dev/null +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -0,0 +1,80 @@ +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:9:25 + | +LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:11:29 + | +LL | let Ok(ref mut a) | Err(a): Result = Ok(0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:13:33 + | +LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); + | - first binding ^ bound in different ways + +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:16:39 + | +LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + | - first binding ^ bound in different ways + +error[E0409]: variable `b` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:16:46 + | +LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + | - first binding ^ bound in different ways + +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:22:38 + | +LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound in inconsistent ways within the same match arm + --> $DIR/inconsistent-modes.rs:26:34 + | +LL | let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1); + | - ^ bound in different ways + | | + | first binding + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/inconsistent-modes.rs:3:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/inconsistent-modes.rs:13:25 + | +LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); + | ^^^^^^^^^ types differ in mutability + | + = note: expected type `&&u8` + found type `&mut &mut u8` + +error[E0308]: mismatched types + --> $DIR/inconsistent-modes.rs:16:31 + | +LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + | ^^^^^^^^^ types differ in mutability + | + = note: expected type `&{integer}` + found type `&mut _` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/missing-bindings.rs b/src/test/ui/or-patterns/missing-bindings.rs new file mode 100644 index 0000000000..b065028e7a --- /dev/null +++ b/src/test/ui/or-patterns/missing-bindings.rs @@ -0,0 +1,84 @@ +// This test ensures that or patterns do not allow missing bindings in any of the arms. + +// edition:2018 + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete + +#![allow(non_camel_case_types)] + +fn main() {} + +fn check_handling_of_paths() { + mod bar { + pub enum foo { + alpha, + beta, + charlie + } + } + + use bar::foo::{alpha, charlie}; + let alpha | beta | charlie = alpha; //~ ERROR variable `beta` is not bound in all patterns + match Some(alpha) { + Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns + } +} + +fn check_misc_nesting() { + enum E { A(T, T), B(T) } + use E::*; + enum Vars3 { V1(S), V2(T), V3(U) } + use Vars3::*; + + // One level: + const X: E = B(0); + let A(a, _) | _ = X; //~ ERROR variable `a` is not bound in all patterns + let _ | B(a) = X; //~ ERROR variable `a` is not bound in all patterns + let A(..) | B(a) = X; //~ ERROR variable `a` is not bound in all patterns + let A(a, _) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns + let A(_, a) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns + let A(a, b) | B(a) = X; //~ ERROR variable `b` is not bound in all patterns + + // Two levels: + const Y: E> = B(B(0)); + let A(A(..) | B(_), _) | B(a) = Y; //~ ERROR variable `a` is not bound in all patterns + let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; + //~^ ERROR variable `a` is not bound in all patterns + let A(A(a, b) | B(c), d) | B(e) = Y; + //~^ ERROR variable `a` is not bound in all patterns + //~| ERROR variable `a` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + //~| ERROR variable `d` is not bound in all patterns + //~| ERROR variable `e` is not bound in all patterns + + // Three levels: + let ( + V1( + //~^ ERROR variable `b` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + A( + Ok(a) | Err(_), //~ ERROR variable `a` is not bound in all patterns + _ + ) | + B(Ok(a) | Err(a)) + ) | + V2( + A( + A(_, a) | //~ ERROR variable `b` is not bound in all patterns + B(b), //~ ERROR variable `a` is not bound in all patterns + _ + ) | + B(_) + //~^ ERROR variable `a` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + ) | + V3(c), + //~^ ERROR variable `a` is not bound in all patterns + ) + : (Vars3>, E>, u8>,) + = (V3(0),); +} diff --git a/src/test/ui/or-patterns/missing-bindings.stderr b/src/test/ui/or-patterns/missing-bindings.stderr new file mode 100644 index 0000000000..c73af7a42e --- /dev/null +++ b/src/test/ui/or-patterns/missing-bindings.stderr @@ -0,0 +1,250 @@ +error[E0408]: variable `beta` is not bound in all patterns + --> $DIR/missing-bindings.rs:22:9 + | +LL | let alpha | beta | charlie = alpha; + | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` + | | | + | | variable not in all patterns + | pattern doesn't bind `beta` + +error[E0408]: variable `beta` is not bound in all patterns + --> $DIR/missing-bindings.rs:24:14 + | +LL | Some(alpha | beta) => {} + | ^^^^^ ---- variable not in all patterns + | | + | pattern doesn't bind `beta` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:36:19 + | +LL | let A(a, _) | _ = X; + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:37:9 + | +LL | let _ | B(a) = X; + | ^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:38:9 + | +LL | let A(..) | B(a) = X; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:39:19 + | +LL | let A(a, _) | B(_) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:40:19 + | +LL | let A(_, a) | B(_) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:41:19 + | +LL | let A(a, b) | B(a) = X; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:9 + | +LL | let A(A(..) | B(_), _) | B(a) = Y; + | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:46:11 + | +LL | let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:21 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:21 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:11 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | ^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `c` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:32 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:32 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:32 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns + +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:32 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | - ^^^^ pattern doesn't bind `d` + | | + | variable not in all patterns + +error[E0408]: variable `e` is not bound in all patterns + --> $DIR/missing-bindings.rs:48:9 + | +LL | let A(A(a, b) | B(c), d) | B(e) = Y; + | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `e` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:64:29 + | +LL | Ok(a) | Err(_), + | - ^^^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:72:21 + | +LL | A(_, a) | + | - variable not in all patterns +LL | B(b), + | ^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:71:21 + | +LL | A(_, a) | + | ^^^^^^^ pattern doesn't bind `b` +LL | B(b), + | - variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:75:17 + | +LL | A(_, a) | + | - variable not in all patterns +... +LL | B(_) + | ^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:75:17 + | +LL | B(b), + | - variable not in all patterns +... +LL | B(_) + | ^^^^ pattern doesn't bind `b` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:79:13 + | +LL | B(Ok(a) | Err(a)) + | - variable not in all patterns +... +LL | A(_, a) | + | - variable not in all patterns +... +LL | V3(c), + | ^^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:60:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `b` +... +LL | B(b), + | - variable not in all patterns +... +LL | V3(c), + | ^^^^^ pattern doesn't bind `b` + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:60:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | / V2( +LL | | A( +LL | | A(_, a) | +LL | | B(b), +... | +LL | | +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | V3(c), + | - variable not in all patterns + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/missing-bindings.rs:5:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.rs b/src/test/ui/or-patterns/multiple-pattern-typo.rs new file mode 100644 index 0000000000..e308c0adb4 --- /dev/null +++ b/src/test/ui/or-patterns/multiple-pattern-typo.rs @@ -0,0 +1,45 @@ +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete and may cause the compiler to crash + +fn main() { + let x = 3; + + match x { + 1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match x { + (1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match (x,) { + (1 | 2 || 3,) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + struct TS(u8); + + match TS(x) { + TS(1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + struct NS { f: u8 } + + match (NS { f: x }) { + NS { f: 1 | 2 || 3 } => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match [x] { + [1 | 2 || 3] => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match x { + || 1 | 2 | 3 => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } +} diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr new file mode 100644 index 0000000000..c61b5cb208 --- /dev/null +++ b/src/test/ui/or-patterns/multiple-pattern-typo.stderr @@ -0,0 +1,52 @@ +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:8:15 + | +LL | 1 | 2 || 3 => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:13:16 + | +LL | (1 | 2 || 3) => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:18:16 + | +LL | (1 | 2 || 3,) => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:25:18 + | +LL | TS(1 | 2 || 3) => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:32:23 + | +LL | NS { f: 1 | 2 || 3 } => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:37:16 + | +LL | [1 | 2 || 3] => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:42:9 + | +LL | || 1 | 2 | 3 => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/multiple-pattern-typo.rs:1:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/or-pattern-mismatch.rs b/src/test/ui/or-patterns/or-pattern-mismatch.rs similarity index 100% rename from src/test/ui/or-pattern-mismatch.rs rename to src/test/ui/or-patterns/or-pattern-mismatch.rs diff --git a/src/test/ui/or-pattern-mismatch.stderr b/src/test/ui/or-patterns/or-pattern-mismatch.stderr similarity index 100% rename from src/test/ui/or-pattern-mismatch.stderr rename to src/test/ui/or-patterns/or-pattern-mismatch.stderr diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs new file mode 100644 index 0000000000..b676ea851a --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -0,0 +1,53 @@ +// Test some cases where or-patterns may ostensibly be allowed but are in fact not. +// This is not a semantic test. We only test parsing. + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete and may cause the compiler to crash + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!(p | q); //~ ERROR no rules expected the token `|` +accept_pat!(| p | q); //~ ERROR no rules expected the token `|` + +// Non-macro tests: + +enum E { A, B } +use E::*; + +fn no_top_level_or_patterns() { + // We do *not* allow or-patterns at the top level of lambdas... + let _ = |A | B: E| (); //~ ERROR binary operation `|` cannot be applied to type `E` + // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. + + // ...and for now neither do we allow or-patterns at the top level of functions. + fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis + + fn fun2(| A | B: E) {} + //~^ ERROR a leading `|` is not allowed in a parameter pattern + //~| ERROR an or-pattern parameter must be wrapped in parenthesis +} + +// We also do not allow a leading `|` when not in a top level position: + +fn no_leading_inner() { + struct TS(E); + struct NS { f: E } + + let ( | A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( | A | B,) = (E::B,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ | A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( | A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: | A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let ( || A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ || A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( || A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: || A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let recovery_witness: String = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr new file mode 100644 index 0000000000..2a3a6abfb7 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -0,0 +1,124 @@ +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/or-patterns-syntactic-fail.rs:28:13 + | +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` + +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/or-patterns-syntactic-fail.rs:30:13 + | +LL | fn fun2(| A | B: E) {} + | ^ help: remove the `|` + +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/or-patterns-syntactic-fail.rs:30:15 + | +LL | fn fun2(| A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:41:11 + | +LL | let ( | A | B) = E::A; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:42:11 + | +LL | let ( | A | B,) = (E::B,); + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:43:11 + | +LL | let [ | A | B ] = [E::A]; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:44:13 + | +LL | let TS( | A | B ); + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:45:17 + | +LL | let NS { f: | A | B }; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:47:11 + | +LL | let ( || A | B) = E::A; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:48:11 + | +LL | let [ || A | B ] = [E::A]; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:49:13 + | +LL | let TS( || A | B ); + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:50:17 + | +LL | let NS { f: || A | B }; + | ^^ help: remove the `||` + +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail.rs:14:15 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(p | q); + | ^ no rules expected this token in macro call + +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail.rs:15:13 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(| p | q); + | ^ no rules expected this token in macro call + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/or-patterns-syntactic-fail.rs:4:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0369]: binary operation `|` cannot be applied to type `E` + --> $DIR/or-patterns-syntactic-fail.rs:24:22 + | +LL | let _ = |A | B: E| (); + | ----^ -- () + | | + | E + | + = note: an implementation of `std::ops::BitOr` might be missing for `E` + +error[E0308]: mismatched types + --> $DIR/or-patterns-syntactic-fail.rs:52:36 + | +LL | let recovery_witness: String = 0; + | ^ + | | + | expected struct `std::string::String`, found integer + | help: try using a conversion method: `0.to_string()` + | + = note: expected type `std::string::String` + found type `{integer}` + +error: aborting due to 16 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs new file mode 100644 index 0000000000..5fe72caf9c --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -0,0 +1,78 @@ +// Here we test all the places `|` is *syntactically* allowed. +// This is not a semantic test. We only test parsing. + +// check-pass + +#![feature(or_patterns)] + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!((p | q)); +accept_pat!((p | q,)); +accept_pat!(TS(p | q)); +accept_pat!(NS { f: p | q }); +accept_pat!([p | q]); + +// Non-macro tests: + +#[cfg(FALSE)] +fn or_patterns() { + // Top level of `let`: + let | A | B; + let A | B; + let A | B: u8; + let A | B = 0; + let A | B: u8 = 0; + + // Top level of `for`: + for | A | B in 0 {} + for A | B in 0 {} + + // Top level of `while`: + while let | A | B = 0 {} + while let A | B = 0 {} + + // Top level of `if`: + if let | A | B = 0 {} + if let A | B = 0 {} + + // Top level of `match` arms: + match 0 { + | A | B => {}, + A | B => {}, + } + + // Functions: + fn fun((A | B): _) {} + + // Lambdas: + let _ = |(A | B): u8| (); + + // Parenthesis and tuple patterns: + let (A | B); + let (A | B,); + + // Tuple struct patterns: + let A(B | C); + let E::V(B | C); + + // Struct patterns: + let S { f1: B | C, f2 }; + let E::V { f1: B | C, f2 }; + + // Slice patterns: + let [A | B, .. | ..]; + + // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: + let box 0 | 1; // Unstable; we *can* the precedence if we want. + let &0 | 1; + let &mut 0 | 1; + let x @ 0 | 1; + let ref x @ 0 | 1; + let ref mut x @ 0 | 1; +} diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr new file mode 100644 index 0000000000..3145a2e9f2 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr @@ -0,0 +1,8 @@ +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/or-patterns-syntactic-pass.rs:6:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed new file mode 100644 index 0000000000..e96d76061a --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -0,0 +1,23 @@ +// Test the suggestion to remove a leading `|`. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading_vert() { + fn fun1( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + fn fun2( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + let ( A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern +} diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs new file mode 100644 index 0000000000..3790b17553 --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -0,0 +1,23 @@ +// Test the suggestion to remove a leading `|`. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading_vert() { + fn fun1( | A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + fn fun2( || A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + let ( | A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( || A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( | A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ | A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ || A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( | A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( || A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: | A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: || A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern +} diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr new file mode 100644 index 0000000000..cbe06f9972 --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -0,0 +1,68 @@ +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/remove-leading-vert.rs:12:14 + | +LL | fn fun1( | A: E) {} + | ^ help: remove the `|` + +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/remove-leading-vert.rs:13:14 + | +LL | fn fun2( || A: E) {} + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:14:11 + | +LL | let ( | A): E; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:15:11 + | +LL | let ( || A): (E); + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:16:11 + | +LL | let ( | A,): (E,); + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:17:11 + | +LL | let [ | A ]: [E; 1]; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:18:11 + | +LL | let [ || A ]: [E; 1]; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:19:13 + | +LL | let TS( | A ): TS; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:20:13 + | +LL | let TS( || A ): TS; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:21:17 + | +LL | let NS { f: | A }: NS; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:22:17 + | +LL | let NS { f: || A }: NS; + | ^^ help: remove the `||` + +error: aborting due to 11 previous errors + diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs new file mode 100644 index 0000000000..b9bfb8638b --- /dev/null +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -0,0 +1,9 @@ +// Test the parser for the "while parsing this or-pattern..." label here. + +fn main() { + match Some(42) { + Some(42) | .=. => {} //~ ERROR expected pattern, found `.` + //~^ while parsing this or-pattern starting here + //~| NOTE expected pattern + } +} diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr new file mode 100644 index 0000000000..7ad62ff99e --- /dev/null +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -0,0 +1,10 @@ +error: expected pattern, found `.` + --> $DIR/while-parsing-this-or-pattern.rs:5:20 + | +LL | Some(42) | .=. => {} + | -------- ^ expected pattern + | | + | while parsing this or-pattern starting here + +error: aborting due to previous error + diff --git a/src/test/ui/overlap-marker-trait.stderr b/src/test/ui/overlap-marker-trait.stderr index a59af8dcdb..15ebcd17b0 100644 --- a/src/test/ui/overlap-marker-trait.stderr +++ b/src/test/ui/overlap-marker-trait.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied - --> $DIR/overlap-marker-trait.rs:30:5 - | -LL | is_marker::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` - | -note: required by `is_marker` - --> $DIR/overlap-marker-trait.rs:18:1 + --> $DIR/overlap-marker-trait.rs:30:17 | LL | fn is_marker() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------- ------ required by this bound in `is_marker` +... +LL | is_marker::(); + | ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` error: aborting due to previous error diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs index 21d36048e6..8126525c34 100644 --- a/src/test/ui/parser-recovery-1.rs +++ b/src/test/ui/parser-recovery-1.rs @@ -3,6 +3,7 @@ // Test that we can recover from missing braces in the parser. trait Foo { +//~^ ERROR `main` function not found fn bar() { let x = foo(); //~^ ERROR cannot find function `foo` in this scope diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr index c29f427591..ffe2b3322f 100644 --- a/src/test/ui/parser-recovery-1.stderr +++ b/src/test/ui/parser-recovery-1.stderr @@ -1,8 +1,9 @@ error: this file contains an un-closed delimiter - --> $DIR/parser-recovery-1.rs:15:55 + --> $DIR/parser-recovery-1.rs:16:55 | LL | trait Foo { | - un-closed delimiter +LL | LL | fn bar() { | - this delimiter might not be properly closed... ... @@ -13,26 +14,34 @@ LL | } | ^ error: unexpected token: `;` - --> $DIR/parser-recovery-1.rs:12:15 + --> $DIR/parser-recovery-1.rs:13:15 | LL | let x = y.; | ^ error[E0425]: cannot find function `foo` in this scope - --> $DIR/parser-recovery-1.rs:7:17 + --> $DIR/parser-recovery-1.rs:8:17 | LL | let x = foo(); | ^^^ not found in this scope error[E0425]: cannot find value `y` in this scope - --> $DIR/parser-recovery-1.rs:12:13 + --> $DIR/parser-recovery-1.rs:13:13 | LL | let x = y.; | ^ not found in this scope error[E0601]: `main` function not found in crate `parser_recovery_1` + --> $DIR/parser-recovery-1.rs:5:1 | - = note: consider adding a `main` function to `$DIR/parser-recovery-1.rs` +LL | / trait Foo { +LL | | +LL | | fn bar() { +LL | | let x = foo(); +... | +LL | | +LL | | } + | |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs` error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/assoc-type-in-type-arg.rs b/src/test/ui/parser/assoc-type-in-type-arg.rs new file mode 100644 index 0000000000..000956ea24 --- /dev/null +++ b/src/test/ui/parser/assoc-type-in-type-arg.rs @@ -0,0 +1,11 @@ +trait Tr { + type TrSubtype; +} + +struct Bar<'a, Item: Tr, ::TrSubtype: 'a> { + //~^ ERROR bounds on associated types do not belong here + item: Item, + item_sub: &'a ::TrSubtype, +} + +fn main() {} diff --git a/src/test/ui/parser/assoc-type-in-type-arg.stderr b/src/test/ui/parser/assoc-type-in-type-arg.stderr new file mode 100644 index 0000000000..b637702f21 --- /dev/null +++ b/src/test/ui/parser/assoc-type-in-type-arg.stderr @@ -0,0 +1,8 @@ +error: bounds on associated types do not belong here + --> $DIR/assoc-type-in-type-arg.rs:5:26 + | +LL | struct Bar<'a, Item: Tr, ::TrSubtype: 'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ belongs in `where` clause + +error: aborting due to previous error + diff --git a/src/test/ui/parser/bad-match.rs b/src/test/ui/parser/bad-match.rs index 79bc7eec31..04100d1701 100644 --- a/src/test/ui/parser/bad-match.rs +++ b/src/test/ui/parser/bad-match.rs @@ -1,4 +1,4 @@ fn main() { - let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `x` + let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `x` match x; } diff --git a/src/test/ui/parser/bad-match.stderr b/src/test/ui/parser/bad-match.stderr index 2f29b978e9..d5baaf5e93 100644 --- a/src/test/ui/parser/bad-match.stderr +++ b/src/test/ui/parser/bad-match.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `x` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `x` --> $DIR/bad-match.rs:2:13 | LL | let isize x = 5; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/bad-name.stderr b/src/test/ui/parser/bad-name.stderr index 15e61cf06c..dce4dabedf 100644 --- a/src/test/ui/parser/bad-name.stderr +++ b/src/test/ui/parser/bad-name.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `.` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` --> $DIR/bad-name.rs:4:8 | LL | let x.y::.z foo; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs index 61fae721ff..d805ab7588 100644 --- a/src/test/ui/parser/do-catch-suggests-try.rs +++ b/src/test/ui/parser/do-catch-suggests-try.rs @@ -1,5 +1,5 @@ fn main() { let _: Option<()> = do catch {}; //~^ ERROR found removed `do catch` syntax - //~^^ HELP Following RFC #2388, the new non-placeholder syntax is `try` + //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try` } diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr index 6d13b0f1cc..e151d4cf8a 100644 --- a/src/test/ui/parser/do-catch-suggests-try.stderr +++ b/src/test/ui/parser/do-catch-suggests-try.stderr @@ -4,7 +4,7 @@ error: found removed `do catch` syntax LL | let _: Option<()> = do catch {}; | ^^ | - = help: Following RFC #2388, the new non-placeholder syntax is `try` + = help: following RFC #2388, the new non-placeholder syntax is `try` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs index 405a7e1e2a..c3f478fe42 100644 --- a/src/test/ui/parser/doc-before-semi.rs +++ b/src/test/ui/parser/doc-before-semi.rs @@ -3,4 +3,6 @@ fn main() { //~^ ERROR found a documentation comment that doesn't document anything //~| HELP maybe a comment was intended ; + //~^ WARNING unnecessary trailing semicolon + //~| HELP remove this semicolon } diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr index e6bade18d0..b9ac30b09b 100644 --- a/src/test/ui/parser/doc-before-semi.stderr +++ b/src/test/ui/parser/doc-before-semi.stderr @@ -6,6 +6,14 @@ LL | /// hi | = help: doc comments must come before what they document, maybe a comment was intended with `//`? +warning: unnecessary trailing semicolon + --> $DIR/doc-before-semi.rs:5:5 + | +LL | ; + | ^ help: remove this semicolon + | + = note: `#[warn(redundant_semicolon)]` on by default + error: aborting due to previous error For more information about this error, try `rustc --explain E0585`. diff --git a/src/test/ui/parser/fn-arg-doc-comment.rs b/src/test/ui/parser/fn-arg-doc-comment.rs index 4a4f959e21..995eb62d0b 100644 --- a/src/test/ui/parser/fn-arg-doc-comment.rs +++ b/src/test/ui/parser/fn-arg-doc-comment.rs @@ -2,14 +2,10 @@ pub fn f( /// Comment //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here - //~| ERROR attributes on function parameters are unstable - //~| NOTE https://github.com/rust-lang/rust/issues/60406 id: u8, /// Other //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here - //~| ERROR attributes on function parameters are unstable - //~| NOTE https://github.com/rust-lang/rust/issues/60406 a: u8, ) {} diff --git a/src/test/ui/parser/fn-arg-doc-comment.stderr b/src/test/ui/parser/fn-arg-doc-comment.stderr index d8884de1fe..669785af45 100644 --- a/src/test/ui/parser/fn-arg-doc-comment.stderr +++ b/src/test/ui/parser/fn-arg-doc-comment.stderr @@ -1,5 +1,5 @@ error: attributes cannot be applied to a function parameter's type - --> $DIR/fn-arg-doc-comment.rs:16:12 + --> $DIR/fn-arg-doc-comment.rs:12:12 | LL | fn bar(id: #[allow(dead_code)] i32) {} | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here @@ -11,31 +11,13 @@ LL | /// Comment | ^^^^^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/fn-arg-doc-comment.rs:8:5 + --> $DIR/fn-arg-doc-comment.rs:6:5 | LL | /// Other | ^^^^^^^^^ doc comments are not allowed here -error[E0658]: attributes on function parameters are unstable - --> $DIR/fn-arg-doc-comment.rs:2:5 - | -LL | /// Comment - | ^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/60406 - = help: add `#![feature(param_attrs)]` to the crate attributes to enable - -error[E0658]: attributes on function parameters are unstable - --> $DIR/fn-arg-doc-comment.rs:8:5 - | -LL | /// Other - | ^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/60406 - = help: add `#![feature(param_attrs)]` to the crate attributes to enable - error[E0308]: mismatched types - --> $DIR/fn-arg-doc-comment.rs:22:7 + --> $DIR/fn-arg-doc-comment.rs:18:7 | LL | f("", ""); | ^^ expected u8, found reference @@ -44,7 +26,7 @@ LL | f("", ""); found type `&'static str` error[E0308]: mismatched types - --> $DIR/fn-arg-doc-comment.rs:22:11 + --> $DIR/fn-arg-doc-comment.rs:18:11 | LL | f("", ""); | ^^ expected u8, found reference @@ -53,7 +35,7 @@ LL | f("", ""); found type `&'static str` error[E0308]: mismatched types - --> $DIR/fn-arg-doc-comment.rs:29:9 + --> $DIR/fn-arg-doc-comment.rs:25:9 | LL | bar(""); | ^^ expected i32, found reference @@ -61,7 +43,6 @@ LL | bar(""); = note: expected type `i32` found type `&'static str` -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index f06b951041..d6efc8be07 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -2,29 +2,29 @@ struct S; impl S { fn foo(&self, &str bar) {} - //~^ ERROR expected one of `:` or `@` + //~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : } fn baz(S quux, xyzzy: i32) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : fn one(i32 a b) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` fn pattern((i32, i32) (a, b)) {} -//~^ ERROR expected `:` +//~^ ERROR expected one of `:` fn fizz(i32) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP if this was a parameter name, give it a type //~| HELP if this is a type, explicitly ignore the parameter name fn missing_colon(quux S) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index fb48bd1fe9..2bda446003 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -1,38 +1,38 @@ -error: expected one of `:` or `@`, found `bar` +error: expected one of `:`, `@`, or `|`, found `bar` --> $DIR/inverted-parameters.rs:4:24 | LL | fn foo(&self, &str bar) {} | -----^^^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` -error: expected one of `:` or `@`, found `quux` +error: expected one of `:`, `@`, or `|`, found `quux` --> $DIR/inverted-parameters.rs:10:10 | LL | fn baz(S quux, xyzzy: i32) {} | --^^^^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` -error: expected one of `:` or `@`, found `a` +error: expected one of `:`, `@`, or `|`, found `a` --> $DIR/inverted-parameters.rs:15:12 | LL | fn one(i32 a b) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here -error: expected `:`, found `(` +error: expected one of `:` or `|`, found `(` --> $DIR/inverted-parameters.rs:18:23 | LL | fn pattern((i32, i32) (a, b)) {} - | ^ expected `:` + | ^ expected one of `:` or `|` here -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/inverted-parameters.rs:21:12 | LL | fn fizz(i32) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -44,13 +44,13 @@ help: if this is a type, explicitly ignore the parameter name LL | fn fizz(_: i32) {} | ^^^^^^ -error: expected one of `:` or `@`, found `S` +error: expected one of `:`, `@`, or `|`, found `S` --> $DIR/inverted-parameters.rs:26:23 | LL | fn missing_colon(quux S) {} | -----^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` error: aborting due to 6 previous errors diff --git a/src/test/ui/parser/issue-22647.rs b/src/test/ui/parser/issue-22647.rs index 25cd7ffce5..a686141068 100644 --- a/src/test/ui/parser/issue-22647.rs +++ b/src/test/ui/parser/issue-22647.rs @@ -1,5 +1,5 @@ fn main() { - let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<` + let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` where F: Fn() -> i32 { let x = f(); diff --git a/src/test/ui/parser/issue-22647.stderr b/src/test/ui/parser/issue-22647.stderr index 2dc56a5eca..4b1ef4f3df 100644 --- a/src/test/ui/parser/issue-22647.stderr +++ b/src/test/ui/parser/issue-22647.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `<` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` --> $DIR/issue-22647.rs:2:15 | LL | let caller = |f: F| - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-22712.rs b/src/test/ui/parser/issue-22712.rs index b03d578e3d..774de9c7e6 100644 --- a/src/test/ui/parser/issue-22712.rs +++ b/src/test/ui/parser/issue-22712.rs @@ -3,7 +3,7 @@ struct Foo { } fn bar() { - let Foo> //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<` + let Foo> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` } fn main() {} diff --git a/src/test/ui/parser/issue-22712.stderr b/src/test/ui/parser/issue-22712.stderr index 167eaf962e..d9e83144b3 100644 --- a/src/test/ui/parser/issue-22712.stderr +++ b/src/test/ui/parser/issue-22712.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `<` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` --> $DIR/issue-22712.rs:6:12 | LL | let Foo> - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issue-2354.rs index 565f84822f..a14eb6e32f 100644 --- a/src/test/ui/parser/issue-2354.rs +++ b/src/test/ui/parser/issue-2354.rs @@ -1,4 +1,7 @@ fn foo() { //~ NOTE un-closed delimiter +//~^ ERROR `main` function not found +//~^^ NOTE main function must be defined +//~^^^ NOTE you have one or more functions match Some(10) { //~^ NOTE this delimiter might not be properly closed... Some(y) => { panic!(); } @@ -11,5 +14,5 @@ fn bar() { while (i < 1000) {} } -fn main() {} //~ NOTE here is a function named 'main' +fn main() {} //~ NOTE here is a function named `main` //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issue-2354.stderr index 7098da738b..038e3dcfa4 100644 --- a/src/test/ui/parser/issue-2354.stderr +++ b/src/test/ui/parser/issue-2354.stderr @@ -1,8 +1,9 @@ error: this file contains an un-closed delimiter - --> $DIR/issue-2354.rs:15:66 + --> $DIR/issue-2354.rs:18:66 | LL | fn foo() { | - un-closed delimiter +... LL | match Some(10) { | - this delimiter might not be properly closed... ... @@ -13,13 +14,24 @@ LL | | ^ error[E0601]: `main` function not found in crate `issue_2354` + --> $DIR/issue-2354.rs:1:1 + | +LL | / fn foo() { +LL | | +LL | | +LL | | +... | +LL | | fn main() {} +LL | | + | |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`) | - = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. -note: here is a function named 'main' - --> $DIR/issue-2354.rs:14:1 +note: here is a function named `main` + --> $DIR/issue-2354.rs:17:1 | LL | fn main() {} | ^^^^^^^^^^^^ + = note: you have one or more functions named `main` not defined at the crate level + = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-24197.rs b/src/test/ui/parser/issue-24197.rs index 005ff9fa2e..aaf5137461 100644 --- a/src/test/ui/parser/issue-24197.rs +++ b/src/test/ui/parser/issue-24197.rs @@ -1,3 +1,3 @@ fn main() { - let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[` + let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` } diff --git a/src/test/ui/parser/issue-24197.stderr b/src/test/ui/parser/issue-24197.stderr index 2dfb31432b..24818db622 100644 --- a/src/test/ui/parser/issue-24197.stderr +++ b/src/test/ui/parser/issue-24197.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `[` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/issue-24197.rs:2:12 | LL | let buf[0] = 0; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs index 9c01a5c6d2..500242030c 100644 --- a/src/test/ui/parser/issue-32501.rs +++ b/src/test/ui/parser/issue-32501.rs @@ -4,5 +4,6 @@ fn main() { let _ = 0; let mut b = 0; let mut _b = 0; - let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_` + let mut _ = 0; + //~^ ERROR `mut` must be followed by a named binding } diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr index 97efb89593..d53302449a 100644 --- a/src/test/ui/parser/issue-32501.stderr +++ b/src/test/ui/parser/issue-32501.stderr @@ -1,8 +1,10 @@ -error: expected identifier, found reserved identifier `_` - --> $DIR/issue-32501.rs:7:13 +error: `mut` must be followed by a named binding + --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^ expected identifier, found reserved identifier + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs index 2ec8695817..22f80a8aae 100644 --- a/src/test/ui/parser/issue-33413.rs +++ b/src/test/ui/parser/issue-33413.rs @@ -2,7 +2,7 @@ struct S; impl S { fn f(*, a: u8) -> u8 {} - //~^ ERROR expected argument name, found `*` + //~^ ERROR expected parameter name, found `*` } fn main() {} diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr index f6f096b1b9..9e1178e8ac 100644 --- a/src/test/ui/parser/issue-33413.stderr +++ b/src/test/ui/parser/issue-33413.stderr @@ -1,8 +1,8 @@ -error: expected argument name, found `*` +error: expected parameter name, found `*` --> $DIR/issue-33413.rs:4:10 | LL | fn f(*, a: u8) -> u8 {} - | ^ expected argument name + | ^ expected parameter name error: aborting due to previous error diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs index d5f5f1469f..a5a8de8546 100644 --- a/src/test/ui/parser/issue-63135.rs +++ b/src/test/ui/parser/issue-63135.rs @@ -1,3 +1,3 @@ -// error-pattern: aborting due to 6 previous errors +// error-pattern: aborting due to 5 previous errors fn i(n{...,f # diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr index c0286d90af..a077ad454a 100644 --- a/src/test/ui/parser/issue-63135.stderr +++ b/src/test/ui/parser/issue-63135.stderr @@ -28,17 +28,11 @@ error: expected `[`, found `}` LL | fn i(n{...,f # | ^ expected `[` -error: expected `:`, found `)` +error: expected one of `:` or `|`, found `)` --> $DIR/issue-63135.rs:3:15 | LL | fn i(n{...,f # - | ^ expected `:` + | ^ expected one of `:` or `|` here -error: expected one of `->`, `where`, or `{`, found `` - --> $DIR/issue-63135.rs:3:15 - | -LL | fn i(n{...,f # - | ^ expected one of `->`, `where`, or `{` here - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs new file mode 100644 index 0000000000..97a405b699 --- /dev/null +++ b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs @@ -0,0 +1,26 @@ +// Regression test; used to ICE with 'visit_mac disabled by default' due to a +// `MutVisitor` in `fn make_all_value_bindings_mutable` (`parse/parser/pat.rs`). + +macro_rules! mac1 { + ($eval:expr) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + }; +} + +macro_rules! mac2 { + ($eval:pat) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR expected identifier, found `does_not_exist!()` + }; +} + +fn foo() { + mac1! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope + mac2! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope +} + +fn main() {} diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr new file mode 100644 index 0000000000..dd193d6a86 --- /dev/null +++ b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -0,0 +1,45 @@ +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13 + | +LL | let mut $eval = (); + | ^^^^^^^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac1! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found `does_not_exist!()` + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:17 + | +LL | let mut $eval = (); + | ^^^^^ expected identifier +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 + | +LL | let mut $eval = (); + | ^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13 + | +LL | mac1! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13 + | +LL | mac2! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/parser/keyword-abstract.rs b/src/test/ui/parser/keyword-abstract.rs index 890802ac13..570206575a 100644 --- a/src/test/ui/parser/keyword-abstract.rs +++ b/src/test/ui/parser/keyword-abstract.rs @@ -1,3 +1,3 @@ fn main() { - let abstract = (); //~ ERROR expected pattern, found reserved keyword `abstract` + let abstract = (); //~ ERROR expected identifier, found reserved keyword `abstract` } diff --git a/src/test/ui/parser/keyword-abstract.stderr b/src/test/ui/parser/keyword-abstract.stderr index 2c79598a81..eb2c810099 100644 --- a/src/test/ui/parser/keyword-abstract.stderr +++ b/src/test/ui/parser/keyword-abstract.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `abstract` +error: expected identifier, found reserved keyword `abstract` --> $DIR/keyword-abstract.rs:2:9 | LL | let abstract = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#abstract = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-as-as-identifier.rs b/src/test/ui/parser/keyword-as-as-identifier.rs index 23ff259db3..cd47c8a390 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.rs +++ b/src/test/ui/parser/keyword-as-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py as' fn main() { - let as = "foo"; //~ error: expected pattern, found keyword `as` + let as = "foo"; //~ error: expected identifier, found keyword `as` } diff --git a/src/test/ui/parser/keyword-as-as-identifier.stderr b/src/test/ui/parser/keyword-as-as-identifier.stderr index ef466488ad..5648652be9 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.stderr +++ b/src/test/ui/parser/keyword-as-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `as` +error: expected identifier, found keyword `as` --> $DIR/keyword-as-as-identifier.rs:4:9 | LL | let as = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#as = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-break-as-identifier.rs b/src/test/ui/parser/keyword-break-as-identifier.rs index 5ee111d38c..04b25a7aaf 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.rs +++ b/src/test/ui/parser/keyword-break-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py break' fn main() { - let break = "foo"; //~ error: expected pattern, found keyword `break` + let break = "foo"; //~ error: expected identifier, found keyword `break` } diff --git a/src/test/ui/parser/keyword-break-as-identifier.stderr b/src/test/ui/parser/keyword-break-as-identifier.stderr index 690bd84221..820193db70 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.stderr +++ b/src/test/ui/parser/keyword-break-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `break` +error: expected identifier, found keyword `break` --> $DIR/keyword-break-as-identifier.rs:4:9 | LL | let break = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#break = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-const-as-identifier.rs b/src/test/ui/parser/keyword-const-as-identifier.rs index 48fc142cf6..6a2d926bf5 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.rs +++ b/src/test/ui/parser/keyword-const-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py const' fn main() { - let const = "foo"; //~ error: expected pattern, found keyword `const` + let const = "foo"; //~ error: expected identifier, found keyword `const` } diff --git a/src/test/ui/parser/keyword-const-as-identifier.stderr b/src/test/ui/parser/keyword-const-as-identifier.stderr index 6da47f88d0..95b536c99c 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.stderr +++ b/src/test/ui/parser/keyword-const-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `const` +error: expected identifier, found keyword `const` --> $DIR/keyword-const-as-identifier.rs:4:9 | LL | let const = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#const = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-continue-as-identifier.rs b/src/test/ui/parser/keyword-continue-as-identifier.rs index 06315a4834..cfdd62a2d1 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.rs +++ b/src/test/ui/parser/keyword-continue-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py continue' fn main() { - let continue = "foo"; //~ error: expected pattern, found keyword `continue` + let continue = "foo"; //~ error: expected identifier, found keyword `continue` } diff --git a/src/test/ui/parser/keyword-continue-as-identifier.stderr b/src/test/ui/parser/keyword-continue-as-identifier.stderr index 4b0a659f9a..6b24422a55 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.stderr +++ b/src/test/ui/parser/keyword-continue-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `continue` +error: expected identifier, found keyword `continue` --> $DIR/keyword-continue-as-identifier.rs:4:9 | LL | let continue = "foo"; - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#continue = "foo"; + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-else-as-identifier.rs b/src/test/ui/parser/keyword-else-as-identifier.rs index 0c69105cf9..f12dac3ff7 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.rs +++ b/src/test/ui/parser/keyword-else-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py else' fn main() { - let else = "foo"; //~ error: expected pattern, found keyword `else` + let else = "foo"; //~ error: expected identifier, found keyword `else` } diff --git a/src/test/ui/parser/keyword-else-as-identifier.stderr b/src/test/ui/parser/keyword-else-as-identifier.stderr index bec7b7ba01..f28635cd08 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.stderr +++ b/src/test/ui/parser/keyword-else-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `else` +error: expected identifier, found keyword `else` --> $DIR/keyword-else-as-identifier.rs:4:9 | LL | let else = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#else = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-enum-as-identifier.rs b/src/test/ui/parser/keyword-enum-as-identifier.rs index d1675800a2..fe66230d02 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.rs +++ b/src/test/ui/parser/keyword-enum-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py enum' fn main() { - let enum = "foo"; //~ error: expected pattern, found keyword `enum` + let enum = "foo"; //~ error: expected identifier, found keyword `enum` } diff --git a/src/test/ui/parser/keyword-enum-as-identifier.stderr b/src/test/ui/parser/keyword-enum-as-identifier.stderr index 51a834f797..fc54dce1b6 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.stderr +++ b/src/test/ui/parser/keyword-enum-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `enum` +error: expected identifier, found keyword `enum` --> $DIR/keyword-enum-as-identifier.rs:4:9 | LL | let enum = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#enum = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-final.rs b/src/test/ui/parser/keyword-final.rs index e1cecd0e8e..a79a11032a 100644 --- a/src/test/ui/parser/keyword-final.rs +++ b/src/test/ui/parser/keyword-final.rs @@ -1,3 +1,3 @@ fn main() { - let final = (); //~ ERROR expected pattern, found reserved keyword `final` + let final = (); //~ ERROR expected identifier, found reserved keyword `final` } diff --git a/src/test/ui/parser/keyword-final.stderr b/src/test/ui/parser/keyword-final.stderr index e8372643be..291710d05c 100644 --- a/src/test/ui/parser/keyword-final.stderr +++ b/src/test/ui/parser/keyword-final.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `final` +error: expected identifier, found reserved keyword `final` --> $DIR/keyword-final.rs:2:9 | LL | let final = (); - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#final = (); + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-fn-as-identifier.rs b/src/test/ui/parser/keyword-fn-as-identifier.rs index bca2d5996a..f30e115f79 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.rs +++ b/src/test/ui/parser/keyword-fn-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py fn' fn main() { - let fn = "foo"; //~ error: expected pattern, found keyword `fn` + let fn = "foo"; //~ error: expected identifier, found keyword `fn` } diff --git a/src/test/ui/parser/keyword-fn-as-identifier.stderr b/src/test/ui/parser/keyword-fn-as-identifier.stderr index a071a40a70..692f195b28 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.stderr +++ b/src/test/ui/parser/keyword-fn-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `fn` +error: expected identifier, found keyword `fn` --> $DIR/keyword-fn-as-identifier.rs:4:9 | LL | let fn = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#fn = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-for-as-identifier.rs b/src/test/ui/parser/keyword-for-as-identifier.rs index ce49fd90d9..9e8a2ad534 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.rs +++ b/src/test/ui/parser/keyword-for-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py for' fn main() { - let for = "foo"; //~ error: expected pattern, found keyword `for` + let for = "foo"; //~ error: expected identifier, found keyword `for` } diff --git a/src/test/ui/parser/keyword-for-as-identifier.stderr b/src/test/ui/parser/keyword-for-as-identifier.stderr index 090046cebd..bcaf421286 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.stderr +++ b/src/test/ui/parser/keyword-for-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `for` +error: expected identifier, found keyword `for` --> $DIR/keyword-for-as-identifier.rs:4:9 | LL | let for = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#for = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-if-as-identifier.rs b/src/test/ui/parser/keyword-if-as-identifier.rs index a130297068..0bd5756afc 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.rs +++ b/src/test/ui/parser/keyword-if-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py if' fn main() { - let if = "foo"; //~ error: expected pattern, found keyword `if` + let if = "foo"; //~ error: expected identifier, found keyword `if` } diff --git a/src/test/ui/parser/keyword-if-as-identifier.stderr b/src/test/ui/parser/keyword-if-as-identifier.stderr index 98bfdb46e9..43fbcd7148 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.stderr +++ b/src/test/ui/parser/keyword-if-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `if` +error: expected identifier, found keyword `if` --> $DIR/keyword-if-as-identifier.rs:4:9 | LL | let if = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#if = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-impl-as-identifier.rs b/src/test/ui/parser/keyword-impl-as-identifier.rs index 95a34483ad..df529bae07 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.rs +++ b/src/test/ui/parser/keyword-impl-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py impl' fn main() { - let impl = "foo"; //~ error: expected pattern, found keyword `impl` + let impl = "foo"; //~ error: expected identifier, found keyword `impl` } diff --git a/src/test/ui/parser/keyword-impl-as-identifier.stderr b/src/test/ui/parser/keyword-impl-as-identifier.stderr index 2672959b7c..01886eb45c 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.stderr +++ b/src/test/ui/parser/keyword-impl-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `impl` +error: expected identifier, found keyword `impl` --> $DIR/keyword-impl-as-identifier.rs:4:9 | LL | let impl = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#impl = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-let-as-identifier.rs b/src/test/ui/parser/keyword-let-as-identifier.rs index 07c0ddf8ce..9b1183501b 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.rs +++ b/src/test/ui/parser/keyword-let-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py let' fn main() { - let let = "foo"; //~ error: expected pattern, found keyword `let` + let let = "foo"; //~ error: expected identifier, found keyword `let` } diff --git a/src/test/ui/parser/keyword-let-as-identifier.stderr b/src/test/ui/parser/keyword-let-as-identifier.stderr index 99dbc0530f..f6c39077be 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.stderr +++ b/src/test/ui/parser/keyword-let-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `let` +error: expected identifier, found keyword `let` --> $DIR/keyword-let-as-identifier.rs:4:9 | LL | let let = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#let = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-loop-as-identifier.rs b/src/test/ui/parser/keyword-loop-as-identifier.rs index 8643ffe434..46914a19be 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.rs +++ b/src/test/ui/parser/keyword-loop-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py loop' fn main() { - let loop = "foo"; //~ error: expected pattern, found keyword `loop` + let loop = "foo"; //~ error: expected identifier, found keyword `loop` } diff --git a/src/test/ui/parser/keyword-loop-as-identifier.stderr b/src/test/ui/parser/keyword-loop-as-identifier.stderr index 783507eb35..f0c282faa2 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.stderr +++ b/src/test/ui/parser/keyword-loop-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `loop` +error: expected identifier, found keyword `loop` --> $DIR/keyword-loop-as-identifier.rs:4:9 | LL | let loop = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#loop = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-match-as-identifier.rs b/src/test/ui/parser/keyword-match-as-identifier.rs index 8ef6b6810a..d3cecb991b 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.rs +++ b/src/test/ui/parser/keyword-match-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py match' fn main() { - let match = "foo"; //~ error: expected pattern, found keyword `match` + let match = "foo"; //~ error: expected identifier, found keyword `match` } diff --git a/src/test/ui/parser/keyword-match-as-identifier.stderr b/src/test/ui/parser/keyword-match-as-identifier.stderr index e56a115c91..f1f4397d19 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.stderr +++ b/src/test/ui/parser/keyword-match-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `match` +error: expected identifier, found keyword `match` --> $DIR/keyword-match-as-identifier.rs:4:9 | LL | let match = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#match = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-mod-as-identifier.rs b/src/test/ui/parser/keyword-mod-as-identifier.rs index 96bcdccf0a..b9c7b6c78e 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.rs +++ b/src/test/ui/parser/keyword-mod-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py mod' fn main() { - let mod = "foo"; //~ error: expected pattern, found keyword `mod` + let mod = "foo"; //~ error: expected identifier, found keyword `mod` } diff --git a/src/test/ui/parser/keyword-mod-as-identifier.stderr b/src/test/ui/parser/keyword-mod-as-identifier.stderr index a8be2ceb03..65ae3baa8c 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.stderr +++ b/src/test/ui/parser/keyword-mod-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `mod` +error: expected identifier, found keyword `mod` --> $DIR/keyword-mod-as-identifier.rs:4:9 | LL | let mod = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#mod = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-move-as-identifier.rs b/src/test/ui/parser/keyword-move-as-identifier.rs index 2193af530b..65be02e3c7 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.rs +++ b/src/test/ui/parser/keyword-move-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py move' fn main() { - let move = "foo"; //~ error: expected pattern, found keyword `move` + let move = "foo"; //~ error: expected identifier, found keyword `move` } diff --git a/src/test/ui/parser/keyword-move-as-identifier.stderr b/src/test/ui/parser/keyword-move-as-identifier.stderr index e0687e27eb..216f7c931e 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.stderr +++ b/src/test/ui/parser/keyword-move-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `move` +error: expected identifier, found keyword `move` --> $DIR/keyword-move-as-identifier.rs:4:9 | LL | let move = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#move = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-override.rs b/src/test/ui/parser/keyword-override.rs index 948a20095f..009bebd7dd 100644 --- a/src/test/ui/parser/keyword-override.rs +++ b/src/test/ui/parser/keyword-override.rs @@ -1,3 +1,3 @@ fn main() { - let override = (); //~ ERROR expected pattern, found reserved keyword `override` + let override = (); //~ ERROR expected identifier, found reserved keyword `override` } diff --git a/src/test/ui/parser/keyword-override.stderr b/src/test/ui/parser/keyword-override.stderr index 1bfc6c9b38..3183fa510c 100644 --- a/src/test/ui/parser/keyword-override.stderr +++ b/src/test/ui/parser/keyword-override.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `override` +error: expected identifier, found reserved keyword `override` --> $DIR/keyword-override.rs:2:9 | LL | let override = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#override = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-pub-as-identifier.rs b/src/test/ui/parser/keyword-pub-as-identifier.rs index 2ed8cc6b26..2b2bb14118 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.rs +++ b/src/test/ui/parser/keyword-pub-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py pub' fn main() { - let pub = "foo"; //~ error: expected pattern, found keyword `pub` + let pub = "foo"; //~ error: expected identifier, found keyword `pub` } diff --git a/src/test/ui/parser/keyword-pub-as-identifier.stderr b/src/test/ui/parser/keyword-pub-as-identifier.stderr index 526ddcd6ee..f81078b12b 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.stderr +++ b/src/test/ui/parser/keyword-pub-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `pub` +error: expected identifier, found keyword `pub` --> $DIR/keyword-pub-as-identifier.rs:4:9 | LL | let pub = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#pub = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-return-as-identifier.rs b/src/test/ui/parser/keyword-return-as-identifier.rs index 920931b00f..e1a2db5e4d 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.rs +++ b/src/test/ui/parser/keyword-return-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py return' fn main() { - let return = "foo"; //~ error: expected pattern, found keyword `return` + let return = "foo"; //~ error: expected identifier, found keyword `return` } diff --git a/src/test/ui/parser/keyword-return-as-identifier.stderr b/src/test/ui/parser/keyword-return-as-identifier.stderr index c0156a63fa..8cc4d12fbb 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.stderr +++ b/src/test/ui/parser/keyword-return-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `return` +error: expected identifier, found keyword `return` --> $DIR/keyword-return-as-identifier.rs:4:9 | LL | let return = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#return = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-static-as-identifier.rs b/src/test/ui/parser/keyword-static-as-identifier.rs index 3ccbfccfc9..423b9854b8 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.rs +++ b/src/test/ui/parser/keyword-static-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py static' fn main() { - let static = "foo"; //~ error: expected pattern, found keyword `static` + let static = "foo"; //~ error: expected identifier, found keyword `static` } diff --git a/src/test/ui/parser/keyword-static-as-identifier.stderr b/src/test/ui/parser/keyword-static-as-identifier.stderr index 00a6597773..7d22bc97d6 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.stderr +++ b/src/test/ui/parser/keyword-static-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `static` +error: expected identifier, found keyword `static` --> $DIR/keyword-static-as-identifier.rs:4:9 | LL | let static = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#static = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-struct-as-identifier.rs b/src/test/ui/parser/keyword-struct-as-identifier.rs index 69d8f19065..18cfe11592 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.rs +++ b/src/test/ui/parser/keyword-struct-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py struct' fn main() { - let struct = "foo"; //~ error: expected pattern, found keyword `struct` + let struct = "foo"; //~ error: expected identifier, found keyword `struct` } diff --git a/src/test/ui/parser/keyword-struct-as-identifier.stderr b/src/test/ui/parser/keyword-struct-as-identifier.stderr index b2d6639e72..b109fa6247 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.stderr +++ b/src/test/ui/parser/keyword-struct-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `struct` +error: expected identifier, found keyword `struct` --> $DIR/keyword-struct-as-identifier.rs:4:9 | LL | let struct = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#struct = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-trait-as-identifier.rs b/src/test/ui/parser/keyword-trait-as-identifier.rs index f62858442d..67f81167db 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.rs +++ b/src/test/ui/parser/keyword-trait-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py trait' fn main() { - let trait = "foo"; //~ error: expected pattern, found keyword `trait` + let trait = "foo"; //~ error: expected identifier, found keyword `trait` } diff --git a/src/test/ui/parser/keyword-trait-as-identifier.stderr b/src/test/ui/parser/keyword-trait-as-identifier.stderr index b31c0df28c..ccc675cdb3 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.stderr +++ b/src/test/ui/parser/keyword-trait-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `trait` +error: expected identifier, found keyword `trait` --> $DIR/keyword-trait-as-identifier.rs:4:9 | LL | let trait = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#trait = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs index 13a938b2e0..4fa37bdb05 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 fn main() { - let try = "foo"; //~ error: expected pattern, found reserved keyword `try` + let try = "foo"; //~ error: expected identifier, found reserved keyword `try` } diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr index c342e3a76f..f71b889a30 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `try` +error: expected identifier, found reserved keyword `try` --> $DIR/keyword-try-as-identifier-edition2018.rs:4:9 | LL | let try = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#try = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-type-as-identifier.rs b/src/test/ui/parser/keyword-type-as-identifier.rs index 992547e6f5..04adddf72c 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.rs +++ b/src/test/ui/parser/keyword-type-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py type' fn main() { - let type = "foo"; //~ error: expected pattern, found keyword `type` + let type = "foo"; //~ error: expected identifier, found keyword `type` } diff --git a/src/test/ui/parser/keyword-type-as-identifier.stderr b/src/test/ui/parser/keyword-type-as-identifier.stderr index b749c708d4..88099d949a 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.stderr +++ b/src/test/ui/parser/keyword-type-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `type` +error: expected identifier, found keyword `type` --> $DIR/keyword-type-as-identifier.rs:4:9 | LL | let type = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#type = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-typeof.rs b/src/test/ui/parser/keyword-typeof.rs index 4ef102646e..29dc77d276 100644 --- a/src/test/ui/parser/keyword-typeof.rs +++ b/src/test/ui/parser/keyword-typeof.rs @@ -1,3 +1,3 @@ fn main() { - let typeof = (); //~ ERROR expected pattern, found reserved keyword `typeof` + let typeof = (); //~ ERROR expected identifier, found reserved keyword `typeof` } diff --git a/src/test/ui/parser/keyword-typeof.stderr b/src/test/ui/parser/keyword-typeof.stderr index e7b18023e6..4a1b63d5c9 100644 --- a/src/test/ui/parser/keyword-typeof.stderr +++ b/src/test/ui/parser/keyword-typeof.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `typeof` +error: expected identifier, found reserved keyword `typeof` --> $DIR/keyword-typeof.rs:2:9 | LL | let typeof = (); - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#typeof = (); + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.rs b/src/test/ui/parser/keyword-unsafe-as-identifier.rs index adb20ebe48..0ff6d188c6 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.rs +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe' fn main() { - let unsafe = "foo"; //~ error: expected pattern, found keyword `unsafe` + let unsafe = "foo"; //~ error: expected identifier, found keyword `unsafe` } diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr index 67935ce43b..205bb81df4 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `unsafe` +error: expected identifier, found keyword `unsafe` --> $DIR/keyword-unsafe-as-identifier.rs:4:9 | LL | let unsafe = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#unsafe = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-use-as-identifier.rs b/src/test/ui/parser/keyword-use-as-identifier.rs index 198444bafc..821bedee08 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.rs +++ b/src/test/ui/parser/keyword-use-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py use' fn main() { - let use = "foo"; //~ error: expected pattern, found keyword `use` + let use = "foo"; //~ error: expected identifier, found keyword `use` } diff --git a/src/test/ui/parser/keyword-use-as-identifier.stderr b/src/test/ui/parser/keyword-use-as-identifier.stderr index 2c69d0a874..85a0492f57 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.stderr +++ b/src/test/ui/parser/keyword-use-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `use` +error: expected identifier, found keyword `use` --> $DIR/keyword-use-as-identifier.rs:4:9 | LL | let use = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#use = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-where-as-identifier.rs b/src/test/ui/parser/keyword-where-as-identifier.rs index 5624a8fc46..56301bd20a 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.rs +++ b/src/test/ui/parser/keyword-where-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py where' fn main() { - let where = "foo"; //~ error: expected pattern, found keyword `where` + let where = "foo"; //~ error: expected identifier, found keyword `where` } diff --git a/src/test/ui/parser/keyword-where-as-identifier.stderr b/src/test/ui/parser/keyword-where-as-identifier.stderr index fc01183ca0..b8b8506907 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.stderr +++ b/src/test/ui/parser/keyword-where-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `where` +error: expected identifier, found keyword `where` --> $DIR/keyword-where-as-identifier.rs:4:9 | LL | let where = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#where = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-while-as-identifier.rs b/src/test/ui/parser/keyword-while-as-identifier.rs index c0a539d350..22026d15dc 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.rs +++ b/src/test/ui/parser/keyword-while-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py while' fn main() { - let while = "foo"; //~ error: expected pattern, found keyword `while` + let while = "foo"; //~ error: expected identifier, found keyword `while` } diff --git a/src/test/ui/parser/keyword-while-as-identifier.stderr b/src/test/ui/parser/keyword-while-as-identifier.stderr index f72ac87742..bb0c0ac668 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.stderr +++ b/src/test/ui/parser/keyword-while-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `while` +error: expected identifier, found keyword `while` --> $DIR/keyword-while-as-identifier.rs:4:9 | LL | let while = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#while = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs index 1e180f87fc..d35dafd9a3 100644 --- a/src/test/ui/parser/lex-bad-char-literals-2.rs +++ b/src/test/ui/parser/lex-bad-char-literals-2.rs @@ -2,3 +2,5 @@ static c: char = 'nope' //~ ERROR: character literal may only contain one codepoint ; + +fn main() {} diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr index b0a4ed0243..5653d4ea67 100644 --- a/src/test/ui/parser/lex-bad-char-literals-2.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr @@ -8,10 +8,5 @@ help: if you meant to write a `str` literal, use double quotes LL | "nope" | ^^^^^^ -error[E0601]: `main` function not found in crate `lex_bad_char_literals_2` - | - = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index a5eb482523..66fd5893af 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -1,6 +1,46 @@ // Can't put mut in non-ident pattern +// edition:2018 + +#![feature(box_patterns)] +#![allow(warnings)] + pub fn main() { + let mut _ = 0; //~ ERROR `mut` must be followed by a named binding + let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding + + let mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + struct Foo { x: isize } - let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{` + let mut Foo { x: x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + let mut Foo { x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + struct r#yield(u8, u8); + let mut mut yield(become, await) = r#yield(0, 0); + //~^ ERROR `mut` on a binding may not be repeated + //~| ERROR `mut` must be attached to each individual binding + //~| ERROR expected identifier, found reserved keyword `yield` + //~| ERROR expected identifier, found reserved keyword `become` + //~| ERROR expected identifier, found keyword `await` + + struct W(T, U); + struct B { f: Box } + let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + //~^ ERROR `mut` must be attached to each individual binding + = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); + + // Make sure we don't accidentally allow `mut $p` where `$p:pat`. + macro_rules! foo { + ($p:pat) => { + let mut $p = 0; //~ ERROR expected identifier, found `x` + } + } + foo!(x); } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index 286956440e..b1cf99189f 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,8 +1,101 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `{` - --> $DIR/mut-patterns.rs:5:17 +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:9:9 + | +LL | let mut _ = 0; + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:10:9 + | +LL | let mut (_, _) = (0, 0); + | ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:12:13 + | +LL | let mut mut x = 0; + | ^^^ help: remove the additional `mut`s + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:17:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:21:9 + | +LL | let mut Foo { x } = Foo { x: 3 }; + | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:26:13 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^ help: remove the additional `mut`s + +error: expected identifier, found reserved keyword `yield` + --> $DIR/mut-patterns.rs:26:17 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut r#yield(become, await) = r#yield(0, 0); + | ^^^^^^^ + +error: expected identifier, found reserved keyword `become` + --> $DIR/mut-patterns.rs:26:23 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(r#become, await) = r#yield(0, 0); + | ^^^^^^^^ + +error: expected identifier, found keyword `await` + --> $DIR/mut-patterns.rs:26:31 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(become, r#await) = r#yield(0, 0); + | ^^^^^^^ + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:26:9 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:35:9 + | +LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found `x` + --> $DIR/mut-patterns.rs:42:21 + | +LL | let mut $p = 0; + | ^^ expected identifier +... +LL | foo!(x); + | -------- in this macro invocation -error: aborting due to previous error +error: aborting due to 12 previous errors diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.rs b/src/test/ui/parser/omitted-arg-in-item-fn.rs index 5ee9daf464..49cbc4d6bf 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.rs +++ b/src/test/ui/parser/omitted-arg-in-item-fn.rs @@ -1,4 +1,4 @@ -fn foo(x) { //~ ERROR expected one of `:` or `@`, found `)` +fn foo(x) { //~ ERROR expected one of `:`, `@`, or `|`, found `)` } fn main() {} diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index e501f235d6..7feb15592c 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/omitted-arg-in-item-fn.rs:1:9 | LL | fn foo(x) { - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/parser/pat-lt-bracket-2.rs b/src/test/ui/parser/pat-lt-bracket-2.rs index 6eb01c1c93..3a778ed14f 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.rs +++ b/src/test/ui/parser/pat-lt-bracket-2.rs @@ -1,4 +1,4 @@ fn a(B<) {} - //~^ error: expected one of `:` or `@`, found `<` + //~^ error: expected one of `:`, `@`, or `|`, found `<` fn main() {} diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr index cce1a17e9e..dbc8d0f586 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.stderr +++ b/src/test/ui/parser/pat-lt-bracket-2.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/pat-lt-bracket-2.rs:1:7 | LL | fn a(B<) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-lt-bracket-5.rs b/src/test/ui/parser/pat-lt-bracket-5.rs index c4b9dd469f..aaece1f6bd 100644 --- a/src/test/ui/parser/pat-lt-bracket-5.rs +++ b/src/test/ui/parser/pat-lt-bracket-5.rs @@ -1,3 +1,3 @@ fn main() { - let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[` + let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` } diff --git a/src/test/ui/parser/pat-lt-bracket-5.stderr b/src/test/ui/parser/pat-lt-bracket-5.stderr index ce4cc05db1..167314dde0 100644 --- a/src/test/ui/parser/pat-lt-bracket-5.stderr +++ b/src/test/ui/parser/pat-lt-bracket-5.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `[` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-5.rs:2:10 | LL | let v[0] = v[1]; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs index 7b97218309..f27caa5d78 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.rs +++ b/src/test/ui/parser/pat-lt-bracket-6.rs @@ -2,8 +2,9 @@ fn main() { struct Test(&'static u8, [u8; 0]); let x = Test(&0, []); - let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[` - //~^ ERROR subslice patterns are unstable + let Test(&desc[..]) = x; + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` + //~^^ ERROR subslice patterns are unstable } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr index 201465b2c8..6f08f0a9d9 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.stderr +++ b/src/test/ui/parser/pat-lt-bracket-6.stderr @@ -1,8 +1,8 @@ -error: expected one of `)`, `,`, or `@`, found `[` +error: expected one of `)`, `,`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-6.rs:5:19 | LL | let Test(&desc[..]) = x; - | ^ expected one of `)`, `,`, or `@` here + | ^ expected one of `)`, `,`, `@`, or `|` here error[E0658]: subslice patterns are unstable --> $DIR/pat-lt-bracket-6.rs:5:20 @@ -14,7 +14,7 @@ LL | let Test(&desc[..]) = x; = help: add `#![feature(slice_patterns)]` to the crate attributes to enable error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-6.rs:9:30 + --> $DIR/pat-lt-bracket-6.rs:10:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected (), found integer diff --git a/src/test/ui/parser/pat-lt-bracket-7.rs b/src/test/ui/parser/pat-lt-bracket-7.rs index 020fdb845e..327aef5ad1 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.rs +++ b/src/test/ui/parser/pat-lt-bracket-7.rs @@ -2,7 +2,8 @@ fn main() { struct Thing(u8, [u8; 0]); let foo = core::iter::empty(); - for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[` + for Thing(x[]) in foo {} + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr index 17557efa49..196f1c0ae9 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.stderr +++ b/src/test/ui/parser/pat-lt-bracket-7.stderr @@ -1,11 +1,11 @@ -error: expected one of `)`, `,`, or `@`, found `[` +error: expected one of `)`, `,`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-7.rs:5:16 | LL | for Thing(x[]) in foo {} - | ^ expected one of `)`, `,`, or `@` here + | ^ expected one of `)`, `,`, `@`, or `|` here error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-7.rs:8:30 + --> $DIR/pat-lt-bracket-7.rs:9:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected (), found integer diff --git a/src/test/ui/parser/pat-ranges-1.rs b/src/test/ui/parser/pat-ranges-1.rs index ce953b2eb2..1dafb5a07b 100644 --- a/src/test/ui/parser/pat-ranges-1.rs +++ b/src/test/ui/parser/pat-ranges-1.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=` + let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, `=`, or `|`, found `..=` } diff --git a/src/test/ui/parser/pat-ranges-1.stderr b/src/test/ui/parser/pat-ranges-1.stderr index 6e0deccab8..4e2c5d2838 100644 --- a/src/test/ui/parser/pat-ranges-1.stderr +++ b/src/test/ui/parser/pat-ranges-1.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, or `=`, found `..=` +error: expected one of `:`, `;`, `=`, or `|`, found `..=` --> $DIR/pat-ranges-1.rs:4:21 | LL | let macropus!() ..= 11 = 12; - | ^^^ expected one of `:`, `;`, or `=` here + | ^^^ expected one of `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-2.rs b/src/test/ui/parser/pat-ranges-2.rs index 9f736ed328..1593222acc 100644 --- a/src/test/ui/parser/pat-ranges-2.rs +++ b/src/test/ui/parser/pat-ranges-2.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!` + let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` } diff --git a/src/test/ui/parser/pat-ranges-2.stderr b/src/test/ui/parser/pat-ranges-2.stderr index d180bb4291..64df56f5a6 100644 --- a/src/test/ui/parser/pat-ranges-2.stderr +++ b/src/test/ui/parser/pat-ranges-2.stderr @@ -1,8 +1,8 @@ -error: expected one of `::`, `:`, `;`, or `=`, found `!` +error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` --> $DIR/pat-ranges-2.rs:4:26 | LL | let 10 ..= makropulos!() = 12; - | ^ expected one of `::`, `:`, `;`, or `=` here + | ^ expected one of `::`, `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-3.rs b/src/test/ui/parser/pat-ranges-3.rs index 65da55e3bd..8976dcf0d9 100644 --- a/src/test/ui/parser/pat-ranges-3.rs +++ b/src/test/ui/parser/pat-ranges-3.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+` + let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, `=`, or `|`, found `+` } diff --git a/src/test/ui/parser/pat-ranges-3.stderr b/src/test/ui/parser/pat-ranges-3.stderr index aaa85e3c2d..c32c18d98d 100644 --- a/src/test/ui/parser/pat-ranges-3.stderr +++ b/src/test/ui/parser/pat-ranges-3.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, or `=`, found `+` +error: expected one of `:`, `;`, `=`, or `|`, found `+` --> $DIR/pat-ranges-3.rs:4:19 | LL | let 10 ..= 10 + 3 = 12; - | ^ expected one of `:`, `;`, or `=` here + | ^ expected one of `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-4.rs b/src/test/ui/parser/pat-ranges-4.rs index 7f4a5f3239..61188976b0 100644 --- a/src/test/ui/parser/pat-ranges-4.rs +++ b/src/test/ui/parser/pat-ranges-4.rs @@ -2,5 +2,5 @@ fn main() { let 10 - 3 ..= 10 = 8; - //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-` + //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` } diff --git a/src/test/ui/parser/pat-ranges-4.stderr b/src/test/ui/parser/pat-ranges-4.stderr index 0a1d7a1f6b..53e38bc670 100644 --- a/src/test/ui/parser/pat-ranges-4.stderr +++ b/src/test/ui/parser/pat-ranges-4.stderr @@ -1,8 +1,8 @@ -error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-` +error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` --> $DIR/pat-ranges-4.rs:4:12 | LL | let 10 - 3 ..= 10 = 8; - | ^ expected one of `...`, `..=`, `..`, `:`, `;`, or `=` here + | ^ expected one of 7 possible tokens here error: aborting due to previous error diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs index e6c59fcf22..c6be2c9066 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.rs +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs @@ -8,7 +8,7 @@ fn main() { let vec = vec![1, 2, 3]; for ( elem in vec ) { - //~^ ERROR expected one of `)`, `,`, or `@`, found `in` + //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found `in` //~| ERROR unexpected closing `)` const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr index c160e646c2..1b5b6cca09 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -1,8 +1,8 @@ -error: expected one of `)`, `,`, or `@`, found `in` +error: expected one of `)`, `,`, `@`, or `|`, found `in` --> $DIR/recover-for-loop-parens-around-head.rs:10:16 | LL | for ( elem in vec ) { - | ^^ expected one of `)`, `,`, or `@` here + | ^^ expected one of `)`, `,`, `@`, or `|` here error: unexpected closing `)` --> $DIR/recover-for-loop-parens-around-head.rs:10:23 diff --git a/src/test/ui/parser/removed-syntax-mode.rs b/src/test/ui/parser/removed-syntax-mode.rs index 23851b5f70..a438db3b0c 100644 --- a/src/test/ui/parser/removed-syntax-mode.rs +++ b/src/test/ui/parser/removed-syntax-mode.rs @@ -1,4 +1,4 @@ fn f(+x: isize) {} -//~^ ERROR expected argument name, found `+` +//~^ ERROR expected parameter name, found `+` fn main() {} diff --git a/src/test/ui/parser/removed-syntax-mode.stderr b/src/test/ui/parser/removed-syntax-mode.stderr index 5e7139d6bf..d0393b379f 100644 --- a/src/test/ui/parser/removed-syntax-mode.stderr +++ b/src/test/ui/parser/removed-syntax-mode.stderr @@ -1,8 +1,8 @@ -error: expected argument name, found `+` +error: expected parameter name, found `+` --> $DIR/removed-syntax-mode.rs:1:6 | LL | fn f(+x: isize) {} - | ^ expected argument name + | ^ expected parameter name error: aborting due to previous error diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 525be5d20e..3dcc0c8f3d 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -11,8 +11,7 @@ fn main() { //~| ERROR: mismatched types f(); - //~^ ERROR: chained comparison operators require parentheses - //~| ERROR: binary operation `<` cannot be applied to type `fn() {f::<_>}` + //~^ ERROR chained comparison operators require parentheses //~| HELP: use `::<...>` instead of `<...>` //~| HELP: or use `(...)` } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 76e548de04..e927f4c324 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -37,17 +37,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error[E0369]: binary operation `<` cannot be applied to type `fn() {f::<_>}` - --> $DIR/require-parens-for-chained-comparison.rs:13:6 - | -LL | f(); - | -^- X - | | - | fn() {f::<_>} - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0369. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs index 5bbda4296c..c8b0eb684f 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.rs +++ b/src/test/ui/parser/trait-object-lifetime-parens.rs @@ -9,7 +9,6 @@ fn check<'a>() { let _: Box<('a) + Trait>; //~^ ERROR expected type, found `'a` //~| ERROR expected `:`, found `)` - //~| ERROR chained comparison operators require parentheses } fn main() {} diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index 7ffc26e9ed..319a308c01 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -16,15 +16,6 @@ error: expected `:`, found `)` LL | let _: Box<('a) + Trait>; | ^ expected `:` -error: chained comparison operators require parentheses - --> $DIR/trait-object-lifetime-parens.rs:9:15 - | -LL | let _: Box<('a) + Trait>; - | ^^^^^^^^^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - error: expected type, found `'a` --> $DIR/trait-object-lifetime-parens.rs:9:17 | @@ -33,5 +24,5 @@ LL | let _: Box<('a) + Trait>; | | | while parsing the type for `_` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr index 2183c74da0..8f32fb0eca 100644 --- a/src/test/ui/parser/type-parameters-in-field-exprs.stderr +++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr @@ -11,10 +11,10 @@ LL | f.x::<>; | ^^ error: field expressions may not have generic arguments - --> $DIR/type-parameters-in-field-exprs.rs:17:10 + --> $DIR/type-parameters-in-field-exprs.rs:17:7 | LL | f.x::(); - | ^^ + | ^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr index 633c63bea9..818f61b4d2 100644 --- a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr +++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr @@ -1,5 +1,5 @@ error: incorrect close delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:5:1 + --> $DIR/unclosed_delim_mod.rs:7:1 | LL | pub fn new() -> Result { | - close delimiter possibly meant for this diff --git a/src/test/ui/parser/unclosed_delim_mod.rs b/src/test/ui/parser/unclosed_delim_mod.rs index b1664f49dc..486e233128 100644 --- a/src/test/ui/parser/unclosed_delim_mod.rs +++ b/src/test/ui/parser/unclosed_delim_mod.rs @@ -1,3 +1,5 @@ +fn main() {} + pub struct Value {} pub fn new() -> Result { Ok(Value { diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr index cc04eb531c..fe2d968af0 100644 --- a/src/test/ui/parser/unclosed_delim_mod.stderr +++ b/src/test/ui/parser/unclosed_delim_mod.stderr @@ -1,5 +1,5 @@ error: incorrect close delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:5:1 + --> $DIR/unclosed_delim_mod.rs:7:1 | LL | pub fn new() -> Result { | - close delimiter possibly meant for this @@ -9,10 +9,5 @@ LL | } LL | } | ^ incorrect close delimiter -error[E0601]: `main` function not found in crate `unclosed_delim_mod` - | - = note: consider adding a `main` function to `$DIR/unclosed_delim_mod.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 0430897510..e64b6efb08 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -19,12 +19,18 @@ LL | (1, 2, .., 3, 4) => {} error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields --> $DIR/pat-tuple-overfield.rs:10:9 | +LL | struct S(u8, u8, u8); + | --------------------- tuple struct defined here +... LL | S(1, 2, 3, 4) => {} | ^^^^^^^^^^^^^ expected 3 fields, found 4 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields --> $DIR/pat-tuple-overfield.rs:12:9 | +LL | struct S(u8, u8, u8); + | --------------------- tuple struct defined here +... LL | S(1, 2, .., 3, 4) => {} | ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4 diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index a581f07496..4fbc630644 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -15,6 +15,9 @@ LL | A::D(_) => (), error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/pattern-error-continue.rs:17:9 | +LL | B(isize, isize), + | --------------- tuple variant defined here +... LL | A::B(_, _, _) => (), | ^^^^^^^^^^^^^ expected 2 fields, found 3 diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr index ec8b3181bc..ac48ee0cb0 100644 --- a/src/test/ui/phantom-oibit.stderr +++ b/src/test/ui/phantom-oibit.stderr @@ -1,25 +1,26 @@ error[E0277]: `T` cannot be shared between threads safely - --> $DIR/phantom-oibit.rs:21:5 + --> $DIR/phantom-oibit.rs:21:12 | +LL | fn is_zen(_: T) {} + | ------ --- required by this bound in `is_zen` +... LL | is_zen(x) - | ^^^^^^ `T` cannot be shared between threads safely + | ^ `T` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `T` = help: consider adding a `where T: std::marker::Sync` bound = note: required because of the requirements on the impl of `Zen` for `&T` = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` -note: required by `is_zen` - --> $DIR/phantom-oibit.rs:18:1 - | -LL | fn is_zen(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be shared between threads safely - --> $DIR/phantom-oibit.rs:26:5 + --> $DIR/phantom-oibit.rs:26:12 | +LL | fn is_zen(_: T) {} + | ------ --- required by this bound in `is_zen` +... LL | is_zen(x) - | ^^^^^^ `T` cannot be shared between threads safely + | ^ `T` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `T` = help: consider adding a `where T: std::marker::Sync` bound @@ -27,11 +28,6 @@ LL | is_zen(x) = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` = note: required because it appears within the type `Nested>` -note: required by `is_zen` - --> $DIR/phantom-oibit.rs:18:1 - | -LL | fn is_zen(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/placement-syntax.rs b/src/test/ui/placement-syntax.rs index 2edd78ec8a..4df96dedbd 100644 --- a/src/test/ui/placement-syntax.rs +++ b/src/test/ui/placement-syntax.rs @@ -1,6 +1,6 @@ fn main() { let x = -5; - if x<-1 { //~ ERROR expected `{`, found `<-` + if x<-1 { //~ ERROR unexpected token: `<-` println!("ok"); } } diff --git a/src/test/ui/placement-syntax.stderr b/src/test/ui/placement-syntax.stderr index e90acce168..e26931e60d 100644 --- a/src/test/ui/placement-syntax.stderr +++ b/src/test/ui/placement-syntax.stderr @@ -1,10 +1,12 @@ -error: expected `{`, found `<-` +error: unexpected token: `<-` --> $DIR/placement-syntax.rs:3:9 | LL | if x<-1 { - | -- ^^ expected `{` - | | - | this `if` statement has a condition, but no block + | ^^ +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | if x< -1 { + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs index 95b4036814..58109be447 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs @@ -17,10 +17,10 @@ fn bar() -> impl std::fmt::Display { fn baz() -> impl std::fmt::Display { if false { - //~^ ERROR mismatched types return 0i32; } else { 1u32 + //~^ ERROR mismatched types } } @@ -33,4 +33,33 @@ fn qux() -> impl std::fmt::Display { } } +fn bat() -> impl std::fmt::Display { + match 13 { + 0 => return 0i32, + _ => 1u32, + //~^ ERROR mismatched types + } +} + +fn can() -> impl std::fmt::Display { + match 13 { + //~^ ERROR mismatched types + 0 => return 0i32, + 1 => 1u32, + _ => 2u32, + } +} + +fn cat() -> impl std::fmt::Display { + match 13 { + 0 => { + return 0i32; + } + _ => { + 1u32 + //~^ ERROR mismatched types + } + } +} + fn main() {} diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr index ee1e36081e..314ff84ae3 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr @@ -29,18 +29,16 @@ LL | return 1u32; found type `u32` error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9 | -LL | fn baz() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | / if false { -LL | | -LL | | return 0i32; - | | ---- ...is found to be `i32` here -LL | | } else { -LL | | 1u32 -LL | | } - | |_____^ expected i32, found u32 +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | if false { +LL | return 0i32; + | ---- ...is found to be `i32` here +LL | } else { +LL | 1u32 + | ^^^^ expected i32, found u32 | = note: expected type `i32` found type `u32` @@ -61,6 +59,52 @@ LL | | } = note: expected type `i32` found type `u32` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:39:14 + | +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | match 13 { +LL | 0 => return 0i32, + | ---- ...is found to be `i32` here +LL | _ => 1u32, + | ^^^^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5 + | +LL | fn can() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | / match 13 { +LL | | +LL | | 0 => return 0i32, + | | ---- ...is found to be `i32` here +LL | | 1 => 1u32, +LL | | _ => 2u32, +LL | | } + | |_____^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13 + | +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +... +LL | return 0i32; + | ---- ...is found to be `i32` here +... +LL | 1u32 + | ^^^^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/privacy/union-field-privacy-2.rs b/src/test/ui/privacy/union-field-privacy-2.rs index 48279630c6..c2458f74bc 100644 --- a/src/test/ui/privacy/union-field-privacy-2.rs +++ b/src/test/ui/privacy/union-field-privacy-2.rs @@ -11,5 +11,5 @@ fn main() { let a = u.a; // OK let b = u.b; // OK - let c = u.c; //~ ERROR field `c` of struct `m::U` is private + let c = u.c; //~ ERROR field `c` of union `m::U` is private } diff --git a/src/test/ui/privacy/union-field-privacy-2.stderr b/src/test/ui/privacy/union-field-privacy-2.stderr index df054b8cff..8789178caa 100644 --- a/src/test/ui/privacy/union-field-privacy-2.stderr +++ b/src/test/ui/privacy/union-field-privacy-2.stderr @@ -1,4 +1,4 @@ -error[E0616]: field `c` of struct `m::U` is private +error[E0616]: field `c` of union `m::U` is private --> $DIR/union-field-privacy-2.rs:14:13 | LL | let c = u.c; diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs new file mode 100644 index 0000000000..055781d2c6 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:attributes-on-definitions.rs + +#![forbid(unsafe_code)] + +extern crate attributes_on_definitions; + +attributes_on_definitions::with_attrs!(); +//~^ WARN use of deprecated item +// No errors about the use of unstable and unsafe code inside the macro. + +fn main() {} diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr new file mode 100644 index 0000000000..c61e043b22 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr @@ -0,0 +1,8 @@ +warning: use of deprecated item 'attributes_on_definitions::with_attrs': test + --> $DIR/attributes-on-definitions.rs:8:1 + | +LL | attributes_on_definitions::with_attrs!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + diff --git a/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs new file mode 100644 index 0000000000..93a339840d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[allow_internal_unstable(proc_macro_internals)] +#[allow_internal_unsafe] +#[deprecated(since = "1.0.0", note = "test")] +pub fn with_attrs(_: TokenStream) -> TokenStream { + " + extern crate proc_macro; + use ::proc_macro::bridge; + + fn contains_unsafe() { unsafe {} } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs new file mode 100644 index 0000000000..d4b67d6b0b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(repro)] +pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream { + "macro_rules! m {()=>{}}".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/derive-helper-configured.rs b/src/test/ui/proc-macro/derive-helper-configured.rs new file mode 100644 index 0000000000..243cf685e8 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-configured.rs @@ -0,0 +1,18 @@ +// Derive helpers are resolved successfully inside `cfg_attr`. + +// check-pass +// compile-flats:--cfg TRUE +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[cfg_attr(TRUE, empty_helper)] +#[derive(Empty)] +#[cfg_attr(TRUE, empty_helper)] +struct S { + #[cfg_attr(TRUE, empty_helper)] + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index 59ba1390e1..21af4093a0 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -19,7 +19,8 @@ struct S { struct U; mod inner { - #[empty_helper] //~ ERROR cannot find attribute macro `empty_helper` in this scope + // FIXME No ambiguity, attributes in non-macro positions are not resolved properly + #[empty_helper] struct V; } diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 149f6eef44..2ba517ce29 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,9 +1,3 @@ -error: cannot find attribute macro `empty_helper` in this scope - --> $DIR/derive-helper-shadowing.rs:22:15 - | -LL | #[empty_helper] - | ^^^^^^^^^^^^ - error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) --> $DIR/derive-helper-shadowing.rs:8:3 | @@ -22,6 +16,6 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs index 4e6f9b0722..3f8d6f0716 100644 --- a/src/test/ui/proc-macro/derive-still-gated.rs +++ b/src/test/ui/proc-macro/derive-still-gated.rs @@ -3,7 +3,7 @@ #[macro_use] extern crate test_macros; -#[derive_Empty] //~ ERROR cannot find attribute macro `derive_Empty` in this scope +#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope struct A; fn main() {} diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr index 4df1715db9..99289fdfe7 100644 --- a/src/test/ui/proc-macro/derive-still-gated.stderr +++ b/src/test/ui/proc-macro/derive-still-gated.stderr @@ -1,4 +1,4 @@ -error: cannot find attribute macro `derive_Empty` in this scope +error: cannot find attribute `derive_Empty` in this scope --> $DIR/derive-still-gated.rs:6:3 | LL | #[derive_Empty] diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index 0fe02a9a34..ea06f6c1ac 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -2,40 +2,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "M", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); @@ -43,39 +43,39 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index a499e1362e..7ee8078b2c 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -3,55 +3,55 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "identity", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: '!', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); @@ -59,54 +59,54 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "B", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "identity", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: '!', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "S", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index da1d7549d0..4f7e000265 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -2,40 +2,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "M", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); @@ -43,40 +43,40 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); @@ -84,80 +84,80 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "D", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "M", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); @@ -165,40 +165,40 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "A", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); @@ -206,39 +206,39 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "D", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs new file mode 100644 index 0000000000..13ad27f937 --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules.rs @@ -0,0 +1,13 @@ +// Derive macros can generate `macro_rules` items, regression test for issue #63651. + +// check-pass +// aux-build:gen-macro-rules.rs + +extern crate gen_macro_rules as repro; + +#[derive(repro::repro)] +pub struct S; + +m!(); // OK + +fn main() {} diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index 51bbb23da7..829d8bf4c8 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -2,13 +2,19 @@ error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not found in this scope + | in this macro invocation error[E0412]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not found in this scope + | in this macro invocation error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:12:1 diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index c9881ad2c3..94a4b403d5 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr index 40333a3f4c..107f5fb515 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-1.rs:10:1 + --> $DIR/invalid-punct-ident-1.rs:15:1 | LL | invalid_punct!(); | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 15e2286a65..778b7eeecd 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr index ec97e265c3..f1b9ecc6cb 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-2.rs:10:1 + --> $DIR/invalid-punct-ident-2.rs:15:1 | LL | invalid_ident!(); | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index 629bbaa9e3..f68ee3de7f 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr index a5e5ded653..6044b98874 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-3.rs:10:1 + --> $DIR/invalid-punct-ident-3.rs:15:1 | LL | invalid_raw_ident!(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index da2bf07a1a..65e40172ef 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -2,7 +2,10 @@ error: unexpected close delimiter: `)` --> $DIR/invalid-punct-ident-4.rs:6:1 | LL | lexer_failure!(); - | ^^^^^^^^^^^^^^^^^ unexpected close delimiter + | ^^^^^^^^^^^^^^^^^ + | | + | unexpected close delimiter + | in this macro invocation error: proc macro panicked --> $DIR/invalid-punct-ident-4.rs:6:1 diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr index 2d97cd700b..f28b8c9fb7 100644 --- a/src/test/ui/proc-macro/lints_in_proc_macros.stderr +++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr @@ -2,7 +2,10 @@ error[E0425]: cannot find value `foobar2` in this scope --> $DIR/lints_in_proc_macros.rs:12:5 | LL | bang_proc_macro2!(); - | ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` + | ^^^^^^^^^^^^^^^^^^^^ + | | + | help: a local variable with a similar name exists: `foobar` + | in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs index 8a26df9e76..b17c056593 100644 --- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs +++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs @@ -25,17 +25,17 @@ fn check_bang1() { my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it } fn check_bang2() { - my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope + my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines //~| ERROR expected macro, found attribute macro `crate::my_macro_attr` } fn check_bang3() { - MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope + MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it //~| ERROR expected macro, found derive macro `crate::MyTrait` } -#[my_macro] //~ ERROR cannot find attribute macro `my_macro` in this scope +#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope #[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it //~| ERROR expected attribute, found macro `crate::my_macro` fn check_attr1() {} diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr index b2f1247882..c011a70cd0 100644 --- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr +++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -88,7 +88,19 @@ error: expected derive macro, found macro `crate::my_macro` LL | #[derive(crate::my_macro)] | ^^^^^^^^^^^^^^^ not a derive macro -error: cannot find attribute macro `my_macro` in this scope +error: cannot find macro `my_macro_attr` in this scope + --> $DIR/macro-namespace-reserved-2.rs:28:5 + | +LL | my_macro_attr!(); + | ^^^^^^^^^^^^^ + +error: cannot find macro `MyTrait` in this scope + --> $DIR/macro-namespace-reserved-2.rs:33:5 + | +LL | MyTrait!(); + | ^^^^^^^ + +error: cannot find attribute `my_macro` in this scope --> $DIR/macro-namespace-reserved-2.rs:38:3 | LL | #[my_macro] @@ -100,17 +112,5 @@ error: cannot find derive macro `my_macro` in this scope LL | #[derive(my_macro)] | ^^^^^^^^ -error: cannot find macro `my_macro_attr!` in this scope - --> $DIR/macro-namespace-reserved-2.rs:28:5 - | -LL | my_macro_attr!(); - | ^^^^^^^^^^^^^ - -error: cannot find macro `MyTrait!` in this scope - --> $DIR/macro-namespace-reserved-2.rs:33:5 - | -LL | MyTrait!(); - | ^^^^^^^ - error: aborting due to 19 previous errors diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr index 44af07a794..e7f705c7fe 100644 --- a/src/test/ui/proc-macro/multispan.stderr +++ b/src/test/ui/proc-macro/multispan.stderr @@ -1,8 +1,19 @@ error: hello to you, too! - --> $DIR/multispan.rs:14:5 - | -LL | hello!(hi); - | ^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:14:5 + | +LL | hello!(hi); + | ----------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:14:12 @@ -11,10 +22,21 @@ LL | hello!(hi); | ^^ error: hello to you, too! - --> $DIR/multispan.rs:17:5 - | -LL | hello!(hi hi); - | ^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:17:5 + | +LL | hello!(hi hi); + | -------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:17:12 @@ -23,10 +45,21 @@ LL | hello!(hi hi); | ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:20:5 - | -LL | hello!(hi hi hi); - | ^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:20:5 + | +LL | hello!(hi hi hi); + | ----------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:20:12 @@ -35,10 +68,21 @@ LL | hello!(hi hi hi); | ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:23:5 - | -LL | hello!(hi hey hi yo hi beep beep hi hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:23:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ---------------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:23:12 @@ -47,10 +91,21 @@ LL | hello!(hi hey hi yo hi beep beep hi hi); | ^^ ^^ ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:24:5 - | -LL | hello!(hi there, hi how are you? hi... hi.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:24:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | -------------------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:24:12 @@ -59,10 +114,21 @@ LL | hello!(hi there, hi how are you? hi... hi.); | ^^ ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:25:5 - | -LL | hello!(whoah. hi di hi di ho); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:25:5 + | +LL | hello!(whoah. hi di hi di ho); + | ------------------------------ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:25:19 @@ -71,10 +137,21 @@ LL | hello!(whoah. hi di hi di ho); | ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:26:5 - | -LL | hello!(hi good hi and good bye); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:26:5 + | +LL | hello!(hi good hi and good bye); + | -------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:26:12 diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs index 04215226c6..6401522bdf 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.rs +++ b/src/test/ui/proc-macro/proc-macro-attributes.rs @@ -4,7 +4,7 @@ extern crate derive_b; #[B] //~ ERROR `B` is ambiguous -#[C] //~ ERROR cannot find attribute macro `C` in this scope +#[C] //~ ERROR cannot find attribute `C` in this scope #[B(D)] //~ ERROR `B` is ambiguous #[B(E = "foo")] //~ ERROR `B` is ambiguous #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr index b068c6bc83..3ac93a7485 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.stderr +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -1,4 +1,4 @@ -error: cannot find attribute macro `C` in this scope +error: cannot find attribute `C` in this scope --> $DIR/proc-macro-attributes.rs:7:3 | LL | #[C] diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs index 35d7fc8042..2fd5efd71f 100644 --- a/src/test/ui/proc-macro/proc-macro-gates2.rs +++ b/src/test/ui/proc-macro/proc-macro-gates2.rs @@ -10,11 +10,11 @@ extern crate test_macros; // should either require a feature gate or not be allowed on stable. fn _test6<#[empty_attr] T>() {} -//~^ ERROR: unknown to the compiler +//~^ ERROR: expected an inert attribute, found an attribute macro fn _test7() { match 1 { - #[empty_attr] //~ ERROR: unknown to the compiler + #[empty_attr] //~ ERROR: expected an inert attribute, found an attribute macro 0 => {} _ => {} } diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr index a7f6f8bfb1..fd271da615 100644 --- a/src/test/ui/proc-macro/proc-macro-gates2.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr @@ -1,21 +1,14 @@ -error[E0658]: the attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future +error: expected an inert attribute, found an attribute macro --> $DIR/proc-macro-gates2.rs:12:11 | LL | fn _test6<#[empty_attr] T>() {} | ^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable -error[E0658]: the attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future +error: expected an inert attribute, found an attribute macro --> $DIR/proc-macro-gates2.rs:17:9 | LL | #[empty_attr] | ^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs index 0a7861aba6..d2282af27f 100644 --- a/src/test/ui/proc-macro/resolve-error.rs +++ b/src/test/ui/proc-macro/resolve-error.rs @@ -23,12 +23,12 @@ macro_rules! attr_proc_mac { //~^ ERROR cannot find struct Foo; -// Interpreted as a feature gated custom attribute -#[attr_proc_macra] //~ ERROR cannot find attribute macro `attr_proc_macra` in this scope +// Interpreted as an unstable custom attribute +#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope struct Bar; -// Interpreted as a feature gated custom attribute -#[FooWithLongNan] //~ ERROR cannot find attribute macro `FooWithLongNan` in this scope +// Interpreted as an unstable custom attribute +#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope struct Asdf; #[derive(Dlone)] diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr index 3c9b2baacb..3dca5cee63 100644 --- a/src/test/ui/proc-macro/resolve-error.stderr +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -1,32 +1,26 @@ -error: cannot find derive macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:22:10 - | -LL | #[derive(FooWithLongNan)] - | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` - -error: cannot find attribute macro `attr_proc_macra` in this scope - --> $DIR/resolve-error.rs:27:3 +error: cannot find macro `bang_proc_macrp` in this scope + --> $DIR/resolve-error.rs:56:5 | -LL | #[attr_proc_macra] - | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` +LL | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` -error: cannot find attribute macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:31:3 +error: cannot find macro `Dlona` in this scope + --> $DIR/resolve-error.rs:53:5 | -LL | #[FooWithLongNan] - | ^^^^^^^^^^^^^^ +LL | Dlona!(); + | ^^^^^ -error: cannot find derive macro `Dlone` in this scope - --> $DIR/resolve-error.rs:34:10 +error: cannot find macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:50:5 | -LL | #[derive(Dlone)] - | ^^^^^ help: a derive macro with a similar name exists: `Clone` +LL | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` -error: cannot find derive macro `Dlona` in this scope - --> $DIR/resolve-error.rs:38:10 +error: cannot find macro `FooWithLongNama` in this scope + --> $DIR/resolve-error.rs:47:5 | -LL | #[derive(Dlona)] - | ^^^^^ help: a derive macro with a similar name exists: `Clona` +LL | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` error: cannot find derive macro `attr_proc_macra` in this scope --> $DIR/resolve-error.rs:42:10 @@ -34,29 +28,35 @@ error: cannot find derive macro `attr_proc_macra` in this scope LL | #[derive(attr_proc_macra)] | ^^^^^^^^^^^^^^^ -error: cannot find macro `FooWithLongNama!` in this scope - --> $DIR/resolve-error.rs:47:5 +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:38:10 | -LL | FooWithLongNama!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` -error: cannot find macro `attr_proc_macra!` in this scope - --> $DIR/resolve-error.rs:50:5 +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:34:10 | -LL | attr_proc_macra!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` -error: cannot find macro `Dlona!` in this scope - --> $DIR/resolve-error.rs:53:5 +error: cannot find attribute `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:31:3 | -LL | Dlona!(); - | ^^^^^ +LL | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ -error: cannot find macro `bang_proc_macrp!` in this scope - --> $DIR/resolve-error.rs:56:5 +error: cannot find attribute `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:27:3 | -LL | bang_proc_macrp!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` +LL | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` error: aborting due to 10 previous errors diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 0a82d28e9e..55835cb88f 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -9,7 +9,7 @@ extern crate test_macros; #[recollect_attr] fn a() { - let x: usize = "hello";;;;; //~ ERROR mismatched types + let x: usize = "hello"; //~ ERROR mismatched types } #[recollect_attr] diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index cf03deee7e..0290f4b2cc 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -6,7 +6,7 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/span-preservation.rs:12:20 | -LL | let x: usize = "hello";;;;; +LL | let x: usize = "hello"; | ^^^^^^^ expected usize, found reference | = note: expected type `usize` diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr index 5117dd6d32..06715c197b 100644 --- a/src/test/ui/proc-macro/subspan.stderr +++ b/src/test/ui/proc-macro/subspan.stderr @@ -2,7 +2,7 @@ error: found 'hi's --> $DIR/subspan.rs:11:1 | LL | subspan!("hi"); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:11:11 @@ -14,7 +14,7 @@ error: found 'hi's --> $DIR/subspan.rs:14:1 | LL | subspan!("hihi"); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:14:11 @@ -26,7 +26,7 @@ error: found 'hi's --> $DIR/subspan.rs:17:1 | LL | subspan!("hihihi"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:17:11 @@ -38,7 +38,7 @@ error: found 'hi's --> $DIR/subspan.rs:20:1 | LL | subspan!("why I hide? hi!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:20:17 @@ -50,7 +50,7 @@ error: found 'hi's --> $DIR/subspan.rs:21:1 | LL | subspan!("hey, hi, hidy, hidy, hi hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:21:16 @@ -62,7 +62,7 @@ error: found 'hi's --> $DIR/subspan.rs:22:1 | LL | subspan!("this is a hi, and this is another hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:22:12 @@ -74,7 +74,7 @@ error: found 'hi's --> $DIR/subspan.rs:23:1 | LL | subspan!("how are you this evening"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:23:24 @@ -86,7 +86,7 @@ error: found 'hi's --> $DIR/subspan.rs:24:1 | LL | subspan!("this is highly eradic"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:24:12 diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr index f8dfa841d4..0698b0f475 100644 --- a/src/test/ui/proc-macro/three-equals.stderr +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -1,8 +1,19 @@ error: found 2 equal signs, need exactly 3 - --> $DIR/three-equals.rs:15:5 - | -LL | three_equals!(==); - | ^^^^^^^^^^^^^^^^^^ + --> $DIR/auxiliary/three-equals.rs:42:1 + | +LL | / pub fn three_equals(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | return TokenStream::new(); +... | +LL | | "3".parse().unwrap() +LL | | } + | |_^ + | + ::: $DIR/three-equals.rs:15:5 + | +LL | three_equals!(==); + | ------------------ in this macro invocation | = help: input must be: `===` diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index 02b29021cb..880dea1cc3 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_add.rs:17:13 | LL | let x = Foo + return; - | ^^^^^^^^^^^^ + | ^^^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_add.rs:3:9 diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index bdc3d143ea..9500688424 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/expr_again.rs:8:9 | +LL | continue; + | -------- any code following this expression is unreachable LL | println!("hi"); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/expr_again.rs:3:9 diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index 18d7ffe74b..b3138d3c33 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -2,7 +2,9 @@ error: unreachable expression --> $DIR/expr_array.rs:9:34 | LL | let x: [usize; 2] = [return, 22]; - | ^^ + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable | note: lint level defined here --> $DIR/expr_array.rs:4:9 @@ -14,7 +16,10 @@ error: unreachable expression --> $DIR/expr_array.rs:14:25 | LL | let x: [usize; 2] = [22, return]; - | ^^^^^^^^^^^^ + | ^^^^^------^ + | | | + | | any code following this expression is unreachable + | unreachable expression error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index def16d90a7..3004da0406 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_assign.rs:10:5 | LL | x = return; - | ^^^^^^^^^^ + | ^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_assign.rs:5:9 @@ -14,13 +17,17 @@ error: unreachable expression --> $DIR/expr_assign.rs:20:14 | LL | *p = return; - | ^^^^^^ + | -- ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable error: unreachable expression --> $DIR/expr_assign.rs:26:15 | LL | *{return; &mut i} = 22; - | ^^^^^^ + | ------ ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index a498502e6c..44baddd1e5 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -1,8 +1,10 @@ error: unreachable expression --> $DIR/expr_block.rs:10:9 | +LL | return; + | ------ any code following this expression is unreachable LL | 22 - | ^^ + | ^^ unreachable expression | note: lint level defined here --> $DIR/expr_block.rs:4:9 @@ -13,8 +15,10 @@ LL | #![deny(unreachable_code)] error: unreachable statement --> $DIR/expr_block.rs:25:9 | +LL | return; + | ------ any code following this expression is unreachable LL | println!("foo"); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr index 63137ce3da..b01a13e9df 100644 --- a/src/test/ui/reachable/expr_box.stderr +++ b/src/test/ui/reachable/expr_box.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_box.rs:6:13 | LL | let x = box return; - | ^^^^^^^^^^ + | ^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_box.rs:3:9 diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index df5cff16f9..ae8b4dd87b 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -2,7 +2,9 @@ error: unreachable expression --> $DIR/expr_call.rs:13:17 | LL | foo(return, 22); - | ^^ + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable | note: lint level defined here --> $DIR/expr_call.rs:5:9 @@ -10,11 +12,13 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression +error: unreachable call --> $DIR/expr_call.rs:18:5 | LL | bar(return); - | ^^^^^^^^^^^ + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index 3086745d28..81813d1d71 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_cast.rs:9:13 | LL | let x = {return} as !; - | ^^^^^^^^^^^^^ + | ^------^^^^^^ + | || + | |any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_cast.rs:4:9 diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index f1690e595e..ccd45ccec6 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -2,10 +2,12 @@ error: unreachable block in `if` expression --> $DIR/expr_if.rs:7:17 | LL | if {return} { - | _________________^ + | _________------__^ + | | | + | | any code following this expression is unreachable LL | | println!("Hello, world!"); LL | | } - | |_____^ + | |_____^ unreachable block in `if` expression | note: lint level defined here --> $DIR/expr_if.rs:4:9 @@ -16,8 +18,11 @@ LL | #![deny(unreachable_code)] error: unreachable statement --> $DIR/expr_if.rs:27:5 | +LL | return; + | ------ any code following this expression is unreachable +... LL | println!("But I am."); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 4d3e06c93a..5f279c9630 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/expr_loop.rs:8:5 | +LL | loop { return; } + | ------ any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/expr_loop.rs:4:9 @@ -14,16 +16,20 @@ LL | #![deny(unreachable_code)] error: unreachable statement --> $DIR/expr_loop.rs:21:5 | +LL | loop { return; } + | ------ any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement --> $DIR/expr_loop.rs:32:5 | +LL | loop { 'middle: loop { loop { break 'middle; } } } + | -------------------------------------------------- any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 1aef06aec5..d39acdc290 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -1,8 +1,10 @@ error: unreachable statement --> $DIR/expr_match.rs:8:5 | +LL | match () { () => return } + | ------------------------- any code following this `match` expression is unreachable, as all arms diverge LL | println!("I am dead"); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/expr_match.rs:4:9 @@ -14,8 +16,10 @@ LL | #![deny(unreachable_code)] error: unreachable statement --> $DIR/expr_match.rs:19:5 | +LL | match () { () if false => return, () => return } + | ------------------------------------------------ any code following this `match` expression is unreachable, as all arms diverge LL | println!("I am dead"); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index bbfa2ef529..82a0745f06 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -2,7 +2,9 @@ error: unreachable expression --> $DIR/expr_method.rs:16:21 | LL | Foo.foo(return, 22); - | ^^ + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable | note: lint level defined here --> $DIR/expr_method.rs:5:9 @@ -10,11 +12,13 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression - --> $DIR/expr_method.rs:21:5 +error: unreachable call + --> $DIR/expr_method.rs:21:9 | LL | Foo.bar(return); - | ^^^^^^^^^^^^^^^ + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 0536cdef72..34129936fd 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_repeat.rs:9:25 | LL | let x: [usize; 2] = [return; 2]; - | ^^^^^^^^^^^ + | ^------^^^^ + | || + | |any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_repeat.rs:4:9 diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index 3317da58ab..c0a94746d0 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_return.rs:10:22 | LL | let x = {return {return {return;}}}; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_return.rs:4:9 diff --git a/src/test/ui/reachable/expr_return_in_macro.rs b/src/test/ui/reachable/expr_return_in_macro.rs new file mode 100644 index 0000000000..4e57618bf5 --- /dev/null +++ b/src/test/ui/reachable/expr_return_in_macro.rs @@ -0,0 +1,15 @@ +// Tests that we generate nice error messages +// when an expression is unreachble due to control +// flow inside of a macro expansion. +#![deny(unreachable_code)] + +macro_rules! early_return { + () => { + return () + } +} + +fn main() { + return early_return!(); + //~^ ERROR unreachable expression +} diff --git a/src/test/ui/reachable/expr_return_in_macro.stderr b/src/test/ui/reachable/expr_return_in_macro.stderr new file mode 100644 index 0000000000..2bc6a763cf --- /dev/null +++ b/src/test/ui/reachable/expr_return_in_macro.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_return_in_macro.rs:13:5 + | +LL | return () + | --------- any code following this expression is unreachable +... +LL | return early_return!(); + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable expression + | +note: lint level defined here + --> $DIR/expr_return_in_macro.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index dcccb7a4db..b3ca06eada 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_struct.rs:14:13 | LL | let x = Foo { a: 22, b: 33, ..return }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_struct.rs:4:9 @@ -14,19 +17,26 @@ error: unreachable expression --> $DIR/expr_struct.rs:19:33 | LL | let x = Foo { a: return, b: 33, ..return }; - | ^^ + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable error: unreachable expression --> $DIR/expr_struct.rs:24:39 | LL | let x = Foo { a: 22, b: return, ..return }; - | ^^^^^^ + | ------ ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable error: unreachable expression --> $DIR/expr_struct.rs:29:13 | LL | let x = Foo { a: 22, b: return }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression error: aborting due to 4 previous errors diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index 1837031107..aaaf6462da 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -2,7 +2,9 @@ error: unreachable expression --> $DIR/expr_tup.rs:9:38 | LL | let x: (usize, usize) = (return, 2); - | ^ + | ------ ^ unreachable expression + | | + | any code following this expression is unreachable | note: lint level defined here --> $DIR/expr_tup.rs:4:9 @@ -14,7 +16,10 @@ error: unreachable expression --> $DIR/expr_tup.rs:14:29 | LL | let x: (usize, usize) = (2, return); - | ^^^^^^^^^^^ + | ^^^^------^ + | | | + | | any code following this expression is unreachable + | unreachable expression error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index f867c89163..cb6e8d7039 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/expr_type.rs:9:13 | LL | let x = {return}: !; - | ^^^^^^^^^^^ + | ^------^^^^ + | || + | |any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_type.rs:4:9 diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index 61982289cd..f5c3564217 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -8,7 +8,10 @@ error: unreachable expression --> $DIR/expr_unary.rs:8:16 | LL | let x: ! = ! { return; }; - | ^^^^^^^^^^^^^ + | ^^^^------^^^ + | | | + | | any code following this expression is unreachable + | unreachable expression | note: lint level defined here --> $DIR/expr_unary.rs:5:9 diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index fc528926b4..edb1dd2b9b 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -2,11 +2,13 @@ error: unreachable block in `while` expression --> $DIR/expr_while.rs:7:20 | LL | while {return} { - | ____________________^ + | ____________------__^ + | | | + | | any code following this expression is unreachable LL | | LL | | println!("Hello, world!"); LL | | } - | |_____^ + | |_____^ unreachable block in `while` expression | note: lint level defined here --> $DIR/expr_while.rs:4:9 @@ -18,11 +20,13 @@ error: unreachable block in `while` expression --> $DIR/expr_while.rs:22:20 | LL | while {return} { - | ____________________^ + | ____________------__^ + | | | + | | any code following this expression is unreachable LL | | LL | | println!("I am dead."); LL | | } - | |_____^ + | |_____^ unreachable block in `while` expression error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-requirements.stderr b/src/test/ui/recursion/recursive-requirements.stderr index b3041902ac..9846c938ba 100644 --- a/src/test/ui/recursion/recursive-requirements.stderr +++ b/src/test/ui/recursion/recursive-requirements.stderr @@ -1,20 +1,21 @@ error[E0277]: `*const Bar` cannot be shared between threads safely --> $DIR/recursive-requirements.rs:16:12 | +LL | struct AssertSync(PhantomData); + | ------------------------------------------- required by `AssertSync` +... LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely | = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `*const Bar` = note: required because it appears within the type `Foo` -note: required by `AssertSync` - --> $DIR/recursive-requirements.rs:3:1 - | -LL | struct AssertSync(PhantomData); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*const Foo` cannot be shared between threads safely --> $DIR/recursive-requirements.rs:16:12 | +LL | struct AssertSync(PhantomData); + | ------------------------------------------- required by `AssertSync` +... LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely | @@ -22,11 +23,6 @@ LL | let _: AssertSync = unimplemented!(); = note: required because it appears within the type `Bar` = note: required because it appears within the type `std::marker::PhantomData` = note: required because it appears within the type `Foo` -note: required by `AssertSync` - --> $DIR/recursive-requirements.rs:3:1 - | -LL | struct AssertSync(PhantomData); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs index 45910c3c3a..f6b317886b 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -6,7 +6,7 @@ fn foo(res: Result) -> u32 { let Ok(x) = res; //~^ ERROR refutable pattern x - //~^ ERROR use of possibly uninitialized variable: `x` + //~^ ERROR use of possibly-uninitialized variable: `x` } fn main() { diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index eee331d95b..b9385952fa 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -4,11 +4,11 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 | LL | x - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/refutable-pattern-errors.rs b/src/test/ui/refutable-pattern-errors.rs index aa5fa76bb8..d4afe17ca7 100644 --- a/src/test/ui/refutable-pattern-errors.rs +++ b/src/test/ui/refutable-pattern-errors.rs @@ -1,7 +1,9 @@ +// ignore-tidy-linelength + fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } //~^ ERROR refutable pattern in function argument: `(_, _)` not covered fn main() { let (1, (Some(1), 2..=3)) = (1, (None, 2)); - //~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered + //~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered } diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr index c67ae7c6d4..3b13e25293 100644 --- a/src/test/ui/refutable-pattern-errors.stderr +++ b/src/test/ui/refutable-pattern-errors.stderr @@ -1,14 +1,14 @@ error[E0005]: refutable pattern in function argument: `(_, _)` not covered - --> $DIR/refutable-pattern-errors.rs:1:9 + --> $DIR/refutable-pattern-errors.rs:3:9 | LL | fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered -error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered - --> $DIR/refutable-pattern-errors.rs:5:9 +error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered + --> $DIR/refutable-pattern-errors.rs:7:9 | LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); - | ^^^^^^^^^^^^^^^^^^^^^ pattern `(std::i32::MIN..=0i32, _)` not covered + | ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr index 867eafe252..4944f2649b 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr index f31f25bf00..61be0778c9 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr @@ -1,16 +1,16 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 37:15 - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 33:15 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 37:18 - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 33:18 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18 | LL | fn with_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr index 867eafe252..4944f2649b 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs index 97c5559360..046d010002 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs @@ -8,8 +8,6 @@ #![allow(dead_code)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -28,8 +26,6 @@ impl<'b> TheTrait for TheType<'b> { impl<'b> TheSubTrait for TheType<'b> { } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc { m: [T; 0] } diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 390f8e7baa..01975d40fd 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr @@ -52,26 +52,26 @@ LL | // oh dear! LL | box B(&*v) as Box | ^^^^^^ | -note: ...so that the reference type `&dyn A` does not outlive the data it points at +note: ...so that the type `T` will meet its required lifetime bounds --> $DIR/regions-close-object-into-object-5.rs:17:9 | LL | box B(&*v) as Box | ^^^^^^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:9 + --> $DIR/regions-close-object-into-object-5.rs:17:11 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { | - help: consider adding an explicit lifetime bound `T: 'static`... LL | // oh dear! LL | box B(&*v) as Box - | ^^^^^^ + | ^^^ | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:9 +note: ...so that the reference type `&dyn A` does not outlive the data it points at + --> $DIR/regions-close-object-into-object-5.rs:17:11 | LL | box B(&*v) as Box - | ^^^^^^ + | ^^^ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 diff --git a/src/test/ui/regions/regions-early-bound-error-method.stderr b/src/test/ui/regions/regions-early-bound-error-method.stderr index 2e5f55f874..7b9f2c9503 100644 --- a/src/test/ui/regions/regions-early-bound-error-method.stderr +++ b/src/test/ui/regions/regions-early-bound-error-method.stderr @@ -17,3 +17,4 @@ LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr index bc52f4bef7..a68355b78f 100644 --- a/src/test/ui/regions/regions-early-bound-error.stderr +++ b/src/test/ui/regions/regions-early-bound-error.stderr @@ -17,3 +17,4 @@ LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index 4840d751f7..5f6a48a35f 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -49,14 +49,14 @@ LL | fn fn_types(a: &'a isize, error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:42:36 | -LL | &'b isize, - | ^^ undeclared lifetime +LL | ... &'b isize, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:45:36 | -LL | &'b isize)>, - | ^^ undeclared lifetime +LL | ... &'b isize)>, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:46:17 diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr index 15c9c9ca4d..904dee6998 100644 --- a/src/test/ui/regions/regions-nested-fns.stderr +++ b/src/test/ui/regions/regions-nested-fns.stderr @@ -57,3 +57,4 @@ LL | fn nested<'x>(x: &'x isize) { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr index 5028663ba6..eed9934be1 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr index d833018400..ed5800940e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr @@ -1,33 +1,33 @@ error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithHrAssocSub>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | let _: &'a WithHrAssocSub> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19 +note: the pointer is valid for the lifetime 'a as defined on the function body at 46:19 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19 | LL | fn with_assoc_sub<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 46:22 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22 | LL | fn with_assoc_sub<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr index 5028663ba6..eed9934be1 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs index 407a4fdf59..cee741184c 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -6,9 +6,6 @@ #![allow(dead_code)] - -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait<'b> { type TheAssocType; } @@ -21,8 +18,6 @@ impl<'a,'b> TheTrait<'a> for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithHrAssoc where for<'a> T : TheTrait<'a> { @@ -37,8 +32,6 @@ fn with_assoc<'a,'b>() { //[nll]~^^ ERROR lifetime may not live long enough } -/////////////////////////////////////////////////////////////////////////// - pub trait TheSubTrait : for<'a> TheTrait<'a> { } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr index 880fe17b74..8c54d8da0a 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 9e31065ca4..152e6c5600 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr @@ -1,16 +1,16 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15 - --> $DIR/regions-outlives-projection-container-wc.rs:31:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-wc.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18 - --> $DIR/regions-outlives-projection-container-wc.rs:31:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-wc.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr index 880fe17b74..8c54d8da0a 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index 5037ea536d..99965f3339 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -8,8 +8,6 @@ #![allow(dead_code)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -22,8 +20,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc where T : TheTrait { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr index ef87d02ec0..2cf6e245d1 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | fn without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -21,7 +21,7 @@ LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:67:5 + --> $DIR/regions-outlives-projection-container.rs:63:5 | LL | fn call_with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -32,7 +32,7 @@ LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:74:5 + --> $DIR/regions-outlives-projection-container.rs:70:5 | LL | fn call_without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container.rs b/src/test/ui/regions/regions-outlives-projection-container.rs index 78305c0693..3afc600bec 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.rs +++ b/src/test/ui/regions/regions-outlives-projection-container.rs @@ -5,8 +5,6 @@ #![allow(dead_code)] #![feature(rustc_attrs)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -19,8 +17,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index b50347ac96..3c1a98a3c0 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -1,67 +1,67 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 + --> $DIR/regions-outlives-projection-container.rs:28:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 28:18 + --> $DIR/regions-outlives-projection-container.rs:28:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 54:18 - --> $DIR/regions-outlives-projection-container.rs:54:18 +note: the pointer is valid for the lifetime 'a as defined on the function body at 50:18 + --> $DIR/regions-outlives-projection-container.rs:50:18 | LL | fn without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 54:21 - --> $DIR/regions-outlives-projection-container.rs:54:21 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 50:21 + --> $DIR/regions-outlives-projection-container.rs:50:21 | LL | fn without_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:67:12 + --> $DIR/regions-outlives-projection-container.rs:63:12 | LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 62:20 - --> $DIR/regions-outlives-projection-container.rs:62:20 +note: the pointer is valid for the lifetime 'a as defined on the function body at 58:20 + --> $DIR/regions-outlives-projection-container.rs:58:20 | LL | fn call_with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 62:23 - --> $DIR/regions-outlives-projection-container.rs:62:23 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 58:23 + --> $DIR/regions-outlives-projection-container.rs:58:23 | LL | fn call_with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:74:12 + --> $DIR/regions-outlives-projection-container.rs:70:12 | LL | call::<&'a WithoutAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 71:23 - --> $DIR/regions-outlives-projection-container.rs:71:23 +note: the pointer is valid for the lifetime 'a as defined on the function body at 67:23 + --> $DIR/regions-outlives-projection-container.rs:67:23 | LL | fn call_without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 71:26 - --> $DIR/regions-outlives-projection-container.rs:71:26 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 67:26 + --> $DIR/regions-outlives-projection-container.rs:67:26 | LL | fn call_without_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-static-bound.migrate.stderr b/src/test/ui/regions/regions-static-bound.migrate.stderr index fc8cca929d..21ead8b768 100644 --- a/src/test/ui/regions/regions-static-bound.migrate.stderr +++ b/src/test/ui/regions/regions-static-bound.migrate.stderr @@ -30,4 +30,5 @@ LL | static_id_indirect(&v); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0621`. +Some errors have detailed explanations: E0312, E0621. +For more information about an error, try `rustc --explain E0312`. diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs new file mode 100644 index 0000000000..09baa059e5 --- /dev/null +++ b/src/test/ui/reify-intrinsic.rs @@ -0,0 +1,15 @@ +// check-fail + +#![feature(intrinsics)] + +fn a() { + let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + //~^ ERROR cannot coerce +} + +fn b() { + let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + //~^ ERROR casting +} + +fn main() {} diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr new file mode 100644 index 0000000000..4a1bd77cf7 --- /dev/null +++ b/src/test/ui/reify-intrinsic.stderr @@ -0,0 +1,22 @@ +error[E0308]: cannot coerce intrinsics to function pointers + --> $DIR/reify-intrinsic.rs:6:64 + | +LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + | ^^^^^^^^^^^^^^^^^^^ + | | + | cannot coerce intrinsics to function pointers + | help: use parentheses to call this function: `std::mem::transmute(...)` + | + = note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize` + found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` + +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid + --> $DIR/reify-intrinsic.rs:11:13 + | +LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0606. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs index fddb991da8..2630db0d09 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.rs +++ b/src/test/ui/reserved/reserved-attr-on-macro.rs @@ -1,5 +1,5 @@ #[rustc_attribute_should_be_reserved] -//~^ ERROR cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope +//~^ ERROR cannot find attribute `rustc_attribute_should_be_reserved` in this scope //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler macro_rules! foo { diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index d4b97d290e..685960588a 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -7,12 +7,6 @@ LL | #[rustc_attribute_should_be_reserved] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope - --> $DIR/reserved-attr-on-macro.rs:1:3 - | -LL | #[rustc_attribute_should_be_reserved] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: cannot determine resolution for the macro `foo` --> $DIR/reserved-attr-on-macro.rs:10:5 | @@ -21,6 +15,12 @@ LL | foo!(); | = note: import resolution is stuck, try simplifying macro imports +error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope + --> $DIR/reserved-attr-on-macro.rs:1:3 + | +LL | #[rustc_attribute_should_be_reserved] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/reserved/reserved-become.rs b/src/test/ui/reserved/reserved-become.rs index 2279a05e6b..56645255ee 100644 --- a/src/test/ui/reserved/reserved-become.rs +++ b/src/test/ui/reserved/reserved-become.rs @@ -1,4 +1,4 @@ fn main() { let become = 0; - //~^ ERROR expected pattern, found reserved keyword `become` + //~^ ERROR expected identifier, found reserved keyword `become` } diff --git a/src/test/ui/reserved/reserved-become.stderr b/src/test/ui/reserved/reserved-become.stderr index f9fe78e18b..3ce9fb33c2 100644 --- a/src/test/ui/reserved/reserved-become.stderr +++ b/src/test/ui/reserved/reserved-become.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `become` +error: expected identifier, found reserved keyword `become` --> $DIR/reserved-become.rs:2:9 | LL | let become = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#become = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/resolve/block-with-trait-parent.rs b/src/test/ui/resolve/block-with-trait-parent.rs new file mode 100644 index 0000000000..bc86f94e92 --- /dev/null +++ b/src/test/ui/resolve/block-with-trait-parent.rs @@ -0,0 +1,14 @@ +// check-pass + +trait Trait { + fn method(&self) { + // Items inside a block turn it into a module internally. + struct S; + impl Trait for S {} + + // OK, `Trait` is in scope here from method resolution point of view. + S.method(); + } +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 968c1f3e46..63ac11dc8a 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object | - = note: method `bar` has no receiver + = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs index 595eaf440c..0e1142db37 100644 --- a/src/test/ui/resolve/visibility-indeterminate.rs +++ b/src/test/ui/resolve/visibility-indeterminate.rs @@ -1,5 +1,7 @@ // edition:2018 -foo!(); //~ ERROR cannot find macro `foo!` in this scope +foo!(); //~ ERROR cannot find macro `foo` in this scope pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility + +fn main() {} diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr index a259c8090b..b9678291ee 100644 --- a/src/test/ui/resolve/visibility-indeterminate.stderr +++ b/src/test/ui/resolve/visibility-indeterminate.stderr @@ -4,16 +4,11 @@ error[E0578]: cannot determine resolution for the visibility LL | pub(in ::bar) struct Baz {} | ^^^^^ -error: cannot find macro `foo!` in this scope +error: cannot find macro `foo` in this scope --> $DIR/visibility-indeterminate.rs:3:1 | LL | foo!(); | ^^^ -error[E0601]: `main` function not found in crate `visibility_indeterminate` - | - = note: consider adding a `main` function to `$DIR/visibility-indeterminate.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs index e43c8541e6..1e086160f3 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs @@ -4,15 +4,13 @@ // run-pass -#![feature(bind_by_move_pattern_guards)] - use std::sync::mpsc::channel; fn main() { let (tx, rx) = channel(); let x = Some(rx); - tx.send(false); - tx.send(false); + tx.send(false).unwrap(); + tx.send(false).unwrap(); match x { Some(z) if z.recv().unwrap() => { panic!() }, Some(z) => { assert!(!z.recv().unwrap()); }, diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr deleted file mode 100644 index fe1f699074..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:36:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr deleted file mode 100644 index fe1f699074..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:36:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr deleted file mode 100644 index 34e8b0e143..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:41:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr deleted file mode 100644 index 34e8b0e143..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:41:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr deleted file mode 100644 index 7a7b1c2535..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/feature-gate.rs:28:16 - | -LL | A { a: v } if *v == 42 => v, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs deleted file mode 100644 index 69fce0bc77..0000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Check that pattern-guards with move-bound variables is only allowed -// with the appropriate set of feature gates. (Note that we require -// the code to opt into MIR-borrowck in *some* way before the feature -// will work; we use the revision system here to enumerate a number of -// ways that opt-in could occur.) - -// gate-test-bind_by_move_pattern_guards - -// revisions: no_gate gate_and_2015 gate_and_2018 - -// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.) -// ignore-compare-mode-nll - -#![feature(rustc_attrs)] - -#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))] -#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))] - -//[gate_and_2015] edition:2015 -//[gate_and_2018] edition:2018 - -struct A { a: Box } - -fn foo(n: i32) { - let x = A { a: Box::new(n) }; - let _y = match x { - - A { a: v } if *v == 42 => v, - //[no_gate]~^ ERROR cannot bind by-move into a pattern guard - - _ => Box::new(0) - }; -} - -#[rustc_error] -fn main() { - foo(107) -} -//[gate_and_2015]~^^^ ERROR compilation successful -//[gate_and_2018]~^^^^ ERROR compilation successful diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs new file mode 100644 index 0000000000..3161d6fbbe --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs @@ -0,0 +1,11 @@ +// This test used to emit E0008 but now passed since `bind_by_move_pattern_guards` +// have been stabilized. + +// check-pass + +fn main() { + match Some("hi".to_string()) { + Some(s) if s.len() == 0 => {}, + _ => {}, + } +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs index eccb4e417b..b716fc870e 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - // run-pass struct A { a: Box } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs index 602a8e15cb..d1f685f3e7 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - enum VecWrapper { A(Vec) } fn foo(x: VecWrapper) -> usize { diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr index c9e8fc8ee5..7becd01324 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-across-arms.rs:7:36 + --> $DIR/rfc-reject-double-move-across-arms.rs:5:36 | LL | VecWrapper::A(v) if { drop(v); false } => 1, | ^ move occurs because `v` has type `std::vec::Vec`, which does not implement the `Copy` trait diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs index 77252a1ce1..571f51c900 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - struct A { a: Box } fn foo(n: i32) { diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr index a345022cee..b93e721906 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30 + --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30 | LL | A { a: v } if { drop(v); true } => v, | ^ move occurs because `v` has type `std::boxed::Box`, which does not implement the `Copy` trait diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs index 193a523aed..c27cea302f 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs @@ -1,4 +1,6 @@ // compile-flags: --test +// ignore-x86 +// ^ due to stderr output differences use std::num::ParseFloatError; diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index f253b67a01..6aa95c308f 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -1,13 +1,17 @@ error[E0277]: `main` has invalid return type `std::result::Result` - --> $DIR/termination-trait-test-wrong-type.rs:6:1 + --> $DIR/termination-trait-test-wrong-type.rs:8:1 | LL | / fn can_parse_zero_as_f32() -> Result { LL | | "0".parse() LL | | } | |_^ `main` can only return types that implement `std::process::Termination` + | + ::: $SRC_DIR/libtest/lib.rs:LL:COL + | +LL | pub fn assert_test_result(result: T) { + | ----------- required by this bound in `test::assert_test_result` | = help: the trait `std::process::Termination` is not implemented for `std::result::Result` - = note: required by `test::assert_test_result` error: aborting due to previous error diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs index 470a5ea983..fe7df44590 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs @@ -10,11 +10,11 @@ pub enum NonExhaustiveVariants { fn main() { let variant_tuple = NonExhaustiveVariants::Tuple(340); - let variant_struct = NonExhaustiveVariants::Struct { field: 340 }; + let _variant_struct = NonExhaustiveVariants::Struct { field: 340 }; match variant_tuple { NonExhaustiveVariants::Unit => "", - NonExhaustiveVariants::Tuple(fe_tpl) => "", - NonExhaustiveVariants::Struct { field } => "" + NonExhaustiveVariants::Tuple(_fe_tpl) => "", + NonExhaustiveVariants::Struct { field: _ } => "" }; } diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs index e885263aa8..04d924a9ae 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs @@ -1,7 +1,5 @@ // run-pass -// ignore-cloudabi no processes -// ignore-emscripten no processes -// ignore-sgx no processes +// check-run-results // Tests ensuring that `dbg!(expr)` has the expected run-time behavior. // as well as some compile time properties we expect. @@ -18,7 +16,7 @@ struct Point { #[derive(Debug, PartialEq)] struct NoCopy(usize); -fn test() { +fn main() { let a: Unit = dbg!(Unit); let _: Unit = dbg!(a); // We can move `a` because it's Copy. @@ -67,81 +65,3 @@ fn test() { assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32, "Yeah",)); } - -fn validate_stderr(stderr: Vec) { - assert_eq!(stderr, &[ - ":22] Unit = Unit", - - ":23] a = Unit", - - ":29] Point{x: 42, y: 24,} = Point {", - " x: 42,", - " y: 24,", - "}", - - ":30] b = Point {", - " x: 42,", - " y: 24,", - "}", - - ":38]", - - ":42] &a = NoCopy(", - " 1337,", - ")", - - ":42] dbg!(& a) = NoCopy(", - " 1337,", - ")", - ":47] f(&42) = 42", - - "before", - ":52] { foo += 1; eprintln!(\"before\"); 7331 } = 7331", - - ":60] (\"Yeah\",) = (", - " \"Yeah\",", - ")", - - ":63] 1 = 1", - ":63] 2 = 2", - - ":67] 1u8 = 1", - ":67] 2u32 = 2", - ":67] \"Yeah\" = \"Yeah\"", - ]); -} - -fn main() { - // The following is a hack to deal with compiletest's inability - // to check the output (to stdout) of run-pass tests. - use std::env; - use std::process::Command; - - let mut args = env::args(); - let prog = args.next().unwrap(); - let child = args.next(); - if let Some("child") = child.as_ref().map(|s| &**s) { - // Only run the test if we've been spawned as 'child' - test() - } else { - // This essentially spawns as 'child' to run the tests - // and then it collects output of stderr and checks the output - // against what we expect. - let out = Command::new(&prog).arg("child").output().unwrap(); - assert!(out.status.success()); - assert!(out.stdout.is_empty()); - - let stderr = String::from_utf8(out.stderr).unwrap(); - let stderr = stderr.lines().map(|mut s| { - if s.starts_with("[") { - // Strip `[` and file path: - s = s.trim_start_matches("["); - assert!(s.starts_with(file!())); - s = s.trim_start_matches(file!()); - } - s.to_owned() - }).collect(); - - validate_stderr(stderr); - } -} diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr new file mode 100644 index 0000000000..707b38cf37 --- /dev/null +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr @@ -0,0 +1,28 @@ +[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit +[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit +[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:28] b = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:36] +[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42 +before +[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331 +[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = ( + "Yeah", +) +[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1 +[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1 +[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah" diff --git a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs index 1de4e5bceb..b95105b59e 100644 --- a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs +++ b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs @@ -2,8 +2,6 @@ #![allow(irrefutable_let_patterns)] -use std::ops::Range; - fn main() { let x: bool; // This should associate as: `(x = (true && false));`. diff --git a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr new file mode 100644 index 0000000000..cf8f0e9830 --- /dev/null +++ b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr @@ -0,0 +1,10 @@ +warning: unreachable block in `if` expression + --> $DIR/protect-precedences.rs:13:41 + | +LL | if let _ = return true && false {}; + | -------------------- ^^ unreachable block in `if` expression + | | + | any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + diff --git a/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs b/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs new file mode 100644 index 0000000000..eeb2191bab --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs @@ -0,0 +1,16 @@ +#[cfg(FALSE)] +impl S { + fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` +} + +#[cfg(FALSE)] +impl T for S { + fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` +} + +#[cfg(FALSE)] +trait T { + fn f(#[attr]); //~ ERROR expected argument name, found `)` +} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr b/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr new file mode 100644 index 0000000000..26dff4d4b3 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr @@ -0,0 +1,20 @@ +error: expected parameter name, found `)` + --> $DIR/attr-without-param.rs:3:17 + | +LL | fn f(#[attr]) {} + | ^ expected parameter name + +error: expected parameter name, found `)` + --> $DIR/attr-without-param.rs:8:17 + | +LL | fn f(#[attr]) {} + | ^ expected parameter name + +error: expected argument name, found `)` + --> $DIR/attr-without-param.rs:13:17 + | +LL | fn f(#[attr]); + | ^ expected argument name + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs new file mode 100644 index 0000000000..b62cf31205 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs index 71815e3c08..c537c1034b 100644 --- a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -11,7 +11,6 @@ macro_rules! checker { ($attr_name:ident, $expected:literal) => { #[proc_macro_attribute] pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream { - assert!(attr.to_string().is_empty()); assert_eq!(input.to_string(), $expected); TokenStream::new() } @@ -28,7 +27,18 @@ checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }"); checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }"); checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }"); checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box, #[a2] arg1: u8) { }"); +checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) { }"); checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);"); checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);"); checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);"); checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box, #[a2] arg1: u8, #[a3] Vec);"); +checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);"); +checker!(rename_params, r#"impl Foo { + fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) { } + fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, + #[angery(true)] c: u32) { + } + fn hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32, + #[what = "how"] b: i32, #[angery(true)] c: u32) { + } +}"#); diff --git a/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs new file mode 100644 index 0000000000..670303906d --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs @@ -0,0 +1,21 @@ +// aux-build:param-attrs.rs + +// check-pass + +extern crate param_attrs; + +use param_attrs::rename_params; + +#[rename_params(send_help)] +impl Foo { + fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {} + fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32) {} + fn hello_self( + #[a1] #[a2] &self, + #[a1] #[a2] a: i32, + #[what = "how"] b: i32, + #[angery(true)] c: u32 + ) {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs index e900ccab4f..a6f693bd5b 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs @@ -1,8 +1,6 @@ // edition:2018 -#![feature(param_attrs)] - trait Trait2015 { fn foo(#[allow(C)] i32); } -//~^ ERROR expected one of `:` or `@`, found `)` +//~^ ERROR expected one of `:`, `@`, or `|`, found `)` fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index d0ed65f288..9860e9805b 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` - --> $DIR/param-attrs-2018.rs:5:41 +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/param-attrs-2018.rs:3:41 | LL | trait Trait2015 { fn foo(#[allow(C)] i32); } - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs index 5eeda66173..1217f89cb3 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -2,7 +2,6 @@ // compile-flags: --cfg something #![deny(unused_mut)] -#![feature(param_attrs)] extern "C" { fn ffi( diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs index b957c673a4..bf09171c9a 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs @@ -1,11 +1,9 @@ -#![feature(param_attrs)] - extern "C" { fn ffi( /// Foo //~^ ERROR documentation comments cannot be applied to function #[test] a: i32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Bar //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -21,7 +19,7 @@ type FnType = fn( /// Foo //~^ ERROR documentation comments cannot be applied to function #[test] a: u32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Bar //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -36,7 +34,7 @@ pub fn foo( /// Foo //~^ ERROR documentation comments cannot be applied to function #[test] a: u32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Bar //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -56,7 +54,22 @@ impl SelfStruct { /// Bar //~^ ERROR documentation comments cannot be applied to function #[test] a: i32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} + + fn issue_64682_associated_fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected an inert attribute, found an attribute macro /// Baz //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -77,7 +90,7 @@ impl RefStruct { /// Bar //~^ ERROR documentation comments cannot be applied to function #[test] a: i32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Baz //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -96,7 +109,22 @@ trait RefTrait { /// Bar //~^ ERROR documentation comments cannot be applied to function #[test] a: i32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} + + fn issue_64682_associated_fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected an inert attribute, found an attribute macro /// Baz //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -107,6 +135,7 @@ trait RefTrait { //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in ) {} } + impl RefTrait for RefStruct { fn foo( /// Foo @@ -115,7 +144,7 @@ impl RefTrait for RefStruct { /// Bar //~^ ERROR documentation comments cannot be applied to function #[test] a: i32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Baz //~^ ERROR documentation comments cannot be applied to function #[must_use] @@ -132,7 +161,7 @@ fn main() { /// Foo //~^ ERROR documentation comments cannot be applied to function #[test] a: u32, - //~^ ERROR the attribute `test` is currently unknown to the compiler and may have + //~^ ERROR expected an inert attribute, found an attribute macro /// Bar //~^ ERROR documentation comments cannot be applied to function #[must_use] diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr index a57572abb3..4d0349e876 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -1,339 +1,386 @@ -error: documentation comments cannot be applied to function parameters +error: expected an inert attribute, found an attribute macro --> $DIR/param-attrs-builtin-attrs.rs:5:9 | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:21:5 + | +LL | #[test] a: u32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:36:5 + | +LL | #[test] a: u32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:56:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:71:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:92:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:111:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:126:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:146:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/param-attrs-builtin-attrs.rs:163:9 + | +LL | #[test] a: u32, + | ^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:3:9 + | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:9:9 + --> $DIR/param-attrs-builtin-attrs.rs:7:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:11:9 + --> $DIR/param-attrs-builtin-attrs.rs:9:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:13:9 + --> $DIR/param-attrs-builtin-attrs.rs:11:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:15:9 + --> $DIR/param-attrs-builtin-attrs.rs:13:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:21:5 + --> $DIR/param-attrs-builtin-attrs.rs:19:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:25:5 + --> $DIR/param-attrs-builtin-attrs.rs:23:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:27:5 + --> $DIR/param-attrs-builtin-attrs.rs:25:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:29:5 + --> $DIR/param-attrs-builtin-attrs.rs:27:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:31:5 + --> $DIR/param-attrs-builtin-attrs.rs:29:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:36:5 + --> $DIR/param-attrs-builtin-attrs.rs:34:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:40:5 + --> $DIR/param-attrs-builtin-attrs.rs:38:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:42:5 + --> $DIR/param-attrs-builtin-attrs.rs:40:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:44:5 + --> $DIR/param-attrs-builtin-attrs.rs:42:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:46:5 + --> $DIR/param-attrs-builtin-attrs.rs:44:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:53:9 + --> $DIR/param-attrs-builtin-attrs.rs:51:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:56:9 + --> $DIR/param-attrs-builtin-attrs.rs:54:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:60:9 + --> $DIR/param-attrs-builtin-attrs.rs:58:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:62:9 + --> $DIR/param-attrs-builtin-attrs.rs:60:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:64:9 + --> $DIR/param-attrs-builtin-attrs.rs:62:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:66:9 + --> $DIR/param-attrs-builtin-attrs.rs:64:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:74:9 + --> $DIR/param-attrs-builtin-attrs.rs:69:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:77:9 - | -LL | /// Bar - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:81:9 + --> $DIR/param-attrs-builtin-attrs.rs:73:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:83:9 + --> $DIR/param-attrs-builtin-attrs.rs:75:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:85:9 + --> $DIR/param-attrs-builtin-attrs.rs:77:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:87:9 + --> $DIR/param-attrs-builtin-attrs.rs:79:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:93:9 + --> $DIR/param-attrs-builtin-attrs.rs:87:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:96:9 + --> $DIR/param-attrs-builtin-attrs.rs:90:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:100:9 + --> $DIR/param-attrs-builtin-attrs.rs:94:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:102:9 + --> $DIR/param-attrs-builtin-attrs.rs:96:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:104:9 + --> $DIR/param-attrs-builtin-attrs.rs:98:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:106:9 + --> $DIR/param-attrs-builtin-attrs.rs:100:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:112:9 + --> $DIR/param-attrs-builtin-attrs.rs:106:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:115:9 + --> $DIR/param-attrs-builtin-attrs.rs:109:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:119:9 + --> $DIR/param-attrs-builtin-attrs.rs:113:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:121:9 + --> $DIR/param-attrs-builtin-attrs.rs:115:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:123:9 + --> $DIR/param-attrs-builtin-attrs.rs:117:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:125:9 + --> $DIR/param-attrs-builtin-attrs.rs:119:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:132:9 + --> $DIR/param-attrs-builtin-attrs.rs:124:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:136:9 + --> $DIR/param-attrs-builtin-attrs.rs:128:9 | -LL | /// Bar +LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:138:9 + --> $DIR/param-attrs-builtin-attrs.rs:130:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:140:9 + --> $DIR/param-attrs-builtin-attrs.rs:132:9 | -LL | /// Baz +LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:142:9 + --> $DIR/param-attrs-builtin-attrs.rs:134:9 | -LL | #[no_mangle] b: i32 +LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:7:9 - | -LL | #[test] a: i32, - | ^^^^^^^ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:141:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:23:5 - | -LL | #[test] a: u32, - | ^^^^^^^ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:144:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:38:5 - | -LL | #[test] a: u32, - | ^^^^^^^ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:148:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:58:9 - | -LL | #[test] a: i32, - | ^^^^^^^ +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:150:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | #[must_use] + | ^^^^^^^^^^^ -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:79:9 - | -LL | #[test] a: i32, - | ^^^^^^^ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:152:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:98:9 +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:154:9 | -LL | #[test] a: i32, - | ^^^^^^^ +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:161:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:117:9 +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:165:9 | -LL | #[test] a: i32, - | ^^^^^^^ +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:167:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | #[must_use] + | ^^^^^^^^^^^ -error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/param-attrs-builtin-attrs.rs:134:9 +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:169:9 | -LL | #[test] a: u32, - | ^^^^^^^ +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:171:9 | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add `#![feature(custom_attribute)]` to the crate attributes to enable +LL | #[no_mangle] b: i32 + | ^^^^^^^^^^^^ -error: aborting due to 52 previous errors +error: aborting due to 64 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs index 069332ffa2..a4d9d32b51 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -1,7 +1,7 @@ // compile-flags: --cfg something // edition:2018 -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure)] #![deny(unused_variables)] extern "C" { @@ -51,6 +51,14 @@ impl RefStruct { //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} } trait RefTrait { fn bar( @@ -62,6 +70,14 @@ trait RefTrait { //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} } impl RefTrait for RefStruct { fn bar( @@ -73,6 +89,14 @@ impl RefTrait for RefStruct { //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} } fn main() { diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr index 3232e2a041..8d9571d09a 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -23,31 +23,43 @@ LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `a` - --> $DIR/param-attrs-cfg.rs:83:27 + --> $DIR/param-attrs-cfg.rs:107:27 | LL | #[cfg(something)] a: i32, | ^ help: consider prefixing with an underscore: `_a` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:89:27 + --> $DIR/param-attrs-cfg.rs:113:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:91:44 + --> $DIR/param-attrs-cfg.rs:115:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:59:27 + --> $DIR/param-attrs-cfg.rs:67:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:61:44 + --> $DIR/param-attrs-cfg.rs:69:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:75:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:77:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` @@ -71,16 +83,40 @@ LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:70:27 + --> $DIR/param-attrs-cfg.rs:56:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:58:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:86:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:88:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:94:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:72:44 + --> $DIR/param-attrs-cfg.rs:96:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` -error: aborting due to 13 previous errors +error: aborting due to 19 previous errors diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs deleted file mode 100644 index a7f4855915..0000000000 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs +++ /dev/null @@ -1,16 +0,0 @@ -// gate-test-param_attrs - -#![deny(unused_variables)] - -fn foo( - /// Foo - //~^ ERROR documentation comments cannot be applied to function parameters - //~| NOTE doc comments are not allowed here - //~| ERROR attributes on function parameters are unstable - //~| NOTE https://github.com/rust-lang/rust/issues/60406 - #[allow(unused_variables)] a: u8 - //~^ ERROR attributes on function parameters are unstable - //~| NOTE https://github.com/rust-lang/rust/issues/60406 -) {} - -fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr deleted file mode 100644 index 0bb9d05dca..0000000000 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-feature-gate.rs:6:5 - | -LL | /// Foo - | ^^^^^^^ doc comments are not allowed here - -error[E0658]: attributes on function parameters are unstable - --> $DIR/param-attrs-feature-gate.rs:6:5 - | -LL | /// Foo - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/60406 - = help: add `#![feature(param_attrs)]` to the crate attributes to enable - -error[E0658]: attributes on function parameters are unstable - --> $DIR/param-attrs-feature-gate.rs:11:5 - | -LL | #[allow(unused_variables)] a: u8 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/60406 - = help: add `#![feature(param_attrs)]` to the crate attributes to enable - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs index 1a7e948174..1183ac65b9 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs @@ -2,7 +2,6 @@ // check-pass -#![feature(param_attrs)] #![feature(c_variadic)] extern crate param_attrs; @@ -37,6 +36,9 @@ impl W { #[attr_inherent_4] fn inherent4<'a>(#[a1] self: Box, #[a2] arg1: u8) {} + + #[attr_inherent_issue_64682] + fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {} } trait A { @@ -51,6 +53,9 @@ trait A { #[attr_trait_4] fn trait4<'a>(#[a1] self: Box, #[a2] arg1: u8, #[a3] Vec); + + #[attr_trait_issue_64682] + fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8); } fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs new file mode 100644 index 0000000000..7f6ff33418 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -0,0 +1,65 @@ +// aux-build:ident-mac.rs + +#![feature(c_variadic)] + +extern crate ident_mac; +use ident_mac::id; + +struct W(u8); + +extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } +//~^ ERROR expected an inert attribute, found an attribute macro +//~| ERROR expected an inert attribute, found an attribute macro + +unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} +//~^ ERROR expected an inert attribute, found an attribute macro + +type Alias = extern "C" fn(#[id] u8, #[id] ...); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + +fn free(#[id] arg1: u8) { + //~^ ERROR expected an inert attribute, found an attribute macro + let lam = |#[id] W(x), #[id] y| (); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro +} + +impl W { + fn inherent1(#[id] self, #[id] arg1: u8) {} + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn inherent2(#[id] &self, #[id] arg1: u8) {} + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro +} + +trait A { + fn trait1(#[id] self, #[id] arg1: u8); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn trait2(#[id] &self, #[id] arg1: u8); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro + fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + //~^ ERROR expected an inert attribute, found an attribute macro + //~| ERROR expected an inert attribute, found an attribute macro +} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr new file mode 100644 index 0000000000..b9a9448a1f --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -0,0 +1,176 @@ +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:10:21 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:10:38 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:14:38 + | +LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:17:28 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:17:38 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:21:9 + | +LL | fn free(#[id] arg1: u8) { + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:23:16 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:23:28 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:29:18 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:29:30 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:32:18 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:32:31 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:35:22 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:35:42 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:38:22 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:38:45 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:41:38 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:41:54 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:47:15 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:47:27 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:50:15 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:50:28 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:53:19 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:53:39 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:56:19 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:56:42 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:56:58 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:60:38 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + | ^^^^^ + +error: expected an inert attribute, found an attribute macro + --> $DIR/proc-macro-cannot-be-used.rs:60:54 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + | ^^^^^ + +error: aborting due to 29 previous errors + diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs index 03492631cb..f5197fd01b 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs @@ -1,12 +1,9 @@ +#![allow(incomplete_features)] #![feature(generic_associated_types)] -//FIXME(#44265): The lifetime shadowing and type parameter shadowing -// should cause an error. Now it compiles (erroneously) and this will be addressed -// by a future PR. Then remove the following: -// build-pass (FIXME(62277): could be check-pass?) - trait Shadow<'a> { - type Bar<'a>; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a>; } trait NoShadow<'a> { @@ -14,11 +11,12 @@ trait NoShadow<'a> { } impl<'a> NoShadow<'a> for &'a u32 { - type Bar<'a> = i32; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a> = i32; } trait ShadowT { - type Bar; // Error: shadowed type parameter + type Bar; //~ ERROR the name `T` is already used } trait NoShadowT { @@ -26,7 +24,7 @@ trait NoShadowT { } impl NoShadowT for Option { - type Bar = i32; // Error: shadowed type parameter + type Bar = i32; //~ ERROR the name `T` is already used } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr index 9526df258c..a06c635084 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr @@ -1,8 +1,19 @@ -warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash - --> $DIR/shadowing.rs:1:12 +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:19:14 | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait ShadowT { + | - first use of `T` +LL | type Bar; + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:27:14 | - = note: `#[warn(incomplete_features)]` on by default +LL | impl NoShadowT for Option { + | - first use of `T` +LL | type Bar = i32; + | ^ already used + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index a81181228d..19f758fd8d 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foobar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:22:11 | LL | x.foobar(); - | ^^^^^^ + | ^^^^^^ method not found in `u32` | = help: items from traits can only be used if the trait is in scope = note: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -12,7 +12,7 @@ error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:28:7 | LL | x.bar(); - | ^^^ + | ^^^ method not found in `u32` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -24,7 +24,7 @@ error[E0599]: no method named `baz` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:29:7 | LL | x.baz(); - | ^^^ + | ^^^ method not found in `u32` error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:30:18 diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.rs b/src/test/ui/rust-2018/uniform-paths/deadlock.rs index 3228d79908..83ed70a045 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.rs +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.rs @@ -1,7 +1,7 @@ // edition:2018 // compile-flags:--extern foo --extern bar -use foo::bar; //~ ERROR unresolved import +use foo::bar; //~ ERROR can't find crate for `foo` use bar::foo; fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr index b4ac15c588..9336e90afb 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr @@ -1,9 +1,9 @@ -error[E0432]: unresolved import +error[E0463]: can't find crate for `foo` --> $DIR/deadlock.rs:4:5 | LL | use foo::bar; - | ^^^^^^^^ + | ^^^ can't find crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0432`. +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rust-unstable-column-gated.rs b/src/test/ui/rust-unstable-column-gated.rs deleted file mode 100644 index 053806ead2..0000000000 --- a/src/test/ui/rust-unstable-column-gated.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("{}", __rust_unstable_column!()); - //~^ ERROR use of unstable library feature '__rust_unstable_column' -} diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr deleted file mode 100644 index 7db1b01fb0..0000000000 --- a/src/test/ui/rust-unstable-column-gated.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro - --> $DIR/rust-unstable-column-gated.rs:2:20 - | -LL | println!("{}", __rust_unstable_column!()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(__rust_unstable_column)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs new file mode 100644 index 0000000000..92e85884f6 --- /dev/null +++ b/src/test/ui/save-analysis/issue-63663.rs @@ -0,0 +1,28 @@ +// check-pass +// compile-flags: -Zsave-analysis + +pub trait Trait { + type Assoc; +} + +pub struct A; + +trait Generic {} +impl Generic for () {} + +// Don't ICE when resolving type paths in return type `impl Trait` +fn assoc_in_opaque_type_bounds() -> impl Generic {} + +// Check that this doesn't ICE when processing associated const in formal +// argument and return type of functions defined inside function/method scope. +pub fn func() { + fn _inner1(_: U::Assoc) {} + fn _inner2() -> U::Assoc { unimplemented!() } + + impl A { + fn _inner1(self, _: U::Assoc) {} + fn _inner2(self) -> U::Assoc { unimplemented!() } + } +} + +fn main() {} diff --git a/src/test/ui/save-analysis/issue-64659.rs b/src/test/ui/save-analysis/issue-64659.rs new file mode 100644 index 0000000000..a3d88a2037 --- /dev/null +++ b/src/test/ui/save-analysis/issue-64659.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } + +fn main() { + struct Data { + x: T::Assoc, + } +} diff --git a/src/test/ui/save-analysis/issue-65411.rs b/src/test/ui/save-analysis/issue-65411.rs new file mode 100644 index 0000000000..9e58b8da5d --- /dev/null +++ b/src/test/ui/save-analysis/issue-65411.rs @@ -0,0 +1,15 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } +trait GenericTrait {} +struct Wrapper { b: B } + +fn func() { + // Processing associated path in impl block definition inside a function + // body does not ICE + impl GenericTrait for Wrapper {} +} + + +fn main() {} diff --git a/src/test/ui/save-analysis/issue-65590.rs b/src/test/ui/save-analysis/issue-65590.rs new file mode 100644 index 0000000000..27874f8655 --- /dev/null +++ b/src/test/ui/save-analysis/issue-65590.rs @@ -0,0 +1,21 @@ +// check-pass +// compile-flags: -Zsave-analysis +// edition:2018 + +// Async desugaring for return types in (associated) functions introduces a +// separate definition internally, which we need to take into account +// (or else we ICE). +trait Trait { type Assoc; } +struct Struct; + +async fn foobar() -> T::Assoc { + unimplemented!() +} + +impl Struct { + async fn foo(&self) -> T::Assoc { + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr index e45bc2657f..e6eba377a9 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s `self` parameter cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: method `foo`'s receiver cannot be dispatched on error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s `self` parameter cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = note: method `foo`'s receiver cannot be dispatched on = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` error: aborting due to 2 previous errors diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs new file mode 100644 index 0000000000..f3474bc1f9 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs @@ -0,0 +1,35 @@ +// check-pass +// edition:2018 + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + async fn pin_pin_pin_ref(self: Pin>>) -> Pin>> { self } + + async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias = Pin; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +// FIXME(Centril): extend with the rest of the non-`async fn` test +// when we allow `async fn`s inside traits and trait implementations. + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr new file mode 100644 index 0000000000..a585b4fdbe --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | - ^^^^^^^^ returning this value requires that `'_` must outlive `'static` + | | + | lifetime `'_` defined here +help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs new file mode 100644 index 0000000000..0afe631f1e --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -0,0 +1,14 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR cannot infer an appropriate lifetime +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr new file mode 100644 index 0000000000..2fb152475a --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -0,0 +1,20 @@ +error: cannot infer an appropriate lifetime + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^ ---------- this return type evaluates to the `'static` lifetime... + | | + | ...but this borrow... + | +note: ...can't outlive the lifetime '_ as defined on the method body at 8:26 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^ +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 8:26 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr new file mode 100644 index 0000000000..e53d91c360 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr @@ -0,0 +1,46 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:45 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:50 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - ^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + | | + | lifetime `'_` defined here + | lifetime `'_` defined here + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:73 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + | | + | lifetime `'_` defined here + | lifetime `'_` defined here + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | ^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:62 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- - ^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a` + | | | + | | lifetime `'_` defined here + | lifetime `'a` defined here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs new file mode 100644 index 0000000000..f42337d534 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs @@ -0,0 +1,20 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ ERROR lifetime mismatch + + async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ ERROR lifetime mismatch +} + +type Alias = Pin; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623 +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr new file mode 100644 index 0000000000..57ad026bdc --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -0,0 +1,29 @@ +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:45 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | ---- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:55 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | ----- ^^^ + | | | + | | ...but data from `arg` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/self/elision/README.md b/src/test/ui/self/elision/README.md index 7ace2e0c89..3bd7a6c00b 100644 --- a/src/test/ui/self/elision/README.md +++ b/src/test/ui/self/elision/README.md @@ -42,3 +42,34 @@ In each case, we test the following patterns: - `self: Box>` In the non-reference cases, `Pin` causes errors so we substitute `Rc`. + +### `async fn` + +For each of the tests above we also check that `async fn` behaves as an `fn` would. +These tests are in files named `*-async.rs`. + +Legends: +- ✓ ⟹ Yes / Pass +- X ⟹ No +- α ⟹ lifetime mismatch +- β ⟹ cannot infer an appropriate lifetime +- γ ⟹ missing lifetime specifier + +| `async` file | Pass? | Conforms to `fn`? | How does it diverge?
`fn` ⟶ `async fn` | +| --- | --- | --- | --- | +| `self-async.rs` | ✓ | ✓ | N/A | +| `struct-async.rs`| ✓ | ✓ | N/A | +| `alias-async.rs`| ✓ | ✓ | N/A | +| `assoc-async.rs`| ✓ | ✓ | N/A | +| `ref-self-async.rs` | X | ✓ | N/A | +| `ref-mut-self-async.rs` | X | ✓ | N/A | +| `ref-struct-async.rs` | X | ✓ | N/A | +| `ref-mut-struct-async.rs` | X | ✓ | N/A | +| `ref-alias-async.rs` | ✓ | ✓ | N/A | +| `ref-assoc-async.rs` | ✓ | ✓ | N/A | +| `ref-mut-alias-async.rs` | ✓ | ✓ | N/A | +| `lt-self-async.rs` | ✓ | ✓ | N/A +| `lt-struct-async.rs` | ✓ | ✓ | N/A +| `lt-alias-async.rs` | ✓ | ✓ | N/A +| `lt-assoc-async.rs` | ✓ | ✓ | N/A +| `lt-ref-self-async.rs` | X | ✓ | N/A | diff --git a/src/test/ui/self/elision/alias-async.rs b/src/test/ui/self/elision/alias-async.rs new file mode 100644 index 0000000000..9743c13909 --- /dev/null +++ b/src/test/ui/self/elision/alias-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + async fn box_Alias(self: Box, f: &u32) -> &u32 { + f + } + + async fn rc_Alias(self: Rc, f: &u32) -> &u32 { + f + } + + async fn box_box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/assoc-async.rs b/src/test/ui/self/elision/assoc-async.rs new file mode 100644 index 0000000000..fa5968de5a --- /dev/null +++ b/src/test/ui/self/elision/assoc-async.rs @@ -0,0 +1,41 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn assoc(self: ::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_AssocType(self: Box<::AssocType>, f: &u32) -> &u32 { + f + } + + async fn rc_AssocType(self: Rc<::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-alias-async.rs b/src/test/ui/self/elision/lt-alias-async.rs new file mode 100644 index 0000000000..cc5badaaa6 --- /dev/null +++ b/src/test/ui/self/elision/lt-alias-async.rs @@ -0,0 +1,39 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Alias(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Alias(self: Rc>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Alias(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-assoc-async.rs b/src/test/ui/self/elision/lt-assoc-async.rs new file mode 100644 index 0000000000..f060800e4d --- /dev/null +++ b/src/test/ui/self/elision/lt-assoc-async.rs @@ -0,0 +1,51 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_AssocType(self: as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn take_Box_AssocType(self: Box< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_AssocType( + self: Box as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } + + async fn take_Rc_AssocType(self: Rc< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_AssocType( + self: Box as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr new file mode 100644 index 0000000000..998178dde1 --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -0,0 +1,123 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:13:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:13:47 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | _______________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:19:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:19:53 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | _____________________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:23:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:23:62 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:27:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:27:62 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:31:66 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:31:71 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:35:62 + | +LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:35:67 + | +LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + | _________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/lt-ref-self-async.rs b/src/test/ui/self/elision/lt-ref-self-async.rs new file mode 100644 index 0000000000..e3ca0c2e2d --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.rs @@ -0,0 +1,40 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr new file mode 100644 index 0000000000..2bc64bdf1f --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -0,0 +1,56 @@ +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:13:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:19:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:23:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:27:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:31:66 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:35:62 + | +LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/lt-self-async.rs b/src/test/ui/self/elision/lt-self-async.rs new file mode 100644 index 0000000000..42647b82ef --- /dev/null +++ b/src/test/ui/self/elision/lt-self-async.rs @@ -0,0 +1,50 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-struct-async.rs b/src/test/ui/self/elision/lt-struct-async.rs new file mode 100644 index 0000000000..dc5a53b89d --- /dev/null +++ b/src/test/ui/self/elision/lt-struct-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Struct(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Struct(self: Rc>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Struct(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/multiple-ref-self-async.rs b/src/test/ui/self/elision/multiple-ref-self-async.rs new file mode 100644 index 0000000000..be073c6edb --- /dev/null +++ b/src/test/ui/self/elision/multiple-ref-self-async.rs @@ -0,0 +1,44 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + async fn box_wrap_ref_Self_ref_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn pin_wrap_ref_Self_ref_Self(self: Pin>, f: &u32) -> &u32 { + f + } + + async fn box_box_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-alias-async.rs b/src/test/ui/self/elision/ref-alias-async.rs new file mode 100644 index 0000000000..4b02c2fd00 --- /dev/null +++ b/src/test/ui/self/elision/ref-alias-async.rs @@ -0,0 +1,40 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + async fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-assoc-async.rs b/src/test/ui/self/elision/ref-assoc-async.rs new file mode 100644 index 0000000000..258e27b7cb --- /dev/null +++ b/src/test/ui/self/elision/ref-assoc-async.rs @@ -0,0 +1,41 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn ref_AssocType(self: &::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_ref_AssocType(self: Box<&::AssocType>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_AssocType(self: Pin<&::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-alias-async.rs b/src/test/ui/self/elision/ref-mut-alias-async.rs new file mode 100644 index 0000000000..5f9ccf3bc7 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-alias-async.rs @@ -0,0 +1,37 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr new file mode 100644 index 0000000000..97bc80509d --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -0,0 +1,123 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:13:46 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:13:51 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | _______________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:19:52 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:19:57 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | _____________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:23:61 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:23:66 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | _____________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:27:61 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:27:66 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | _____________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:31:70 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:31:75 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | _____________________________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:35:70 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:35:75 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | _____________________________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-mut-self-async.rs b/src/test/ui/self/elision/ref-mut-self-async.rs new file mode 100644 index 0000000000..2ca14800a7 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.rs @@ -0,0 +1,40 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + async fn ref_self(&mut self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch + f + } + + // Test using `&mut Self` explicitly: + + async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr new file mode 100644 index 0000000000..39a1b30ca5 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -0,0 +1,56 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:13:46 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:19:52 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:23:61 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:27:61 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:31:70 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:35:70 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr new file mode 100644 index 0000000000..2905a022e5 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -0,0 +1,103 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:13:56 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:13:61 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | _______________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:17:65 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:17:70 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | _______________________________________-______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:21:65 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:21:70 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | _______________________________________-______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:25:74 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:25:79 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | _______________________________________________-_______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:29:74 + | +LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:29:79 + | +LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + | _______________________________________________-_______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-mut-struct-async.rs b/src/test/ui/self/elision/ref-mut-struct-async.rs new file mode 100644 index 0000000000..a671116de2 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.rs @@ -0,0 +1,34 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr new file mode 100644 index 0000000000..fe4a636ada --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -0,0 +1,47 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:13:56 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:17:65 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:21:65 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:25:74 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:29:74 + | +LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr new file mode 100644 index 0000000000..0eee56654f --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.nll.stderr @@ -0,0 +1,143 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:22:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:22:47 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | _______________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:28:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:28:53 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | _____________________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:32:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:32:62 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:36:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:36:62 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:40:66 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:40:71 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:44:66 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:44:71 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:48:69 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:48:73 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ____________________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs new file mode 100644 index 0000000000..06f3b127b2 --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -0,0 +1,53 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch + f + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr new file mode 100644 index 0000000000..2f9e2a01e3 --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -0,0 +1,65 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:22:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:28:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:32:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:36:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:40:66 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:44:66 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:48:69 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ----- ^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr new file mode 100644 index 0000000000..8508e42264 --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -0,0 +1,103 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:13:52 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:13:57 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | _______________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:17:61 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:17:66 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | _______________________________________-__________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:21:61 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:21:66 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | _______________________________________-__________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:25:70 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:25:75 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | _______________________________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:29:66 + | +LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:29:71 + | +LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + | ___________________________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-struct-async.rs b/src/test/ui/self/elision/ref-struct-async.rs new file mode 100644 index 0000000000..94eaeedc73 --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.rs @@ -0,0 +1,34 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr new file mode 100644 index 0000000000..222e27ebf0 --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -0,0 +1,47 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:13:52 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:17:61 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:21:61 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:25:70 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:29:66 + | +LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/self-async.rs b/src/test/ui/self/elision/self-async.rs new file mode 100644 index 0000000000..e1379bfaf2 --- /dev/null +++ b/src/test/ui/self/elision/self-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/struct-async.rs b/src/test/ui/self/elision/struct-async.rs new file mode 100644 index 0000000000..4a38a2164c --- /dev/null +++ b/src/test/ui/self/elision/struct-async.rs @@ -0,0 +1,33 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + async fn box_Struct(self: Box, f: &u32) -> &u32 { + f + } + + async fn rc_Struct(self: Rc, f: &u32) -> &u32 { + f + } + + async fn box_box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Struct(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-method.rs new file mode 100644 index 0000000000..0f7deeacad --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.rs @@ -0,0 +1,9 @@ +struct A; + +impl A { + fn foo(self: Box) {} +} + +fn main() { + A.foo(); //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr new file mode 100644 index 0000000000..dec5809f15 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for type `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 + | +LL | struct A; + | --------- method `foo` not found for this +... +LL | fn foo(self: Box) {} + | --- the method is available for `std::boxed::Box` here +... +LL | A.foo(); + | ^^^ method not found in `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs new file mode 100644 index 0000000000..53d9927711 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs @@ -0,0 +1,10 @@ +trait B { fn foo(self: Box); } +struct A; + +impl B for A { + fn foo(self: Box) {} +} + +fn main() { + A.foo() //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr new file mode 100644 index 0000000000..e93c4da9df --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `foo` found for type `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 + | +LL | trait B { fn foo(self: Box); } + | --- the method is available for `std::boxed::Box` here +LL | struct A; + | --------- method `foo` not found for this +... +LL | A.foo() + | ^^^ method not found in `A` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `foo`, perhaps you need to implement it: + candidate #1: `B` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/self/self_lifetime-async.rs b/src/test/ui/self/self_lifetime-async.rs new file mode 100644 index 0000000000..c3c6e56582 --- /dev/null +++ b/src/test/ui/self/self_lifetime-async.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index 01b3309fca..dfb7d6583d 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -14,11 +14,12 @@ pub fn main() { ref Self => (), //~^ ERROR expected identifier, found keyword `Self` mut Self => (), - //~^ ERROR expected identifier, found keyword `Self` + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR cannot find unit struct/variant or constant `Self` ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` Self!() => (), - //~^ ERROR cannot find macro `Self!` in this scope + //~^ ERROR cannot find macro `Self` in this scope Foo { Self } => (), //~^ ERROR expected identifier, found keyword `Self` } diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index b63de98b8e..11b3b012c5 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -10,38 +10,40 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:16:13 +error: `mut` must be followed by a named binding + --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^ expected identifier, found keyword + | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:18:17 + --> $DIR/self_type_keyword.rs:19:17 | LL | ref mut Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:22:15 + --> $DIR/self_type_keyword.rs:23:15 | LL | Foo { Self } => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:28:26 + --> $DIR/self_type_keyword.rs:29:26 | LL | extern crate core as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:33:32 + --> $DIR/self_type_keyword.rs:34:32 | LL | use std::option::Option as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:38:11 + --> $DIR/self_type_keyword.rs:39:11 | LL | trait Self {} | ^^^^ expected identifier, found keyword @@ -52,12 +54,22 @@ error: lifetimes cannot use keyword names LL | struct Bar<'Self>; | ^^^^^ -error: cannot find macro `Self!` in this scope - --> $DIR/self_type_keyword.rs:20:9 +error: cannot find macro `Self` in this scope + --> $DIR/self_type_keyword.rs:21:9 | LL | Self!() => (), | ^^^^ +error[E0531]: cannot find unit struct/variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use foo::Self; + | + error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | @@ -66,6 +78,6 @@ LL | struct Bar<'Self>; | = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr index e05da17983..190159ec7b 100644 --- a/src/test/ui/shadowed/shadowed-trait-methods.stderr +++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for type `()` in the current scope --> $DIR/shadowed-trait-methods.rs:13:8 | LL | ().f() - | ^ + | ^ method not found in `()` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs index ba9f3abcf7..e74620f890 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.rs +++ b/src/test/ui/shadowed/shadowed-type-parameter.rs @@ -6,7 +6,7 @@ struct Foo(T); impl Foo { fn shadow_in_method(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_item(&self) { struct Bar(T,U); // not a shadow, separate item @@ -18,10 +18,10 @@ trait Bar { fn dummy(&self) -> T; fn shadow_in_required(&self); - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn shadow_in_provided(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_required(&self); fn not_shadow_in_provided(&self) {} diff --git a/src/test/ui/shadowed/shadowed-type-parameter.stderr b/src/test/ui/shadowed/shadowed-type-parameter.stderr index 6b4d1fae3d..0ea82f983f 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.stderr +++ b/src/test/ui/shadowed/shadowed-type-parameter.stderr @@ -1,29 +1,29 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:8:25 + | +LL | impl Foo { + | - first use of `T` +LL | fn shadow_in_method(&self) {} + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:20:27 | LL | trait Bar { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_required(&self); - | ^ shadows another type parameter + | ^ already used -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:23:27 | LL | trait Bar { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_provided(&self) {} - | ^ shadows another type parameter - -error[E0194]: type parameter `T` shadows another type parameter of the same name - --> $DIR/shadowed-type-parameter.rs:8:25 - | -LL | impl Foo { - | - first `T` declared here -LL | fn shadow_in_method(&self) {} - | ^ shadows another type parameter + | ^ already used error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr index 71197efcab..1c51653db6 100644 --- a/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr +++ b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr @@ -1,8 +1,8 @@ -error[E0416]: identifier `a` is bound more than once in the same pattern +error[E0415]: identifier `a` is bound more than once in this parameter list --> $DIR/shadowing-in-the-same-pattern.rs:3:10 | LL | fn f((a, a): (isize, isize)) {} - | ^ used in a pattern more than once + | ^ used as parameter more than once error[E0416]: identifier `a` is bound more than once in the same pattern --> $DIR/shadowing-in-the-same-pattern.rs:6:13 @@ -12,4 +12,5 @@ LL | let (a, a) = (1, 1); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0416`. +Some errors have detailed explanations: E0415, E0416. +For more information about an error, try `rustc --explain E0415`. diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs index 5c9893f64a..7a0cfb679e 100644 --- a/src/test/ui/span/issue-27522.rs +++ b/src/test/ui/span/issue-27522.rs @@ -3,7 +3,7 @@ struct SomeType {} trait Foo { - fn handler(self: &SomeType); //~ ERROR invalid method receiver type + fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type } fn main() {} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 88dfee1cad..8a254a9685 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: &SomeType +error[E0307]: invalid `self` parameter type: &SomeType --> $DIR/issue-27522.rs:6:22 | LL | fn handler(self: &SomeType); | ^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 24dfdf8ebc..1d3e33e4b0 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied --> $DIR/issue-29595.rs:6:17 | +LL | const C: Self; + | -------------- required by `Tr::C` +... LL | let a: u8 = Tr::C; | ^^^^^ the trait `Tr` is not implemented for `u8` - | -note: required by `Tr::C` - --> $DIR/issue-29595.rs:2:5 - | -LL | const C: Self; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 5dd9895c6e..cc0eccd37a 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -1,14 +1,14 @@ -error: expected one of `:` or `@`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-34264.rs:1:14 | LL | fn foo(Option, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 | LL | fn foo(Option, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -20,11 +20,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo(Option, _: String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/issue-34264.rs:3:9 | LL | fn bar(x, y: usize) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 04c2870d83..30c9adb1dc 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -1,10 +1,10 @@ error[E0282]: type annotations needed for `std::option::Option<_>` - --> $DIR/issue-42234-unknown-receiver-type.rs:7:5 + --> $DIR/issue-42234-unknown-receiver-type.rs:7:7 | LL | let x: Option<_> = None; | - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified LL | x.unwrap().method_that_could_exist_on_some_type(); - | ^^^^^^^^^^ cannot infer type for `T` + | ^^^^^^ cannot infer type for `T` | = note: type must be known at this point diff --git a/src/test/ui/span/type-annotations-needed-expr.rs b/src/test/ui/span/type-annotations-needed-expr.rs new file mode 100644 index 0000000000..f64dab4d7b --- /dev/null +++ b/src/test/ui/span/type-annotations-needed-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = (vec![1,2,3]).into_iter().sum() as f64; //~ ERROR E0282 +} diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr new file mode 100644 index 0000000000..e32a542bb7 --- /dev/null +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/type-annotations-needed-expr.rs:2:39 + | +LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; + | ^^^ cannot infer type for `S` + | + = note: type must be known at this point + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs index 7ea79a9a7b..37005f839d 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr index 91690f64d9..13636b28b1 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl Redundant for T { LL | | fn redundant(&self) {} diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index c14fc04f63..bbfe4c3d59 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -5,7 +5,7 @@ LL | struct MyStruct; | ---------------- method `foo_one` not found for this ... LL | println!("{}", MyStruct.foo_one()); - | ^^^^^^^ + | ^^^^^^^ method not found in `MyStruct` | = note: the method `foo_one` exists but the following trait bounds were not satisfied: `MyStruct : Foo` diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr index dcb34f3ad4..36f96b0119 100644 --- a/src/test/ui/specialization/issue-52050.stderr +++ b/src/test/ui/specialization/issue-52050.stderr @@ -11,7 +11,7 @@ LL | LL | impl IntoPyDictPointer for () | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` | - = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `()` in future versions + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions error: aborting due to previous error diff --git a/src/test/ui/specialization/issue-63716-parse-async.rs b/src/test/ui/specialization/issue-63716-parse-async.rs new file mode 100644 index 0000000000..c3764ffaab --- /dev/null +++ b/src/test/ui/specialization/issue-63716-parse-async.rs @@ -0,0 +1,14 @@ +// Ensure that `default async fn` will parse. +// See issue #63716 for details. + +// check-pass +// edition:2018 + +#![feature(specialization)] + +fn main() {} + +#[cfg(FALSE)] +impl Foo for Bar { + default async fn baz() {} +} diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr index ab0bdc44cf..43cebd7f9c 100644 --- a/src/test/ui/specialization/specialization-default-projection.stderr +++ b/src/test/ui/specialization/specialization-default-projection.stderr @@ -9,6 +9,8 @@ LL | () | = note: expected type `::Assoc` found type `()` + = note: consider constraining the associated type `::Assoc` to `()` or calling a method that returns `::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/specialization-default-projection.rs:28:5 @@ -23,6 +25,8 @@ LL | generic::<()>() | = note: expected type `()` found type `<() as Foo>::Assoc` + = note: consider constraining the associated type `<() as Foo>::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr index 1192b0e5cf..932087421f 100644 --- a/src/test/ui/specialization/specialization-default-types.stderr +++ b/src/test/ui/specialization/specialization-default-types.stderr @@ -8,6 +8,8 @@ LL | Box::new(self) | = note: expected type `::Output` found type `std::boxed::Box` + = note: consider constraining the associated type `::Output` to `std::boxed::Box` or calling a method that returns `::Output` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/specialization-default-types.rs:25:5 @@ -19,6 +21,8 @@ LL | Example::generate(t) | = note: expected type `std::boxed::Box` found type `::Output` + = note: consider constraining the associated type `::Output` to `std::boxed::Box` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs index 29afbbd9bf..57346b26d2 100644 --- a/src/test/ui/specialization/specialization-no-default.rs +++ b/src/test/ui/specialization/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr index c39986de38..992e9abbd4 100644 --- a/src/test/ui/specialization/specialization-no-default.stderr +++ b/src/test/ui/specialization/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl Redundant for T { LL | | fn redundant(&self) {} diff --git a/src/test/ui/std-backtrace.rs b/src/test/ui/std-backtrace.rs new file mode 100644 index 0000000000..d84c493d53 --- /dev/null +++ b/src/test/ui/std-backtrace.rs @@ -0,0 +1,75 @@ +// run-pass +// ignore-android FIXME #17520 +// ignore-cloudabi spawning processes is not supported +// ignore-emscripten spawning processes is not supported +// ignore-openbsd no support for libbacktrace without filename +// ignore-sgx no processes +// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test +// compile-flags:-g + +#![feature(backtrace)] + +use std::env; +use std::process::Command; +use std::str; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 && args[1] == "force" { + println!("{}", std::backtrace::Backtrace::force_capture()); + } else if args.len() >= 2 { + println!("{}", std::backtrace::Backtrace::capture()); + } else { + runtest(&args[0]); + println!("test ok"); + } +} + +fn runtest(me: &str) { + env::remove_var("RUST_BACKTRACE"); + env::remove_var("RUST_LIB_BACKTRACE"); + + let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "1").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + assert!(String::from_utf8_lossy(&p.stdout).contains("backtrace::main")); + + let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "0").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me).arg("a").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me) + .arg("a") + .env("RUST_LIB_BACKTRACE", "1") + .env("RUST_BACKTRACE", "1") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + + let p = Command::new(me) + .arg("a") + .env("RUST_LIB_BACKTRACE", "0") + .env("RUST_BACKTRACE", "1") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me) + .arg("force") + .env("RUST_LIB_BACKTRACE", "0") + .env("RUST_BACKTRACE", "0") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + + let p = Command::new(me).arg("force").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); +} diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index e388534f13..9f21aaaeba 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -10,20 +10,20 @@ LL | let _: u8 = s[4]; = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-idx.rs:4:15 + --> $DIR/str-idx.rs:4:19 | LL | let _ = s.get(4); - | ^^^ string indices are ranges of `usize` + | ^ string indices are ranges of `usize` | = help: the trait `std::slice::SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-idx.rs:5:15 + --> $DIR/str-idx.rs:5:29 | LL | let _ = s.get_unchecked(4); - | ^^^^^^^^^^^^^ string indices are ranges of `usize` + | ^ string indices are ranges of `usize` | = help: the trait `std::slice::SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index beb2272452..3c957970e5 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -1,16 +1,14 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-mut-idx.rs:4:15 | +LL | fn bot() -> T { loop {} } + | --- - required by this bound in `bot` +... LL | s[1..2] = bot(); | ^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit -note: required by `bot` - --> $DIR/str-mut-idx.rs:1:1 - | -LL | fn bot() -> T { loop {} } - | ^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-mut-idx.rs:4:5 @@ -32,20 +30,20 @@ LL | s[1usize] = bot(); = note: required because of the requirements on the impl of `std::ops::Index` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-mut-idx.rs:9:7 + --> $DIR/str-mut-idx.rs:9:15 | LL | s.get_mut(1); - | ^^^^^^^ string indices are ranges of `usize` + | ^ string indices are ranges of `usize` | = help: the trait `std::slice::SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-mut-idx.rs:11:7 + --> $DIR/str-mut-idx.rs:11:25 | LL | s.get_unchecked_mut(1); - | ^^^^^^^^^^^^^^^^^ string indices are ranges of `usize` + | ^ string indices are ranges of `usize` | = help: the trait `std::slice::SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr index 70eb2610ea..1c2c205e01 100644 --- a/src/test/ui/structs/struct-path-alias-bounds.stderr +++ b/src/test/ui/structs/struct-path-alias-bounds.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied --> $DIR/struct-path-alias-bounds.rs:9:13 | +LL | struct S { a: T } + | ------------------ required by `S` +... LL | let s = A { a: NoClone }; | ^ the trait `std::clone::Clone` is not implemented for `NoClone` - | -note: required by `S` - --> $DIR/struct-path-alias-bounds.rs:3:1 - | -LL | struct S { a: T } - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/structs/struct-path-self-type-mismatch.stderr b/src/test/ui/structs/struct-path-self-type-mismatch.stderr index 72c6d7ae22..b905cd1a29 100644 --- a/src/test/ui/structs/struct-path-self-type-mismatch.stderr +++ b/src/test/ui/structs/struct-path-self-type-mismatch.stderr @@ -12,6 +12,8 @@ LL | inner: u | = note: expected type `T` found type `U` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:13:9 @@ -27,6 +29,8 @@ LL | | } | = note: expected type `Foo` found type `Foo` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to 3 previous errors diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs index 77880bfca4..c938ce8dad 100644 --- a/src/test/ui/structs/struct-path-self.rs +++ b/src/test/ui/structs/struct-path-self.rs @@ -3,13 +3,13 @@ struct S; trait Tr { fn f() { let s = Self {}; - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter let z = Self:: {}; - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter //~| ERROR type arguments are not allowed for this type match s { Self { .. } => {} - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter } } } diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr index 9eaa1f95bd..8c88cacc69 100644 --- a/src/test/ui/structs/struct-path-self.stderr +++ b/src/test/ui/structs/struct-path-self.stderr @@ -1,4 +1,4 @@ -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:5:17 | LL | let s = Self {}; @@ -10,13 +10,13 @@ error[E0109]: type arguments are not allowed for this type LL | let z = Self:: {}; | ^^ type argument not allowed -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:7:17 | LL | let z = Self:: {}; | ^^^^^^^^^^ not a struct -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:11:13 | LL | Self { .. } => {} diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr index b3b879ef9a..cb55203c88 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/substs-ppaux.normal.stderr @@ -61,17 +61,15 @@ LL | let x: () = foo::<'static>; error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 | +LL | fn bar<'a, T>() where T: 'a {} + | --- -- required by this bound in `Foo::bar` +... LL | >::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit = note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str` -note: required by `Foo::bar` - --> $DIR/substs-ppaux.rs:7:5 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index 363018db23..cafcba97b9 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -61,17 +61,15 @@ LL | let x: () = foo::<'static>; error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 | +LL | fn bar<'a, T>() where T: 'a {} + | --- -- required by this bound in `Foo::bar` +... LL | >::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit = note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str` -note: required by `Foo::bar` - --> $DIR/substs-ppaux.rs:7:5 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 0000000000..a2d2ba145b --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,10 @@ +// edition:2018 +use std::future::Future; + +async fn foo() {} + +fn bar(f: impl Future) {} + +fn main() { + bar(foo); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 0000000000..1cc704b443 --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `fn() -> impl std::future::Future {foo}: std::future::Future` is not satisfied + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:9:9 + | +LL | fn bar(f: impl Future) {} + | --- ----------------- required by this bound in `bar` +... +LL | bar(foo); + | ^^^ + | | + | the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}` + | help: use parentheses to call the function: `foo()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs index 74f63f2b0e..7c8231bbb2 100644 --- a/src/test/ui/suggestions/attribute-typos.rs +++ b/src/test/ui/suggestions/attribute-typos.rs @@ -1,11 +1,11 @@ -#[deprcated] //~ ERROR cannot find attribute macro `deprcated` in this scope +#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope fn foo() {} -#[tests] //~ ERROR cannot find attribute macro `tests` in this scope +#[tests] //~ ERROR cannot find attribute `tests` in this scope fn bar() {} #[rustc_err] -//~^ ERROR cannot find attribute macro `rustc_err` in this scope +//~^ ERROR cannot find attribute `rustc_err` in this scope //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler fn main() {} diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr index 6b2f591b9e..e40329382f 100644 --- a/src/test/ui/suggestions/attribute-typos.stderr +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -7,19 +7,19 @@ LL | #[rustc_err] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: cannot find attribute macro `rustc_err` in this scope +error: cannot find attribute `rustc_err` in this scope --> $DIR/attribute-typos.rs:7:3 | LL | #[rustc_err] | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error` -error: cannot find attribute macro `tests` in this scope +error: cannot find attribute `tests` in this scope --> $DIR/attribute-typos.rs:4:3 | LL | #[tests] | ^^^^^ help: an attribute macro with a similar name exists: `test` -error: cannot find attribute macro `deprcated` in this scope +error: cannot find attribute `deprcated` in this scope --> $DIR/attribute-typos.rs:1:3 | LL | #[deprcated] diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs index 1c1230346a..bf0c1dc27c 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs @@ -34,7 +34,7 @@ pub fn main() { let vs = &vx; let vsm = &mut vec![X(Y)]; - // -------- test for duplicate suggestions -------- + // test for duplicate suggestions let &(X(_t), X(_u)) = &(x.clone(), x.clone()); //~^ ERROR cannot move diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs index 6e3879a415..f1e043c30f 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs @@ -22,7 +22,7 @@ fn move_into_fn() { let x = X(Y); - // -------- move into Fn -------- + // move into Fn consume_fn(|| { let X(_t) = x; @@ -89,7 +89,7 @@ fn move_into_fnmut() { let x = X(Y); - // -------- move into FnMut -------- + // move into FnMut consume_fnmut(|| { let X(_t) = x; diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs index 69b303a662..c53ac3d2cd 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/simple.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs @@ -33,7 +33,7 @@ pub fn main() { let vs = &vx; let vsm = &mut vec![X(Y)]; - // -------- move from Either/X place -------- + // move from Either/X place let X(_t) = *s; //~^ ERROR cannot move @@ -163,7 +163,7 @@ pub fn main() { // FIXME: should suggest removing `ref` too } - // -------- move from &Either/&X place -------- + // move from &Either/&X place let &X(_t) = s; //~^ ERROR cannot move @@ -251,7 +251,7 @@ pub fn main() { //~| HELP consider removing the `&mut` //~| SUGGESTION X(_t) - // -------- move from tuple of &Either/&X -------- + // move from tuple of &Either/&X // FIXME: These should have suggestions. @@ -283,7 +283,7 @@ pub fn main() { fn f4((&mut X(_t),): (&mut X,)) { } //~^ ERROR cannot move - // -------- move from &Either/&X value -------- + // move from &Either/&X value let &X(_t) = &x; //~^ ERROR cannot move diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs new file mode 100644 index 0000000000..d625199c93 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs @@ -0,0 +1,3 @@ +fn main() { + assert_eq!(10u64, 10usize); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr new file mode 100644 index 0000000000..f04306997a --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-try_into-in-macros.rs:2:5 + | +LL | assert_eq!(10u64, 10usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 0000000000..acd149c585 --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,18 @@ +// edition:2018 +trait T { + type O; +} + +struct S; + +impl T for S { + type O = (); +} + +fn foo() -> impl T { S } + +fn bar(f: impl T) {} + +fn main() { + bar(foo); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 0000000000..7a49031bde --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 + | +LL | fn bar(f: impl T) {} + | --- ------- required by this bound in `bar` +... +LL | bar(foo); + | ^^^ + | | + | the trait `T` is not implemented for `fn() -> impl T {foo}` + | help: use parentheses to call the function: `foo()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs index 9b6b107481..dd5af3e344 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -42,4 +42,6 @@ fn main() { let _: usize = X::bal; //~ ERROR mismatched types let _: usize = X.ban; //~ ERROR attempted to take value of method let _: usize = X.bal; //~ ERROR attempted to take value of method + let closure = || 42; + let _: usize = closure; //~ ERROR mismatched types } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 0686b56f97..28b331bdbd 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -214,7 +214,21 @@ error[E0615]: attempted to take value of method `bal` on type `X` LL | let _: usize = X.bal; | ^^^ help: use parentheses to call the method: `bal()` -error: aborting due to 16 previous errors +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 + | +LL | let closure = || 42; + | -- closure defined here +LL | let _: usize = closure; + | ^^^^^^^ + | | + | expected usize, found closure + | help: use parentheses to call this closure: `closure()` + | + = note: expected type `usize` + found type `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:24]` + +error: aborting due to 17 previous errors Some errors have detailed explanations: E0308, E0423, E0615. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 0000000000..5109511f95 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 0000000000..cd05b77386 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 0000000000..4aec72006e --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `hello` found for type `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | foo.hello(); + | ^^^^^ method not found in `impl Foo` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 3e28700ce9..fb3e1096ad 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `&str: std::convert::From` is not satisfied --> $DIR/into-str.rs:4:5 | +LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + | --- ------------- required by this bound in `foo` +... LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` -note: required by `foo` - --> $DIR/into-str.rs:1:1 - | -LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr index 6cf71c8b7c..f2496f696d 100644 --- a/src/test/ui/suggestions/issue-21673.stderr +++ b/src/test/ui/suggestions/issue-21673.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `method` found for type `&T` in the current scope --> $DIR/issue-21673.rs:6:7 | LL | x.method() - | ^^^^^^ + | ^^^^^^ method not found in `&T` | = help: items from traits can only be used if the type parameter is bounded by the trait help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: @@ -14,7 +14,7 @@ error[E0599]: no method named `method` found for type `T` in the current scope --> $DIR/issue-21673.rs:10:7 | LL | x.method() - | ^^^^^^ + | ^^^^^^ method not found in `T` | = help: items from traits can only be used if the type parameter is bounded by the trait help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr index cc27b5b49b..b5801e9162 100644 --- a/src/test/ui/suggestions/issue-62843.stderr +++ b/src/test/ui/suggestions/issue-62843.stderr @@ -1,8 +1,8 @@ error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String` - --> $DIR/issue-62843.rs:4:27 + --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); - | ^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String` + | ^^^^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String` | = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String` = note: borrowing the `std::string::String` might fix the problem diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.rs b/src/test/ui/suggestions/mismatched-types-numeric-from.rs new file mode 100644 index 0000000000..56549da9c7 --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.rs @@ -0,0 +1,3 @@ +fn main() { + let _: u32 = i32::from(0_u8); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.stderr b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr new file mode 100644 index 0000000000..223b674732 --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types-numeric-from.rs:2:18 + | +LL | let _: u32 = i32::from(0_u8); + | ^^^^^^^^^^^^^^^ expected u32, found i32 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/opaque-type-error.rs b/src/test/ui/suggestions/opaque-type-error.rs new file mode 100644 index 0000000000..979bb60d48 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.rs @@ -0,0 +1,24 @@ +// edition:2018 +use core::future::Future; + +async fn base_thing() -> Result<(), ()> { + Ok(()) +} + +fn thing_one() -> impl Future> { + base_thing() +} + +fn thing_two() -> impl Future> { + base_thing() +} + +async fn thing() -> Result<(), ()> { + if true { + thing_one() + } else { + thing_two() //~ ERROR if and else have incompatible types + }.await +} + +fn main() {} diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr new file mode 100644 index 0000000000..450cbd4799 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -0,0 +1,20 @@ +error[E0308]: if and else have incompatible types + --> $DIR/opaque-type-error.rs:20:9 + | +LL | / if true { +LL | | thing_one() + | | ----------- expected because of this +LL | | } else { +LL | | thing_two() + | | ^^^^^^^^^^^ expected opaque type, found a different opaque type +LL | | }.await + | |_____- if and else have incompatible types + | + = note: expected type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: distinct uses of `impl Trait` result in different opaque types + = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-box.fixed b/src/test/ui/suggestions/suggest-box.fixed new file mode 100644 index 0000000000..3de02cd0bd --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types + Err(())?; + Ok(()) + }); +} diff --git a/src/test/ui/suggestions/suggest-box.rs b/src/test/ui/suggestions/suggest-box.rs new file mode 100644 index 0000000000..e680a61db3 --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box Result<(), ()>> = || { //~ ERROR mismatched types + Err(())?; + Ok(()) + }; +} diff --git a/src/test/ui/suggestions/suggest-box.stderr b/src/test/ui/suggestions/suggest-box.stderr new file mode 100644 index 0000000000..50c106d63a --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/suggest-box.rs:4:47 + | +LL | let _x: Box Result<(), ()>> = || { + | _______________________________________________^ +LL | | Err(())?; +LL | | Ok(()) +LL | | }; + | |_____^ expected struct `std::boxed::Box`, found closure + | + = note: expected type `std::boxed::Box std::result::Result<(), ()>>` + found type `[closure@$DIR/suggest-box.rs:4:47: 7:6]` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | let _x: Box Result<(), ()>> = Box::new(|| { +LL | Err(())?; +LL | Ok(()) +LL | }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.rs b/src/test/ui/suggestions/suggest-closure-return-type-1.rs new file mode 100644 index 0000000000..910f273b97 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || -> _ { [] }; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr new file mode 100644 index 0000000000..de2d29f127 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-1.rs:2:24 + | +LL | let _v = || -> _ { [] }; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.rs b/src/test/ui/suggestions/suggest-closure-return-type-2.rs new file mode 100644 index 0000000000..6955b37ad9 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || { [] }; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr new file mode 100644 index 0000000000..9dbd822fbb --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-2.rs:2:19 + | +LL | let _v = || { [] }; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.rs b/src/test/ui/suggestions/suggest-closure-return-type-3.rs new file mode 100644 index 0000000000..ec6c094027 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || []; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr new file mode 100644 index 0000000000..ad0d4e41f7 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-3.rs:2:17 + | +LL | let _v = || []; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index ad4a4deb5a..4678410eb4 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -23,7 +23,7 @@ error[E0599]: no method named `count_o` found for type `u32` in the current scop --> $DIR/suggest-methods.rs:28:19 | LL | let _ = 63u32.count_o(); - | ^^^^^^^ + | ^^^^^^^ method not found in `u32` error: aborting due to 4 previous errors diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 52bb118fa2..137b72dcd9 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -64,9 +64,9 @@ fn main() { //[legacy]~^ ERROR symbol-name(_ZN198_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) - //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) - //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) + //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) + //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_def_path] //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index 1c4b256c9e..e024799df8 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -46,19 +46,19 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) +error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) +error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) +error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 7fcd2ede31..de8efdde73 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -4,13 +4,13 @@ error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3f LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h059a991a004536ad) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(issue_60925::foo::Foo::foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs index 89de15cc0f..02438351db 100644 --- a/src/test/ui/symbol-names/issue-60925.rs +++ b/src/test/ui/symbol-names/issue-60925.rs @@ -20,8 +20,8 @@ mod foo { impl Foo<::llvm::Foo> { #[rustc_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo - //[legacy]~| ERROR demangling(issue_60925::foo::Foo::foo + //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo::foo) //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) //[v0]~| ERROR demangling(>::foo) //[v0]~| ERROR demangling-alt(>::foo) diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs index 0206a76993..2d6710af39 100644 --- a/src/test/ui/syntax-extension-minor.rs +++ b/src/test/ui/syntax-extension-minor.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(concat_idents)] pub fn main() { @@ -5,10 +7,8 @@ pub fn main() { let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions let asdf_fdsa = "<.<".to_string(); - // this now fails (correctly, I claim) because hygiene prevents - // the assembled identifier from being a reference to the binding. + // concat_idents should have call-site hygiene. assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); - //~^ ERROR cannot find value `asdf_fdsa` in this scope assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction"); } diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr deleted file mode 100644 index 2d8056da52..0000000000 --- a/src/test/ui/syntax-extension-minor.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0425]: cannot find value `asdf_fdsa` in this scope - --> $DIR/syntax-extension-minor.rs:10:13 - | -LL | assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs new file mode 100644 index 0000000000..abd9e189a7 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr new file mode 100644 index 0000000000..bf1699f5ca --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-2.rs:4:311 + | +LL | ...; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:... + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs new file mode 100644 index 0000000000..8d4d1b1627 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr new file mode 100644 index 0000000000..b56b1948d9 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-unicode.rs:4:415 + | +LL | ...♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆... + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.rs b/src/test/ui/terminal-width/non-whitespace-trimming.rs new file mode 100644 index 0000000000..f6c8d345c6 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.stderr b/src/test/ui/terminal-width/non-whitespace-trimming.stderr new file mode 100644 index 0000000000..622713eb5f --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming.rs:4:241 + | +LL | ...) = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ()... + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.rs b/src/test/ui/terminal-width/whitespace-trimming-2.rs new file mode 100644 index 0000000000..c68f678aab --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming-2.rs @@ -0,0 +1,8 @@ +// ignore-tidy-linelength + +fn foo() -> usize { + () +//~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.stderr b/src/test/ui/terminal-width/whitespace-trimming-2.stderr new file mode 100644 index 0000000000..38df5a9e9a --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming-2.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming-2.rs:4:187 + | +LL | ...-> usize { + | ----- expected `usize` because of return type +LL | ... () + | ^^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/whitespace-trimming.rs b/src/test/ui/terminal-width/whitespace-trimming.rs new file mode 100644 index 0000000000..f747bcf17e --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: () = 42; +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/whitespace-trimming.stderr b/src/test/ui/terminal-width/whitespace-trimming.stderr new file mode 100644 index 0000000000..45a804b9f6 --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming.rs:4:193 + | +LL | ... let _: () = 42; + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-attrs/auxiliary/test_macro.rs similarity index 100% rename from src/test/ui/test-shadowing/auxiliary/test_macro.rs rename to src/test/ui/test-attrs/auxiliary/test_macro.rs diff --git a/src/test/ui/test-attrs/decl-macro-test.rs b/src/test/ui/test-attrs/decl-macro-test.rs new file mode 100644 index 0000000000..fcbe9f49e5 --- /dev/null +++ b/src/test/ui/test-attrs/decl-macro-test.rs @@ -0,0 +1,22 @@ +// Check that declarative macros can declare tests + +// check-pass +// compile-flags: --test + +#![feature(decl_macro)] + +macro create_test() { + #[test] + fn test() {} +} + +macro create_module_test() { + mod x { + #[test] + fn test() {} + } +} + +create_test!(); +create_test!(); +create_module_test!(); diff --git a/src/test/ui/inaccessible-test-modules.rs b/src/test/ui/test-attrs/inaccessible-test-modules.rs similarity index 56% rename from src/test/ui/inaccessible-test-modules.rs rename to src/test/ui/test-attrs/inaccessible-test-modules.rs index 7095ec290f..f5b3479379 100644 --- a/src/test/ui/inaccessible-test-modules.rs +++ b/src/test/ui/test-attrs/inaccessible-test-modules.rs @@ -2,8 +2,8 @@ // the `--test` harness creates modules with these textual names, but // they should be inaccessible from normal code. -use __test as x; //~ ERROR unresolved import `__test` -use __test_reexports as y; //~ ERROR unresolved import `__test_reexports` +use main as x; //~ ERROR unresolved import `main` +use test as y; //~ ERROR unresolved import `test` #[test] fn baz() {} diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr new file mode 100644 index 0000000000..a94ea1e79b --- /dev/null +++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `main` + --> $DIR/inaccessible-test-modules.rs:5:5 + | +LL | use main as x; + | ----^^^^^ + | | + | no `main` in the root + | help: a similar name exists in the module: `main` + +error[E0432]: unresolved import `test` + --> $DIR/inaccessible-test-modules.rs:6:5 + | +LL | use test as y; + | ----^^^^^ + | | + | no `test` in the root + | help: a similar name exists in the module: `test` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs similarity index 100% rename from src/test/ui/test-allow-fail-attr.rs rename to src/test/ui/test-attrs/test-allow-fail-attr.rs diff --git a/src/test/ui/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs similarity index 100% rename from src/test/ui/test-attr-non-associated-functions.rs rename to src/test/ui/test-attrs/test-attr-non-associated-functions.rs diff --git a/src/test/ui/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr similarity index 100% rename from src/test/ui/test-attr-non-associated-functions.stderr rename to src/test/ui/test-attrs/test-attr-non-associated-functions.stderr diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-attrs/test-cant-be-shadowed.rs similarity index 100% rename from src/test/ui/test-shadowing/test-cant-be-shadowed.rs rename to src/test/ui/test-attrs/test-cant-be-shadowed.rs diff --git a/src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs similarity index 100% rename from src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs rename to src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs diff --git a/src/test/ui/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs similarity index 100% rename from src/test/ui/test-main-not-dead-attr.rs rename to src/test/ui/test-attrs/test-main-not-dead-attr.rs diff --git a/src/test/ui/test-main-not-dead.rs b/src/test/ui/test-attrs/test-main-not-dead.rs similarity index 100% rename from src/test/ui/test-main-not-dead.rs rename to src/test/ui/test-attrs/test-main-not-dead.rs diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-attrs/test-on-macro.rs similarity index 100% rename from src/test/ui/test-on-macro.rs rename to src/test/ui/test-attrs/test-on-macro.rs diff --git a/src/test/ui/test-on-macro.stderr b/src/test/ui/test-attrs/test-on-macro.stderr similarity index 100% rename from src/test/ui/test-on-macro.stderr rename to src/test/ui/test-attrs/test-on-macro.stderr diff --git a/src/test/ui/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs similarity index 100% rename from src/test/ui/test-runner-hides-buried-main.rs rename to src/test/ui/test-attrs/test-runner-hides-buried-main.rs diff --git a/src/test/ui/test-runner-hides-main.rs b/src/test/ui/test-attrs/test-runner-hides-main.rs similarity index 100% rename from src/test/ui/test-runner-hides-main.rs rename to src/test/ui/test-attrs/test-runner-hides-main.rs diff --git a/src/test/ui/test-runner-hides-start.rs b/src/test/ui/test-attrs/test-runner-hides-start.rs similarity index 100% rename from src/test/ui/test-runner-hides-start.rs rename to src/test/ui/test-attrs/test-runner-hides-start.rs diff --git a/src/test/ui/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs similarity index 100% rename from src/test/ui/test-should-fail-good-message.rs rename to src/test/ui/test-attrs/test-should-fail-good-message.rs diff --git a/src/test/ui/test-should-panic-attr.rs b/src/test/ui/test-attrs/test-should-panic-attr.rs similarity index 100% rename from src/test/ui/test-should-panic-attr.rs rename to src/test/ui/test-attrs/test-should-panic-attr.rs diff --git a/src/test/ui/test-should-panic-attr.stderr b/src/test/ui/test-attrs/test-should-panic-attr.stderr similarity index 100% rename from src/test/ui/test-should-panic-attr.stderr rename to src/test/ui/test-attrs/test-should-panic-attr.stderr diff --git a/src/test/ui/test-vs-cfg-test.rs b/src/test/ui/test-attrs/test-vs-cfg-test.rs similarity index 100% rename from src/test/ui/test-vs-cfg-test.rs rename to src/test/ui/test-attrs/test-vs-cfg-test.rs diff --git a/src/test/ui/test-warns-dead-code.rs b/src/test/ui/test-attrs/test-warns-dead-code.rs similarity index 100% rename from src/test/ui/test-warns-dead-code.rs rename to src/test/ui/test-attrs/test-warns-dead-code.rs diff --git a/src/test/ui/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr similarity index 100% rename from src/test/ui/test-warns-dead-code.stderr rename to src/test/ui/test-attrs/test-warns-dead-code.stderr diff --git a/src/test/ui/tool-attributes/diagnostic_item.rs b/src/test/ui/tool-attributes/diagnostic_item.rs new file mode 100644 index 0000000000..26a52ce60c --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item.rs @@ -0,0 +1,3 @@ +#[rustc_diagnostic_item = "foomp"] //~ ERROR compiler internal support for linting +struct Foomp; +fn main() {} diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr new file mode 100644 index 0000000000..5432f8dea8 --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item.stderr @@ -0,0 +1,12 @@ +error[E0658]: diagnostic items compiler internal support for linting + --> $DIR/diagnostic_item.rs:1:1 + | +LL | #[rustc_diagnostic_item = "foomp"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/tool-attributes/diagnostic_item2.rs b/src/test/ui/tool-attributes/diagnostic_item2.rs new file mode 100644 index 0000000000..b32a66b16b --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item2.rs @@ -0,0 +1,6 @@ +// check-pass + +#[clippy::diagnostic_item = "mep"] +struct Mep; + +fn main() {} diff --git a/src/test/ui/tool-attributes/diagnostic_item3.rs b/src/test/ui/tool-attributes/diagnostic_item3.rs new file mode 100644 index 0000000000..c1a236ed1c --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item3.rs @@ -0,0 +1,7 @@ +// check-pass +#![feature(rustc_attrs)] + +#[rustc_diagnostic_item = "foomp"] +struct Foomp; + +fn main() {} diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs index 8c62b34bd9..d5698be8d4 100644 --- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs +++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs @@ -4,14 +4,14 @@ type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt:: #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope struct S; -// Interpreted as a feature gated custom attribute -#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope +// Interpreted as an unstable custom attribute +#[rustfmt] //~ ERROR cannot find attribute `rustfmt` in this scope fn check() {} #[rustfmt::skip] // OK fn main() { rustfmt; //~ ERROR expected value, found tool module `rustfmt` - rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope + rustfmt!(); //~ ERROR cannot find macro `rustfmt` in this scope rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip` } diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr index 33581a1708..6bef793e0e 100644 --- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr +++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr @@ -4,13 +4,13 @@ error: cannot find derive macro `rustfmt` in this scope LL | #[derive(rustfmt)] | ^^^^^^^ -error: cannot find attribute macro `rustfmt` in this scope +error: cannot find attribute `rustfmt` in this scope --> $DIR/tool-attributes-misplaced-1.rs:8:3 | LL | #[rustfmt] | ^^^^^^^ -error: cannot find macro `rustfmt!` in this scope +error: cannot find macro `rustfmt` in this scope --> $DIR/tool-attributes-misplaced-1.rs:14:5 | LL | rustfmt!(); diff --git a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr index 972d213ac8..cad5c81f5a 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr @@ -1,28 +1,24 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely - --> $DIR/trait-alias-cross-crate.rs:14:5 + --> $DIR/trait-alias-cross-crate.rs:14:17 | +LL | fn use_alias() {} + | --------- -------- required by this bound in `use_alias` +... LL | use_alias::>(); - | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be sent between threads safely + | ^^^^^^^ `std::rc::Rc` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc` -note: required by `use_alias` - --> $DIR/trait-alias-cross-crate.rs:10:1 - | -LL | fn use_alias() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely - --> $DIR/trait-alias-cross-crate.rs:14:5 + --> $DIR/trait-alias-cross-crate.rs:14:17 | +LL | fn use_alias() {} + | --------- -------- required by this bound in `use_alias` +... LL | use_alias::>(); - | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be shared between threads safely + | ^^^^^^^ `std::rc::Rc` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc` -note: required by `use_alias` - --> $DIR/trait-alias-cross-crate.rs:10:1 - | -LL | fn use_alias() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs index fb26b7e2df..1440f02df1 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // This test checks that trait objects involving trait aliases are well-formed. diff --git a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr index ee2dd5b24a..ca6d058471 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr @@ -1,15 +1,12 @@ error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/trait-alias-wf.rs:5:1 | +LL | trait A {} + | --------------- required by `A` LL | trait B = A; | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` | = help: consider adding a `where T: Foo` bound -note: required by `A` - --> $DIR/trait-alias-wf.rs:4:1 - | -LL | trait A {} - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr index 6fdd2ceaaa..3c68d461f8 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:13:1 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | fn explode(x: Foo) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `f32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:16:1 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | fn kaboom(y: Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `f32` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr index 15441b583c..7e8db610fe 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `u16: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:20:6 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | impl PolyTrait> for Struct { | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr index cdcfff97bd..070b7b013e 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:15:14 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | let baz: Foo = loop { }; | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `{integer}: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:10:15 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr index b019c29792..722f01750c 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-static.rs:9:11 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | static X: Foo = Foo { | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-static.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr index 9a4cc90f3a..bd76df8071 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr @@ -1,89 +1,71 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:13:9 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | impl Foo { | ^^^^^^ the trait `Trait` is not implemented for `T` | = help: consider adding a `where T: Trait` bound -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `isize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | a: Foo, | ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `isize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:23:10 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | Quux(Bar), | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `U: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:27:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | b: Foo, | ^^^^^^^^^ the trait `Trait` is not implemented for `U` | = help: consider adding a `where U: Trait` bound -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `V: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | EvenMoreBadness(Bar), | ^^^^^^ the trait `Trait` is not implemented for `V` | = help: consider adding a `where V: Trait` bound -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | Foo, | ^^^^^^^^ the trait `Trait` is not implemented for `i32` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:39:22 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | DictionaryLike { field: Bar }, | ^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u8` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr index 71d5cc26bf..0d61c3ed00 100644 --- a/src/test/ui/traits/trait-impl-1.stderr +++ b/src/test/ui/traits/trait-impl-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for type `&i32` in the current scope --> $DIR/trait-impl-1.rs:15:7 | LL | x.foo(); - | ^^^ + | ^^^ method not found in `&i32` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index de699a69fa..39cc66d275 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -5,7 +5,7 @@ LL | struct S; | --------- method `a` not found for this ... LL | S.a(); - | ^ + | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `a`, perhaps you need to implement it: @@ -17,8 +17,15 @@ error[E0599]: no method named `b` found for type `S` in the current scope LL | struct S; | --------- method `b` not found for this ... +LL | fn b(&self) { } + | - + | | + | the method is available for `std::boxed::Box` here + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here +... LL | S.b(); - | ^ + | ^ method not found in `S` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -103,12 +110,17 @@ LL | C::A; error[E0038]: the trait `assoc_const::C` cannot be made into an object --> $DIR/trait-item-privacy.rs:101:5 | +LL | const A: u8 = 0; + | - the trait cannot contain associated consts like `A` +... +LL | const B: u8 = 0; + | - the trait cannot contain associated consts like `B` +... +LL | const C: u8 = 0; + | - the trait cannot contain associated consts like `C` +... LL | C::A; | ^^^^ the trait `assoc_const::C` cannot be made into an object - | - = note: the trait cannot contain associated consts like `C` - = note: the trait cannot contain associated consts like `B` - = note: the trait cannot contain associated consts like `A` error[E0223]: ambiguous associated type --> $DIR/trait-item-privacy.rs:115:12 diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 68edc17870..3ac1e96b30 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -1,19 +1,22 @@ error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:22 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = note: method `foo` has no receiver = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object - | - = note: method `foo` has no receiver error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr index 390d21c4a6..a99536d31e 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.stderr +++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: base::HasNew` --> $DIR/trait-static-method-generic-inference.rs:24:25 | +LL | fn new() -> T; + | -------------- required by `base::HasNew::new` +... LL | let _f: base::Foo = base::HasNew::new(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `base::HasNew::new` - --> $DIR/trait-static-method-generic-inference.rs:8:9 - | -LL | fn new() -> T; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-suggest-where-clause.rs b/src/test/ui/traits/trait-suggest-where-clause.rs index 8405e5ff62..5ed14a6a86 100644 --- a/src/test/ui/traits/trait-suggest-where-clause.rs +++ b/src/test/ui/traits/trait-suggest-where-clause.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences use std::mem; struct Misc(T); diff --git a/src/test/ui/traits/trait-suggest-where-clause.stderr b/src/test/ui/traits/trait-suggest-where-clause.stderr index f88dae37e4..d15edaa9c8 100644 --- a/src/test/ui/traits/trait-suggest-where-clause.stderr +++ b/src/test/ui/traits/trait-suggest-where-clause.stderr @@ -1,28 +1,36 @@ error[E0277]: the size for values of type `U` cannot be known at compilation time - --> $DIR/trait-suggest-where-clause.rs:7:5 + --> $DIR/trait-suggest-where-clause.rs:9:20 | LL | mem::size_of::(); - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` | = help: the trait `std::marker::Sized` is not implemented for `U` = note: to learn more, visit = help: consider adding a `where U: std::marker::Sized` bound - = note: required by `std::mem::size_of` error[E0277]: the size for values of type `U` cannot be known at compilation time - --> $DIR/trait-suggest-where-clause.rs:10:5 + --> $DIR/trait-suggest-where-clause.rs:12:5 | LL | mem::size_of::>(); | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` | = help: within `Misc`, the trait `std::marker::Sized` is not implemented for `U` = note: to learn more, visit = help: consider adding a `where U: std::marker::Sized` bound = note: required because it appears within the type `Misc` - = note: required by `std::mem::size_of` error[E0277]: the trait bound `u64: std::convert::From` is not satisfied - --> $DIR/trait-suggest-where-clause.rs:15:5 + --> $DIR/trait-suggest-where-clause.rs:17:5 | LL | >::from; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `u64` @@ -31,7 +39,7 @@ LL | >::from; = note: required by `std::convert::From::from` error[E0277]: the trait bound `u64: std::convert::From<::Item>` is not satisfied - --> $DIR/trait-suggest-where-clause.rs:18:5 + --> $DIR/trait-suggest-where-clause.rs:20:5 | LL | ::Item>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<::Item>` is not implemented for `u64` @@ -40,7 +48,7 @@ LL | ::Item>>::from; = note: required by `std::convert::From::from` error[E0277]: the trait bound `Misc<_>: std::convert::From` is not satisfied - --> $DIR/trait-suggest-where-clause.rs:23:5 + --> $DIR/trait-suggest-where-clause.rs:25:5 | LL | as From>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `Misc<_>` @@ -48,24 +56,32 @@ LL | as From>::from; = note: required by `std::convert::From::from` error[E0277]: the size for values of type `[T]` cannot be known at compilation time - --> $DIR/trait-suggest-where-clause.rs:28:5 + --> $DIR/trait-suggest-where-clause.rs:30:20 | LL | mem::size_of::<[T]>(); - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` | = help: the trait `std::marker::Sized` is not implemented for `[T]` = note: to learn more, visit - = note: required by `std::mem::size_of` error[E0277]: the size for values of type `[&U]` cannot be known at compilation time - --> $DIR/trait-suggest-where-clause.rs:31:5 + --> $DIR/trait-suggest-where-clause.rs:33:5 | LL | mem::size_of::<[&U]>(); | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` | = help: the trait `std::marker::Sized` is not implemented for `[&U]` = note: to learn more, visit - = note: required by `std::mem::size_of` error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 5d5251925a..83c2c06527 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -13,20 +13,25 @@ LL | 10.blah::(); error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:16 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its parameters or return type +... LL | (box 10 as Box).dup(); | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object - | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:6 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its parameters or return type +... LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<{integer}>` error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/traits-conditional-model-fn.rs b/src/test/ui/traits/traits-conditional-model-fn.rs index 27ce6d93a8..ba88670032 100644 --- a/src/test/ui/traits/traits-conditional-model-fn.rs +++ b/src/test/ui/traits/traits-conditional-model-fn.rs @@ -6,7 +6,6 @@ // aux-build:go_trait.rs - extern crate go_trait; use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; @@ -14,8 +13,6 @@ use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; use std::rc::Rc; use std::cell::Cell; -/////////////////////////////////////////////////////////////////////////// - struct SomeGoableThing { counter: Rc> } @@ -26,8 +23,6 @@ impl Go for SomeGoableThing { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeGoOnceableThing { counter: Rc> } @@ -38,8 +33,6 @@ impl GoOnce for SomeGoOnceableThing { } } -/////////////////////////////////////////////////////////////////////////// - fn main() { let counter = Rc::new(Cell::new(0)); let mut x = SomeGoableThing { counter: counter.clone() }; diff --git a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr index cd8501e4df..6fd6a37b22 100644 --- a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr @@ -1,15 +1,13 @@ error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` --> $DIR/traits-inductive-overflow-simultaneous.rs:18:5 | +LL | fn is_ee(t: T) { + | ----- ----- required by this bound in `is_ee` +... LL | is_ee(4); | ^^^^^ | = note: required because of the requirements on the impl of `Combo` for `{integer}` -note: required by `is_ee` - --> $DIR/traits-inductive-overflow-simultaneous.rs:13:1 - | -LL | fn is_ee(t: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index 87e7ba3e7e..40c2c2e4c9 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -5,17 +5,15 @@ LL | auto trait Magic: Copy {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:18 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23 | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ---- ----- required by this bound in `copy` +... LL | let (a, b) = copy(NoClone); - | ^^^^ the trait `std::marker::Copy` is not implemented for `NoClone` + | ^^^^^^^ the trait `std::marker::Copy` is not implemented for `NoClone` | = note: required because of the requirements on the impl of `Magic` for `NoClone` -note: required by `copy` - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:9:1 - | -LL | fn copy(x: T) -> (T, T) { (x, x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr index 769582a778..96a9343d4e 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr @@ -1,15 +1,13 @@ error[E0275]: overflow evaluating the requirement `NoClone: Magic` --> $DIR/traits-inductive-overflow-supertrait.rs:13:18 | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ---- ----- required by this bound in `copy` +... LL | let (a, b) = copy(NoClone); | ^^^^ | = note: required because of the requirements on the impl of `Magic` for `NoClone` -note: required by `copy` - --> $DIR/traits-inductive-overflow-supertrait.rs:7:1 - | -LL | fn copy(x: T) -> (T, T) { (x, x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr index 61adbf00f7..447fc56434 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr @@ -1,14 +1,11 @@ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/traits-inductive-overflow-two-traits.rs:19:5 | +LL | fn wizard() { check::<::X>(); } + | ------ ----- required by this bound in `wizard` +... LL | wizard::<*mut ()>(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `wizard` - --> $DIR/traits-inductive-overflow-two-traits.rs:16:1 - | -LL | fn wizard() { check::<::X>(); } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr index 1bdd73eb6f..22b6d2a0c4 100644 --- a/src/test/ui/traits/traits-negative-impls.stderr +++ b/src/test/ui/traits/traits-negative-impls.stderr @@ -1,100 +1,86 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:23:5 + --> $DIR/traits-negative-impls.rs:23:11 | +LL | struct Outer(T); + | ------------------------- required by `Outer` +... LL | Outer(TestType); - | ^^^^^ `dummy::TestType` cannot be sent between threads safely + | ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` -note: required by `Outer` - --> $DIR/traits-negative-impls.rs:10:1 - | -LL | struct Outer(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:23:5 | +LL | struct Outer(T); + | ------------------------- required by `Outer` +... LL | Outer(TestType); | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` -note: required by `Outer` - --> $DIR/traits-negative-impls.rs:10:1 - | -LL | struct Outer(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy1b::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:32:5 + --> $DIR/traits-negative-impls.rs:32:13 | +LL | fn is_send(_: T) {} + | ------- ---- required by this bound in `is_send` +... LL | is_send(TestType); - | ^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely + | ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy1c::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:40:5 + --> $DIR/traits-negative-impls.rs:40:13 | +LL | fn is_send(_: T) {} + | ------- ---- required by this bound in `is_send` +... LL | is_send((8, TestType)); - | ^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely + | ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely | = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType` = note: required because it appears within the type `({integer}, dummy1c::TestType)` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy2::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:48:5 + --> $DIR/traits-negative-impls.rs:48:13 | +LL | fn is_send(_: T) {} + | ------- ---- required by this bound in `is_send` +... LL | is_send(Box::new(TestType)); - | ^^^^^^^ `dummy2::TestType` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^^^ `dummy2::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy2::TestType` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy3::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:56:5 + --> $DIR/traits-negative-impls.rs:56:13 | +LL | fn is_send(_: T) {} + | ------- ---- required by this bound in `is_send` +... LL | is_send(Box::new(Outer2(TestType))); - | ^^^^^^^ `dummy3::TestType` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely | = help: within `Outer2`, the trait `std::marker::Send` is not implemented for `dummy3::TestType` = note: required because it appears within the type `Outer2` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique>` = note: required because it appears within the type `std::boxed::Box>` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `main::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:66:5 + --> $DIR/traits-negative-impls.rs:66:13 | +LL | fn is_sync(_: T) {} + | ------- ---- required by this bound in `is_sync` +... LL | is_sync(Outer2(TestType)); - | ^^^^^^^ `main::TestType` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `main::TestType` = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2` -note: required by `is_sync` - --> $DIR/traits-negative-impls.rs:17:1 - | -LL | fn is_sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr index 5d1c913768..db77e82adb 100644 --- a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr @@ -15,27 +15,22 @@ LL | c.same_as(22) error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:34:5 | +LL | fn same_as(&self, t: T) -> bool; + | -------------------------------- required by `CompareTo::same_as` +... LL | CompareToInts::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` - | -note: required by `CompareTo::same_as` - --> $DIR/traits-repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:38:5 | +LL | fn same_as(&self, t: T) -> bool; + | -------------------------------- required by `CompareTo::same_as` +... LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `C` | = help: consider adding a `where C: CompareTo` bound -note: required by `CompareTo::same_as` - --> $DIR/traits-repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i64: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:42:23 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 46b4b2a878..acf309ac60 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -12,35 +12,29 @@ error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | LL | 3i32.test(); - | ^^^^ + | ^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `test`, perhaps you need to implement it: candidate #1: `Foo` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/trivial-bounds-leak.rs:25:5 - | -LL | Foo::test(&4i32); - | ^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `Foo::test` - --> $DIR/trivial-bounds-leak.rs:5:5 + --> $DIR/trivial-bounds-leak.rs:25:15 | LL | fn test(&self); - | ^^^^^^^^^^^^^^^ + | --------------- required by `Foo::test` +... +LL | Foo::test(&4i32); + | ^^^^^ the trait `Foo` is not implemented for `i32` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/trivial-bounds-leak.rs:26:5 + --> $DIR/trivial-bounds-leak.rs:26:22 | LL | generic_function(5i32); - | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `generic_function` - --> $DIR/trivial-bounds-leak.rs:29:1 - | + | ^^^^ the trait `Foo` is not implemented for `i32` +... LL | fn generic_function(t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------- --- required by this bound in `generic_function` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs index 2387db8de4..ef10b47fd1 100644 --- a/src/test/ui/try-block/try-block-opt-init.rs +++ b/src/test/ui/try-block/try-block-opt-init.rs @@ -12,5 +12,5 @@ pub fn main() { Ok::<(), ()>(())?; use_val(cfg_res); }; - assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res` + assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly-uninitialized variable: `cfg_res` } diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr index ec0128dbdf..308906477d 100644 --- a/src/test/ui/try-block/try-block-opt-init.stderr +++ b/src/test/ui/try-block/try-block-opt-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `cfg_res` +error[E0381]: borrow of possibly-uninitialized variable: `cfg_res` --> $DIR/try-block-opt-init.rs:15:5 | LL | assert_eq!(cfg_res, 5); - | ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res` + | ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs index 3b48194eb4..602c3c5c35 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-operator-on-main.rs @@ -19,7 +19,7 @@ fn main() { fn try_trait_generic() -> T { // and a non-`Try` object on a `Try` fn. - ()?; //~ ERROR the `?` operator can only + ()?; //~ ERROR the `?` operator can only be applied to values that implement `std::ops::Try` loop {} } diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index 9f120e0094..d2f1a04837 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -17,16 +17,13 @@ LL | ()?; = note: required by `std::ops::Try::into_result` error[E0277]: the trait bound `(): std::ops::Try` is not satisfied - --> $DIR/try-operator-on-main.rs:15:5 + --> $DIR/try-operator-on-main.rs:15:25 | LL | try_trait_generic::<()>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()` - | -note: required by `try_trait_generic` - --> $DIR/try-operator-on-main.rs:20:1 - | + | ^^ the trait `std::ops::Try` is not implemented for `()` +... LL | fn try_trait_generic() -> T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------- --- required by this bound in `try_trait_generic` error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` --> $DIR/try-operator-on-main.rs:22:5 diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs index 0c212096f9..19fcc78721 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs @@ -9,13 +9,13 @@ #![allow(irrefutable_let_patterns)] -enum Enum { TSVariant(T), SVariant { v: T }, UVariant } +enum Enum { TSVariant(T), SVariant { _v: T }, UVariant } type Alias = Enum; type AliasFixed = Enum<()>; macro_rules! is_variant { (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr)); - (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr)); + (SVariant, $expr:expr) => (is_variant!(@check SVariant, { _v: _ }, $expr)); (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr)); (@check $variant:ident, $matcher:tt, $expr:expr) => ( assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false }, @@ -37,14 +37,14 @@ fn main() { // Struct variant - is_variant!(SVariant, Enum::SVariant { v: () }); - is_variant!(SVariant, Enum::SVariant::<()> { v: () }); - is_variant!(SVariant, Enum::<()>::SVariant { v: () }); + is_variant!(SVariant, Enum::SVariant { _v: () }); + is_variant!(SVariant, Enum::SVariant::<()> { _v: () }); + is_variant!(SVariant, Enum::<()>::SVariant { _v: () }); - is_variant!(SVariant, Alias::SVariant { v: () }); - is_variant!(SVariant, Alias::<()>::SVariant { v: () }); + is_variant!(SVariant, Alias::SVariant { _v: () }); + is_variant!(SVariant, Alias::<()>::SVariant { _v: () }); - is_variant!(SVariant, AliasFixed::SVariant { v: () }); + is_variant!(SVariant, AliasFixed::SVariant { _v: () }); // Unit variant diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index ee73622cb7..a0a617fdbb 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -6,6 +6,8 @@ LL | Self::TSVariant(()); | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:15:27 @@ -27,6 +29,8 @@ LL | Self::<()>::TSVariant(()); | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:20:16 @@ -48,6 +52,8 @@ LL | Self::SVariant { v: () }; | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:28:26 @@ -63,6 +69,8 @@ LL | Self::SVariant::<()> { v: () }; | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:31:16 @@ -78,6 +86,8 @@ LL | Self::<()>::SVariant { v: () }; | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:34:16 @@ -99,6 +109,8 @@ LL | Self::<()>::SVariant::<()> { v: () }; | = note: expected type `T` found type `()` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:41:26 diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 91c4576597..9e96b1cf7b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -24,3 +24,5 @@ where .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) } } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index ebb13fca1d..b838c06cad 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_60564` - | - = note: consider adding a `main` function to `$DIR/issue-60564.rs` - error: type parameter `E` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-60564.rs:20:49 | @@ -20,6 +16,5 @@ error: could not find defining uses LL | type IterBitsIter = impl std::iter::Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs index c11a248d3c..c21d9f3d97 100644 --- a/src/test/ui/type/ascription/issue-34255-1.rs +++ b/src/test/ui/type/ascription/issue-34255-1.rs @@ -13,3 +13,4 @@ impl Reactor { } // This case isn't currently being handled gracefully, including for completeness. +fn main() {} diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr index 531455b82b..0d0acfde88 100644 --- a/src/test/ui/type/ascription/issue-34255-1.stderr +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -5,26 +5,22 @@ LL | input_cells: Vec::new() | ^^^^^^^^^^^ a field by this name exists in `Self` error: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-34255-1.rs:7:30 + --> $DIR/issue-34255-1.rs:7:27 | LL | input_cells: Vec::new() - | ^^ + | ^^^^^ | = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error[E0601]: `main` function not found in crate `issue_34255_1` - | - = note: consider adding a `main` function to `$DIR/issue-34255-1.rs` - error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/issue-34255-1.rs:7:22 | LL | input_cells: Vec::new() | ^^^^^^^^^^ expected 1 type argument -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0425, E0601. +Some errors have detailed explanations: E0107, E0425. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs index 6d65760e29..b53bfe5df0 100644 --- a/src/test/ui/type/ascription/issue-54516.rs +++ b/src/test/ui/type/ascription/issue-54516.rs @@ -2,5 +2,5 @@ use std::collections::BTreeMap; fn main() { println!("{}", std::mem:size_of::>()); - //~^ ERROR expected token: `,` + //~^ ERROR expected one of } diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr index a846f3bc32..97942904a0 100644 --- a/src/test/ui/type/ascription/issue-54516.stderr +++ b/src/test/ui/type/ascription/issue-54516.stderr @@ -1,8 +1,8 @@ -error: expected token: `,` +error: expected one of `!`, `,`, or `::`, found `(` --> $DIR/issue-54516.rs:4:58 | LL | println!("{}", std::mem:size_of::>()); - | - ^ expected `,` + | - ^ expected one of `!`, `,`, or `::` here | | | help: maybe write a path separator here: `::` | diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs index ff2342c445..ddf16f7699 100644 --- a/src/test/ui/type/type-annotation-needed.rs +++ b/src/test/ui/type/type-annotation-needed.rs @@ -1,5 +1,6 @@ fn foo>(x: i32) {} //~^ NOTE required by +//~| NOTE fn main() { foo(42); diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 92ae9746b1..01287b727d 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: std::convert::Into` - --> $DIR/type-annotation-needed.rs:5:5 + --> $DIR/type-annotation-needed.rs:6:5 | +LL | fn foo>(x: i32) {} + | --- ------------ required by this bound in `foo` +... LL | foo(42); | ^^^ - | -note: required by `foo` - --> $DIR/type-annotation-needed.rs:1:1 - | -LL | fn foo>(x: i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index a46d79ec31..742a709958 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -1,90 +1,71 @@ error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32` --> $DIR/type-check-defaults.rs:6:19 | +LL | struct Foo>(T, U); + | ---------------------------------------- required by `Foo` LL | struct WellFormed>(Z); | ^ a collection of type `i32` cannot be built from `std::iter::Iterator` | = help: the trait `std::iter::FromIterator` is not implemented for `i32` -note: required by `Foo` - --> $DIR/type-check-defaults.rs:5:1 - | -LL | struct Foo>(T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32` --> $DIR/type-check-defaults.rs:8:27 | +LL | struct Foo>(T, U); + | ---------------------------------------- required by `Foo` +... LL | struct WellFormedNoBounds>(Z); | ^ a collection of type `i32` cannot be built from `std::iter::Iterator` | = help: the trait `std::iter::FromIterator` is not implemented for `i32` -note: required by `Foo` - --> $DIR/type-check-defaults.rs:5:1 - | -LL | struct Foo>(T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied - --> $DIR/type-check-defaults.rs:11:1 + --> $DIR/type-check-defaults.rs:11:17 | LL | struct Bounds(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `Bounds` - --> $DIR/type-check-defaults.rs:11:1 - | -LL | struct Bounds(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------^^^^------------ + | | | + | | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `Bounds` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied - --> $DIR/type-check-defaults.rs:14:1 - | -LL | struct WhereClause(T) where T: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `WhereClause` - --> $DIR/type-check-defaults.rs:14:1 + --> $DIR/type-check-defaults.rs:14:42 | LL | struct WhereClause(T) where T: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -----------------------------------------^^^^- + | | | + | | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `WhereClause` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied - --> $DIR/type-check-defaults.rs:17:1 - | -LL | trait TraitBound {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `TraitBound` - --> $DIR/type-check-defaults.rs:17:1 + --> $DIR/type-check-defaults.rs:17:20 | LL | trait TraitBound {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------^^^^-------- + | | | + | | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `TraitBound` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:21:1 | +LL | trait Super { } + | -------------------- required by `Super` LL | trait Base: Super { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `Super` - --> $DIR/type-check-defaults.rs:20:1 - | -LL | trait Super { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add `u8` to `i32` - --> $DIR/type-check-defaults.rs:24:1 + --> $DIR/type-check-defaults.rs:24:66 | LL | trait ProjectionPred> where T::Item : Add {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` + | -----------------------------------------------------------------^^^^^^^ + | | | + | | no implementation for `i32 + u8` + | required by `ProjectionPred` | = help: the trait `std::ops::Add` is not implemented for `i32` -note: required by `ProjectionPred` - --> $DIR/type-check-defaults.rs:24:1 - | -LL | trait ProjectionPred> where T::Item : Add {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 254875fcaa..732a81c8a2 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,6 +1,9 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-40294.rs:5:1 | +LL | trait Foo: Sized { + | ---------------- required by `Foo` +... LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) LL | | where &'a T : Foo, LL | | &'b T : Foo @@ -9,12 +12,6 @@ LL | | x.foo(); LL | | y.foo(); LL | | } | |_^ - | -note: required by `Foo` - --> $DIR/issue-40294.rs:1:1 - | -LL | trait Foo: Sized { - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 58727ea0fe..b315fe9df8 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -13,10 +13,11 @@ LL | let y = x as dyn MyAdd; error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | +LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } + | --- method `add` references the `Self` type in its parameters or return type +... LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object - | - = note: method `add` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/type/type-parameter-names.stderr b/src/test/ui/type/type-parameter-names.stderr index 9acae5c376..3397eec9e0 100644 --- a/src/test/ui/type/type-parameter-names.stderr +++ b/src/test/ui/type/type-parameter-names.stderr @@ -8,6 +8,8 @@ LL | x | = note: expected type `Bar` found type `Foo` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/type/type-params-in-different-spaces-1.rs b/src/test/ui/type/type-params-in-different-spaces-1.rs index 449a26e901..71fb7f380a 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.rs +++ b/src/test/ui/type/type-params-in-different-spaces-1.rs @@ -5,7 +5,7 @@ trait BrokenAdd: Copy + Add { *self + rhs //~ ERROR mismatched types //~| expected type `Self` //~| found type `T` - //~| expected Self, found type parameter + //~| expected type parameter, found a different type parameter } } diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr index b3b78424fd..a10bf4e0b7 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr @@ -2,10 +2,12 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-1.rs:5:17 | LL | *self + rhs - | ^^^ expected Self, found type parameter + | ^^^ expected type parameter, found a different type parameter | = note: expected type `Self` found type `T` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index 15db94ef1e..7d4bbc813c 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -1,28 +1,24 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:10:9 | +LL | fn op(_: T) -> Self; + | -------------------- required by `Tr::op` +... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | = help: consider adding a `where Self: Tr` bound -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 | +LL | fn op(_: T) -> Self; + | -------------------- required by `Tr::op` +... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | = help: consider adding a `where Self: Tr` bound -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr index 4e8134da2d..9f0fa5a0ea 100644 --- a/src/test/ui/type/type-params-in-different-spaces-3.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr @@ -4,10 +4,12 @@ error[E0308]: mismatched types LL | fn test(u: X) -> Self { | ---- expected `Self` because of return type LL | u - | ^ expected Self, found type parameter + | ^ expected type parameter, found a different type parameter | = note: expected type `Self` found type `X` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index a31ee83ae1..b842d0ae1a 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -3,14 +3,12 @@ error[E0277]: `::AssocType` cannot be sent between threads safely | LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely +... +LL | fn is_send() { + | ------- ---- required by this bound in `is_send` | = help: the trait `std::marker::Send` is not implemented for `::AssocType` = help: consider adding a `where ::AssocType: std::marker::Send` bound -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-assoc-type.rs:12:1 - | -LL | fn is_send() { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr index db1d7d8c0b..f060afea24 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5 | +LL | fn is_mytrait() {} + | ---------- ------- required by this bound in `is_mytrait` +... LL | is_mytrait::<(MyS2, MyS)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` | = help: the following implementations were found: = note: required because it appears within the type `(MyS2, MyS)` -note: required by `is_mytrait` - --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:11:1 - | -LL | fn is_mytrait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr index 0f90518964..22a2cb3e0e 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:5 + --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:18 | +LL | fn is_mytrait() {} + | ---------- ------- required by this bound in `is_mytrait` +... LL | is_mytrait::(); - | ^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `MyS2` + | ^^^^ the trait `MyTrait` is not implemented for `MyS2` | = help: the following implementations were found: -note: required by `is_mytrait` - --> $DIR/typeck-default-trait-impl-constituent-types.rs:15:1 - | -LL | fn is_mytrait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr index 8442f47e82..e30d4dfa1b 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr @@ -1,15 +1,13 @@ error[E0277]: `MyNotSendable` cannot be sent between threads safely - --> $DIR/typeck-default-trait-impl-negation-send.rs:19:5 + --> $DIR/typeck-default-trait-impl-negation-send.rs:19:15 | +LL | fn is_send() {} + | ------- ---- required by this bound in `is_send` +... LL | is_send::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely + | ^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `MyNotSendable` -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-negation-send.rs:15:1 - | -LL | fn is_send() {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index 4d435bf4e8..4dd8e01cf2 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -1,43 +1,37 @@ error[E0277]: `MyNotSync` cannot be shared between threads safely - --> $DIR/typeck-default-trait-impl-negation-sync.rs:33:5 + --> $DIR/typeck-default-trait-impl-negation-sync.rs:33:15 | +LL | fn is_sync() {} + | ------- ---- required by this bound in `is_sync` +... LL | is_sync::(); - | ^^^^^^^^^^^^^^^^^^^^ `MyNotSync` cannot be shared between threads safely + | ^^^^^^^^^ `MyNotSync` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `MyNotSync` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:5 | +LL | fn is_sync() {} + | ------- ---- required by this bound in `is_sync` +... LL | is_sync::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: within `MyTypeWUnsafe`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `MyTypeWUnsafe` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Managed` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5 | +LL | fn is_sync() {} + | ------- ---- required by this bound in `is_sync` +... LL | is_sync::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely | = help: within `MyTypeManaged`, the trait `std::marker::Sync` is not implemented for `Managed` = note: required because it appears within the type `MyTypeManaged` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr index 751083d035..4b13fcc885 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr @@ -1,30 +1,26 @@ error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:21:5 + --> $DIR/typeck-default-trait-impl-negation.rs:21:19 | +LL | fn is_my_trait() {} + | ----------- ------- required by this bound in `is_my_trait` +... LL | is_my_trait::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` + | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` | = help: the following implementations were found: -note: required by `is_my_trait` - --> $DIR/typeck-default-trait-impl-negation.rs:16:1 - | -LL | fn is_my_trait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:24:5 + --> $DIR/typeck-default-trait-impl-negation.rs:24:26 | +LL | fn is_my_unsafe_trait() {} + | ------------------ ------------- required by this bound in `is_my_unsafe_trait` +... LL | is_my_unsafe_trait::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` + | ^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` | = help: the following implementations were found: -note: required by `is_my_unsafe_trait` - --> $DIR/typeck-default-trait-impl-negation.rs:17:1 - | -LL | fn is_my_unsafe_trait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr index d45cbb27a5..1587730441 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:18:5 | +LL | fn is_defaulted() { } + | ------------ --------- required by this bound in `is_defaulted` +... LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | = note: required because of the requirements on the impl of `Defaulted` for `&'static u32` -note: required by `is_defaulted` - --> $DIR/typeck-default-trait-impl-precedence.rs:11:1 - | -LL | fn is_defaulted() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr index a850cc7b37..b3139083b1 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -1,16 +1,14 @@ error[E0277]: `T` cannot be sent between threads safely - --> $DIR/typeck-default-trait-impl-send-param.rs:5:5 + --> $DIR/typeck-default-trait-impl-send-param.rs:5:15 | LL | is_send::() - | ^^^^^^^^^^^^ `T` cannot be sent between threads safely + | ^ `T` cannot be sent between threads safely +... +LL | fn is_send() { + | ------- ---- required by this bound in `is_send` | = help: the trait `std::marker::Send` is not implemented for `T` = help: consider adding a `where T: std::marker::Send` bound -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-send-param.rs:8:1 - | -LL | fn is_send() { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr index ff351afdca..d08613238f 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr +++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr @@ -1,55 +1,47 @@ error[E0277]: `std::cell::UnsafeCell>` cannot be shared between threads safely - --> $DIR/typeck-unsafe-always-share.rs:19:5 + --> $DIR/typeck-unsafe-always-share.rs:19:10 | +LL | fn test(s: T) {} + | ---- ---- required by this bound in `test` +... LL | test(us); - | ^^^^ `std::cell::UnsafeCell>` cannot be shared between threads safely + | ^^ `std::cell::UnsafeCell>` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell>` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely - --> $DIR/typeck-unsafe-always-share.rs:23:5 + --> $DIR/typeck-unsafe-always-share.rs:23:10 | +LL | fn test(s: T) {} + | ---- ---- required by this bound in `test` +... LL | test(uns); - | ^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely + | ^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:27:5 | +LL | fn test(s: T) {} + | ---- ---- required by this bound in `test` +... LL | test(ms); | ^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: within `MySync`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `MySync` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `NoSync` cannot be shared between threads safely - --> $DIR/typeck-unsafe-always-share.rs:30:5 + --> $DIR/typeck-unsafe-always-share.rs:30:10 | +LL | fn test(s: T) {} + | ---- ---- required by this bound in `test` +... LL | test(NoSync); - | ^^^^ `NoSync` cannot be shared between threads safely + | ^^^^^^ `NoSync` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `NoSync` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs index c6ff94a5e7..bdb8e197fb 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs @@ -6,7 +6,7 @@ struct Foo { impl Foo { fn foo(self: isize, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type self.f + x } } @@ -17,11 +17,11 @@ struct Bar { impl Bar { fn foo(self: Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } fn bar(self: &Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } } @@ -34,14 +34,14 @@ trait SomeTrait { impl<'a, T> SomeTrait for &'a Bar { fn dummy1(self: &&'a Bar) { } - fn dummy2(self: &Bar) {} //~ ERROR mismatched method receiver - //~^ ERROR mismatched method receiver + fn dummy2(self: &Bar) {} //~ ERROR mismatched `self` parameter type + //~^ ERROR mismatched `self` parameter type fn dummy3(self: &&Bar) {} - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index 6da20e3757..b2fe1b281f 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -1,31 +1,31 @@ -error[E0307]: invalid method receiver type: isize +error[E0307]: invalid `self` parameter type: isize --> $DIR/ufcs-explicit-self-bad.rs:8:18 | LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: Bar +error[E0307]: invalid `self` parameter type: Bar --> $DIR/ufcs-explicit-self-bad.rs:19:18 | LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: &Bar +error[E0307]: invalid `self` parameter type: &Bar --> $DIR/ufcs-explicit-self-bad.rs:23:18 | LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -44,7 +44,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -63,7 +63,7 @@ note: ...does not necessarily outlive the anonymous lifetime #1 defined on the m LL | fn dummy2(self: &Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -82,7 +82,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -103,4 +103,5 @@ LL | fn dummy3(self: &&Bar) {} error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0307, E0308. +For more information about an error, try `rustc --explain E0307`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr index fd5ef4b9df..6ec4063828 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-default.rs:21:5 | +LL | fn eq() where A : Eq { } + | -- ----- required by this bound in `eq` +... LL | eq::, dyn Foo(isize)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>` - | -note: required by `eq` - --> $DIR/unboxed-closure-sugar-default.rs:14:1 - | -LL | fn eq() where A : Eq { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr index 005a86bc21..8dd32ee7f1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr @@ -1,15 +1,12 @@ error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-equiv.rs:43:5 | +LL | fn eq>() { } + | -- ----- required by this bound in `eq` +... LL | / eq::< dyn Foo<(),Output=()>, LL | | dyn Foo(char) >(); | |_______________________________________________________________________^ the trait `Eq>` is not implemented for `dyn Foo<(char,), Output = ()>` - | -note: required by `eq` - --> $DIR/unboxed-closure-sugar-equiv.rs:16:1 - | -LL | fn eq>() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr index 81095826f3..32619420f6 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr @@ -1,8 +1,8 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19 + --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 | LL | let x: Box = panic!(); - | ^^ only `Fn` traits may use parentheses + | ^^^^^ only `Fn` traits may use parentheses error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index 7d05ca55ff..f5cf6db30f 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -1,11 +1,11 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18 + --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:13 | LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) - | ^^^^^^^^^^^^^^ - | | - | only `Fn` traits may use parentheses - | help: use angle brackets instead: `` + | ^^^^^^^^^^^^^^^^^^^ + | | + | only `Fn` traits may use parentheses + | help: use angle brackets instead: `Bar::` error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr index 3c78d9f913..ba93b60dad 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr @@ -1,8 +1,8 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18 + --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 | LL | fn foo(b: Box) { - | ^^ only `Fn` traits may use parentheses + | ^^^^^ only `Fn` traits may use parentheses error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr index c59082932d..59e7bc8c83 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr @@ -1,8 +1,8 @@ error[E0220]: associated type `Output` not found for `One<()>` - --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:19 + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:16 | LL | fn foo(_: &dyn One()) - | ^^ associated type `Output` not found + | ^^^^^ associated type `Output` not found error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr index 6c61e74584..f42ac38d37 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr @@ -5,10 +5,10 @@ LL | fn foo(_: &dyn Three()) | ^^^^^^^ expected 3 type arguments error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>` - --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:21 + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16 | LL | fn foo(_: &dyn Three()) - | ^^ associated type `Output` not found + | ^^^^^^^ associated type `Output` not found error: aborting due to 2 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr index b96e2cbc36..8185a798e7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr @@ -1,14 +1,14 @@ error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:19 + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15 | LL | fn foo(_: dyn Zero()) - | ^^ unexpected type argument + | ^^^^^^ unexpected type argument error[E0220]: associated type `Output` not found for `Zero` - --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:19 + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15 | LL | fn foo(_: dyn Zero()) - | ^^ associated type `Output` not found + | ^^^^^^ associated type `Output` not found error: aborting due to 2 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr index bd707a8508..c81402a3dc 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr @@ -1,8 +1,8 @@ error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:13 + --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:8 | LL | fn f isize>(x: F) {} - | ^^^^^^^ unexpected type argument + | ^^^^^^^^^^^^ unexpected type argument error[E0220]: associated type `Output` not found for `Trait` --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:24 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index fcf11290c8..dc76618153 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -1,15 +1,13 @@ error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `S` - --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:13 + --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21 | +LL | fn call_itisize>(f: &F, x: isize) -> isize { + | ------- ---------------- required by this bound in `call_it` +... LL | let x = call_it(&S, 22); - | ^^^^^^^ expected an `Fn<(isize,)>` closure, found `S` + | ^^ expected an `Fn<(isize,)>` closure, found `S` | = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `S` -note: required by `call_it` - --> $DIR/unboxed-closures-fnmut-as-fn.rs:23:1 - | -LL | fn call_itisize>(f: &F, x: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr index 728efadf41..526055ba04 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr @@ -23,3 +23,4 @@ LL | | }); error: aborting due to previous error +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index 2e1845888a..18276d5710 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `call` found for type `[closure@$DIR/unboxed-closu --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10 | LL | mut_.call((0, )); - | ^^^^ + | ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` | = note: mut_ is a function, perhaps you wish to call it diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index ca02982836..0b86719df8 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----------------- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- -------------------- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- ----- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:26 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ------------ ----- required by this bound in `call_it_once` +... LL | let z = call_it_once(square, 22); - | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 0abc58aeeb..17faf047c1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:13 + --> $DIR/unboxed-closures-wrong-abi.rs:12:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----------------- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-abi.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:13 + --> $DIR/unboxed-closures-wrong-abi.rs:12:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-abi.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- -------------------- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-abi.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- ----- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-abi.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:24:13 + --> $DIR/unboxed-closures-wrong-abi.rs:24:26 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ------------ ----- required by this bound in `call_it_once` +... LL | let z = call_it_once(square, 22); - | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-wrong-abi.rs:9:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 19b87ad171..5b1d6eb5b6 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----------------- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ------- ----- required by this bound in `call_it` +... LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- -------------------- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ----------- ----- required by this bound in `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:26 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ------------ ----- required by this bound in `call_it_once` +... LL | let z = call_it_once(square, 22); - | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/underscore-imports/auxiliary/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs rename to src/test/ui/underscore-imports/auxiliary/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/underscore-imports/auxiliary/underscore-imports.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs rename to src/test/ui/underscore-imports/auxiliary/underscore-imports.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/underscore-imports/basic.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.rs rename to src/test/ui/underscore-imports/basic.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/underscore-imports/basic.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.stderr rename to src/test/ui/underscore-imports/basic.stderr diff --git a/src/test/ui/underscore-imports/cycle.rs b/src/test/ui/underscore-imports/cycle.rs new file mode 100644 index 0000000000..bacf9b2d5a --- /dev/null +++ b/src/test/ui/underscore-imports/cycle.rs @@ -0,0 +1,18 @@ +// Check that cyclic glob imports are allowed with underscore imports + +// check-pass + +mod x { + pub use crate::y::*; + pub use std::ops::Deref as _; +} + +mod y { + pub use crate::x::*; + pub use std::ops::Deref as _; +} + +pub fn main() { + use x::*; + (&0).deref(); +} diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/underscore-imports/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/duplicate.rs rename to src/test/ui/underscore-imports/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/underscore-imports/intercrate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/intercrate.rs rename to src/test/ui/underscore-imports/intercrate.rs diff --git a/src/test/ui/underscore-imports/shadow.rs b/src/test/ui/underscore-imports/shadow.rs new file mode 100644 index 0000000000..325f2001b9 --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.rs @@ -0,0 +1,23 @@ +// Check that underscore imports don't cause glob imports to be unshadowed + +mod a { + pub use std::ops::Deref as Shadow; +} + +mod b { + pub use crate::a::*; + macro_rules! m { + ($i:ident) => { pub struct $i; } + } + m!(Shadow); +} + +mod c { + use crate::b::Shadow as _; // Only imports the struct + + fn f(x: &()) { + x.deref(); //~ ERROR no method named `deref` found + } +} + +fn main() {} diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr new file mode 100644 index 0000000000..63262d0dc3 --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `deref` found for type `&()` in the current scope + --> $DIR/shadow.rs:19:11 + | +LL | x.deref(); + | ^^^^^ method not found in `&()` + | + = help: items from traits can only be used if the trait is in scope + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: + `use std::ops::Deref;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/underscore-imports/unused-2018.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.rs rename to src/test/ui/underscore-imports/unused-2018.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/underscore-imports/unused-2018.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr rename to src/test/ui/underscore-imports/unused-2018.stderr diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index be6ed8d562..2079f6fd53 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 | +LL | fn foo(); + | --------- required by `Foo::foo` +... LL | <[(); 0] as Foo>::foo() | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | = help: the following implementations were found: <[(); 1] as Foo> -note: required by `Foo::foo` - --> $DIR/unevaluated_fixed_size_array_len.rs:4:5 - | -LL | fn foo(); - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index 45976f8ac5..29ff1dc376 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -3,6 +3,7 @@ error[E0005]: refutable pattern in local binding: `A(_)` not covered | LL | / enum Foo { LL | | A(foo::SecretlyEmpty), + | | - not covered LL | | B(foo::NotSoSecretlyEmpty), LL | | C(NotSoSecretlyEmpty), LL | | D(u32), diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 37a0093784..4f4c779b12 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -13,7 +13,7 @@ LL | union U4 { | ----------- method `clone` not found for this ... LL | let w = u.clone(); - | ^^^^^ + | ^^^^^ method not found in `U4` | = note: the method `clone` exists but the following trait bounds were not satisfied: `U4 : std::clone::Clone` diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr index 6a3216db64..f13b2def6d 100644 --- a/src/test/ui/union/union-generic.stderr +++ b/src/test/ui/union/union-generic.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied --> $DIR/union-generic.rs:8:13 | +LL | union U { + | ---------------- required by `U` +... LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `U` - --> $DIR/union-generic.rs:3:1 - | -LL | union U { - | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied --> $DIR/union-generic.rs:10:13 | +LL | union U { + | ---------------- required by `U` +... LL | let u = U::> { a: Default::default() }; | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `U` - --> $DIR/union-generic.rs:3:1 - | -LL | union U { - | ^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/union/union-repr-c.rs b/src/test/ui/union/union-repr-c.rs index 658452d57f..1367835e67 100644 --- a/src/test/ui/union/union-repr-c.rs +++ b/src/test/ui/union/union-repr-c.rs @@ -12,7 +12,7 @@ union W { extern "C" { static FOREIGN1: U; // OK - static FOREIGN2: W; //~ ERROR union has unspecified layout + static FOREIGN2: W; //~ ERROR `extern` block uses type `W` } fn main() {} diff --git a/src/test/ui/union/union-repr-c.stderr b/src/test/ui/union/union-repr-c.stderr index c60817a849..c8bc0380de 100644 --- a/src/test/ui/union/union-repr-c.stderr +++ b/src/test/ui/union/union-repr-c.stderr @@ -1,8 +1,8 @@ -error: `extern` block uses type `W` which is not FFI-safe: this union has unspecified layout +error: `extern` block uses type `W`, which is not FFI-safe --> $DIR/union-repr-c.rs:15:22 | LL | static FOREIGN2: W; - | ^ + | ^ not FFI-safe | note: lint level defined here --> $DIR/union-repr-c.rs:2:9 @@ -10,6 +10,7 @@ note: lint level defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union + = note: this union has unspecified layout note: type defined here --> $DIR/union-repr-c.rs:9:1 | diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 407905f52e..cd46878c19 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for type `std::boxed::Box` --> $DIR/unique-object-noncopyable.rs:24:16 | LL | let _z = y.clone(); - | ^^^^^ + | ^^^^^ method not found in `std::boxed::Box` | = note: the method `clone` exists but the following trait bounds were not satisfied: `std::boxed::Box : std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 0f6ba90afa..19ef2b21c2 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for type `std::boxed::Box` in the --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | let _j = i.clone(); - | ^^^^^ + | ^^^^^ method not found in `std::boxed::Box` | = note: the method `clone` exists but the following trait bounds were not satisfied: `std::boxed::Box : std::clone::Clone` diff --git a/src/test/ui/unreachable/unreachable-code.stderr b/src/test/ui/unreachable/unreachable-code.stderr index 803bb966be..184440db5d 100644 --- a/src/test/ui/unreachable/unreachable-code.stderr +++ b/src/test/ui/unreachable/unreachable-code.stderr @@ -1,8 +1,11 @@ error: unreachable statement --> $DIR/unreachable-code.rs:7:3 | +LL | loop{} + | ------ any code following this expression is unreachable +LL | LL | let a = 3; - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable statement | note: lint level defined here --> $DIR/unreachable-code.rs:1:9 diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/unreachable/unreachable-in-call.rs index 25f849d7a0..dd94e79f4d 100644 --- a/src/test/ui/unreachable/unreachable-in-call.rs +++ b/src/test/ui/unreachable/unreachable-in-call.rs @@ -14,7 +14,7 @@ fn diverge_first() { get_u8()); //~ ERROR unreachable expression } fn diverge_second() { - call( //~ ERROR unreachable expression + call( //~ ERROR unreachable call get_u8(), diverge()); } diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr index f8dd54590f..1d081d1c76 100644 --- a/src/test/ui/unreachable/unreachable-in-call.stderr +++ b/src/test/ui/unreachable/unreachable-in-call.stderr @@ -1,8 +1,10 @@ error: unreachable expression --> $DIR/unreachable-in-call.rs:14:10 | +LL | call(diverge(), + | --------- any code following this expression is unreachable LL | get_u8()); - | ^^^^^^^^ + | ^^^^^^^^ unreachable expression | note: lint level defined here --> $DIR/unreachable-in-call.rs:2:9 @@ -10,13 +12,14 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression +error: unreachable call --> $DIR/unreachable-in-call.rs:17:5 | -LL | / call( -LL | | get_u8(), -LL | | diverge()); - | |__________________^ +LL | call( + | ^^^^ unreachable call +LL | get_u8(), +LL | diverge()); + | --------- any code following this expression is unreachable error: aborting due to 2 previous errors diff --git a/src/test/ui/unreachable/unreachable-try-pattern.stderr b/src/test/ui/unreachable/unreachable-try-pattern.stderr index 758aa5a45b..707038442a 100644 --- a/src/test/ui/unreachable/unreachable-try-pattern.stderr +++ b/src/test/ui/unreachable/unreachable-try-pattern.stderr @@ -2,7 +2,10 @@ warning: unreachable expression --> $DIR/unreachable-try-pattern.rs:19:36 | LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; - | ^^^^^^^^ + | -^^^^^^^ + | | + | unreachable expression + | any code following this expression is unreachable | note: lint level defined here --> $DIR/unreachable-try-pattern.rs:3:9 diff --git a/src/test/ui/unreachable/unwarned-match-on-never.stderr b/src/test/ui/unreachable/unwarned-match-on-never.stderr index ccb70d7431..6b2fb4a33c 100644 --- a/src/test/ui/unreachable/unwarned-match-on-never.stderr +++ b/src/test/ui/unreachable/unwarned-match-on-never.stderr @@ -2,7 +2,10 @@ error: unreachable expression --> $DIR/unwarned-match-on-never.rs:10:5 | LL | match x {} - | ^^^^^^^^^^ + | - any code following this expression is unreachable +LL | // But matches in unreachable code are warned. +LL | match x {} + | ^^^^^^^^^^ unreachable expression | note: lint level defined here --> $DIR/unwarned-match-on-never.rs:1:9 @@ -13,16 +16,20 @@ LL | #![deny(unreachable_code)] error: unreachable arm --> $DIR/unwarned-match-on-never.rs:15:15 | +LL | match (return) { + | -------- any code following this expression is unreachable LL | () => () - | ^^ + | ^^ unreachable arm error: unreachable expression --> $DIR/unwarned-match-on-never.rs:21:5 | +LL | return; + | ------ any code following this expression is unreachable LL | / match () { LL | | () => (), LL | | } - | |_____^ + | |_____^ unreachable expression error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index cee1459c79..e56176690a 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -1,17 +1,14 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/unsized-bare-typaram.rs:2:23 + --> $DIR/unsized-bare-typaram.rs:2:29 | +LL | fn bar() { } + | --- - required by this bound in `bar` LL | fn foo() { bar::() } - | ^^^^^^^^ doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `bar` - --> $DIR/unsized-bare-typaram.rs:1:1 - | -LL | fn bar() { } - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index 20857a1d65..dff934834e 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-enum.rs:6:36 | +LL | enum Foo { FooSome(U), FooNone } + | ----------- required by `Foo` +LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/unsized-enum.rs:4:1 - | -LL | enum Foo { FooSome(U), FooNone } - | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 98eecabc84..1a726bb089 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-inherent-impl-self-type.rs:7:17 | +LL | struct S5(Y); + | ---------------- required by `S5` +LL | LL | impl S5 { | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `S5` - --> $DIR/unsized-inherent-impl-self-type.rs:5:1 - | -LL | struct S5(Y); - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index 7add65c078..0d4776ff6c 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -1,21 +1,22 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:6:36 | +LL | struct Foo { data: T } + | ------------- required by `Foo` +LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/unsized-struct.rs:4:1 - | -LL | struct Foo { data: T } - | ^^^^^^^^^^^^^ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 | +LL | fn is_sized() { } + | -------- - required by this bound in `is_sized` +... LL | fn bar2() { is_sized::>() } | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -23,11 +24,6 @@ LL | fn bar2() { is_sized::>() } = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound = note: required because it appears within the type `Bar` -note: required by `is_sized` - --> $DIR/unsized-struct.rs:1:1 - | -LL | fn is_sized() { } - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index c39f3652b6..f399f8ded1 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-trait-impl-self-type.rs:10:17 | +LL | struct S5(Y); + | ---------------- required by `S5` +LL | LL | impl T3 for S5 { | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `S5` - --> $DIR/unsized-trait-impl-self-type.rs:8:1 - | -LL | struct S5(Y); - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index 2c7b86c5d8..c821a08f6b 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -1,54 +1,48 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:7:5 + --> $DIR/unsized3.rs:7:13 | LL | f2::(x); - | ^^^^^^^ doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time +... +LL | fn f2(x: &X) { + | -- - required by this bound in `f2` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `f2` - --> $DIR/unsized3.rs:10:1 - | -LL | fn f2(x: &X) { - | ^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:18:5 + --> $DIR/unsized3.rs:18:13 | LL | f4::(x); - | ^^^^^^^ doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time +... +LL | fn f4(x: &X) { + | -- - required by this bound in `f4` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `f4` - --> $DIR/unsized3.rs:21:1 - | -LL | fn f4(x: &X) { - | ^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:33:5 + --> $DIR/unsized3.rs:33:8 | +LL | fn f5(x: &Y) {} + | -- - required by this bound in `f5` +... LL | f5(x1); - | ^^ doesn't have a size known at compile-time + | ^^ doesn't have a size known at compile-time | = help: within `S`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` -note: required by `f5` - --> $DIR/unsized3.rs:24:1 - | -LL | fn f5(x: &Y) {} - | ^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:40:5 + --> $DIR/unsized3.rs:40:8 | LL | f5(&(*x1, 34)); - | ^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `S`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit @@ -70,21 +64,19 @@ LL | f5(&(32, *x1)); = note: tuples must have a statically known size to be initialized error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:45:5 + --> $DIR/unsized3.rs:45:8 | +LL | fn f5(x: &Y) {} + | -- - required by this bound in `f5` +... LL | f5(&(32, *x1)); - | ^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `({integer}, S)`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` = note: required because it appears within the type `({integer}, S)` -note: required by `f5` - --> $DIR/unsized3.rs:24:1 - | -LL | fn f5(x: &Y) {} - | ^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/vtable-res-trait-param.stderr b/src/test/ui/vtable-res-trait-param.stderr index 58a88979b2..bff6481326 100644 --- a/src/test/ui/vtable-res-trait-param.stderr +++ b/src/test/ui/vtable-res-trait-param.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `{integer}: TraitA` is not satisfied - --> $DIR/vtable-res-trait-param.rs:17:7 + --> $DIR/vtable-res-trait-param.rs:17:18 | LL | b.gimme_an_a(y) - | ^^^^^^^^^^ the trait `TraitA` is not implemented for `{integer}` + | ^ the trait `TraitA` is not implemented for `{integer}` error: aborting due to previous error diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr index 4df429259e..531aadc25d 100644 --- a/src/test/ui/wf/wf-const-type.stderr +++ b/src/test/ui/wf/wf-const-type.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied --> $DIR/wf-const-type.rs:10:12 | +LL | struct IsCopy { t: T } + | --------------------- required by `IsCopy` +... LL | const FOO: IsCopy> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy` | = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option` -note: required by `IsCopy` - --> $DIR/wf-const-type.rs:7:1 - | -LL | struct IsCopy { t: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr index de28a882f1..d5632f4a9c 100644 --- a/src/test/ui/wf/wf-enum-bound.stderr +++ b/src/test/ui/wf/wf-enum-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-enum-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / enum SomeEnum LL | | where T: ExtraCopy LL | | { @@ -9,11 +12,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-enum-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr index 6c1267cf7e..51ee23fc5a 100644 --- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-enum-fields-struct-variant.rs:13:9 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | f: IsCopy | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-enum-fields-struct-variant.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr index 9c4eec6c5f..5f4e7c66f5 100644 --- a/src/test/ui/wf/wf-enum-fields.stderr +++ b/src/test/ui/wf/wf-enum-fields.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-enum-fields.rs:12:17 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | SomeVariant(IsCopy) | ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-enum-fields.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index b50e895d86..4bc2e370f2 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-fn-where-clause.rs:8:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / fn foo() where T: ExtraCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-fn-where-clause.rs:6:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:1 diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr index 158b55a3f4..ceafb4f615 100644 --- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: MyHash` is not satisfied --> $DIR/wf-impl-associated-type-trait.rs:17:5 | +LL | pub struct MySet { + | -------------------------- required by `MySet` +... LL | type Bar = MySet; | ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T` | = help: consider adding a `where T: MyHash` bound -note: required by `MySet` - --> $DIR/wf-impl-associated-type-trait.rs:8:1 - | -LL | pub struct MySet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index 8635dad851..e7432f8198 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-arg.rs:10:1 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | / fn bar(_: &MustBeCopy) LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-arg.rs:6:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr index 3879f7b0a4..005ffe8450 100644 --- a/src/test/ui/wf/wf-in-fn-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-ret.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-ret.rs:10:1 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | / fn bar() -> MustBeCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-ret.rs:6:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr index 40cb4a7050..b4cd921040 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-type-arg.rs:9:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: fn(MustBeCopy) | ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-type-arg.rs:3:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr index 059f164e25..988fbed8e9 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-type-ret.rs:9:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: fn() -> MustBeCopy | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-type-ret.rs:3:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr index 1e732a3341..0af38ddcff 100644 --- a/src/test/ui/wf/wf-in-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-where-clause.rs:9:1 | +LL | trait MustBeCopy { + | ------------------------ required by `MustBeCopy` +... LL | / fn bar() LL | | where T: MustBeCopy LL | | { @@ -8,11 +11,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-where-clause.rs:6:1 - | -LL | trait MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr index 2c85dd042e..0f4b4e417c 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-obj-type-trait.rs:11:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: dyn Object> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-obj-type-trait.rs:5:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr index b79093f7d0..1e258864d0 100644 --- a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-inherent-impl-method-where-clause.rs:12:5 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +... LL | / fn foo(self) where T: ExtraCopy LL | | {} | |______^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-inherent-impl-method-where-clause.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr index f10ff841ac..4c389b3ef3 100644 --- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-inherent-impl-where-clause.rs:11:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +... LL | / impl Foo where T: ExtraCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-inherent-impl-where-clause.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index 3b264ecd58..0d8441f87e 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `A` cannot be made into an object --> $DIR/wf-object-safe.rs:9:13 | +LL | fn foo(&self, _x: &Self); + | --- method `foo` references the `Self` type in its parameters or return type +... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.stderr index f82526aa88..3ec90f0044 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.stderr @@ -105,4 +105,5 @@ LL | ::static_evil(b) error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0478`. +Some errors have detailed explanations: E0312, E0478. +For more information about an error, try `rustc --explain E0312`. diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr index 4234c7161b..05a628d7c3 100644 --- a/src/test/ui/wf/wf-static-type.stderr +++ b/src/test/ui/wf/wf-static-type.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | +LL | struct IsCopy { t: T } + | --------------------- required by `IsCopy` +... LL | static FOO: IsCopy> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy` | = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option` -note: required by `IsCopy` - --> $DIR/wf-static-type.rs:7:1 - | -LL | struct IsCopy { t: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr index 1fdcced90c..2028a0baa1 100644 --- a/src/test/ui/wf/wf-struct-bound.stderr +++ b/src/test/ui/wf/wf-struct-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-struct-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / struct SomeStruct LL | | where T: ExtraCopy LL | | { @@ -9,11 +12,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-struct-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr index e609f93ff7..d2bff25367 100644 --- a/src/test/ui/wf/wf-struct-field.stderr +++ b/src/test/ui/wf/wf-struct-field.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-struct-field.rs:12:5 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | data: IsCopy | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-struct-field.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr index 658d41218e..d5b2b5762a 100644 --- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-trait-associated-type-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait { LL | | type Type1: ExtraCopy; LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-associated-type-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr index 70fabcd4b3..d8ab955048 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `::Type1: std::marker::Copy` is not satisfied --> $DIR/wf-trait-associated-type-trait.rs:11:5 | +LL | struct IsCopy { x: T } + | --------------------- required by `IsCopy` +... LL | type Type2 = IsCopy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `::Type1` | = help: consider adding a `where ::Type1: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-trait-associated-type-trait.rs:7:1 - | -LL | struct IsCopy { x: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr index 5cc9451bf5..85f12b2de5 100644 --- a/src/test/ui/wf/wf-trait-bound.stderr +++ b/src/test/ui/wf/wf-trait-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-trait-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait LL | | where T: ExtraCopy LL | | { @@ -8,11 +11,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index e713389223..4d0e1f2f0f 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-arg.rs:11:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | / fn bar(&self, x: &Bar) { LL | | LL | | // @@ -9,11 +12,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-arg.rs:8:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr index 5a310a826d..e82b76b61c 100644 --- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-ret.rs:11:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | / fn bar(&self) -> Bar { LL | | LL | | // @@ -10,11 +13,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-ret.rs:8:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr index d5a00be6d3..6504f6698d 100644 --- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-where-clause.rs:11:5 | +LL | trait Bar { } + | ---------------------- required by `Bar` +... LL | / fn bar(&self) where A: Bar { LL | | LL | | // @@ -9,11 +12,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-where-clause.rs:8:1 - | -LL | trait Bar { } - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 2b26eac9c0..0887d4b2fc 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-arg.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self, x: &Bar); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-arg.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr index 70f07f02e9..5555081498 100644 --- a/src/test/ui/wf/wf-trait-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-fn-ret.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-ret.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self) -> &Bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-ret.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr index 2d6223e6d9..5e8fd89823 100644 --- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-where-clause.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self) where Self: Sized, Bar: Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-where-clause.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr index a3c4ab58f6..377ca64053 100644 --- a/src/test/ui/wf/wf-trait-superbound.stderr +++ b/src/test/ui/wf/wf-trait-superbound.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-trait-superbound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait: ExtraCopy { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-superbound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 125b65b187..727c9b8e06 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:9 + --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22 | +LL | fn require_copy(x: T) {} + | ------------ ---- required by this bound in `require_copy` +... LL | require_copy(self.x); - | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `require_copy` - --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:1 - | -LL | fn require_copy(x: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index eb555b181f..1c1937c307 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:9 + --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22 | +LL | fn require_copy(x: T) {} + | ------------ ---- required by this bound in `require_copy` +... LL | require_copy(self.x); - | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `require_copy` - --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:1 - | -LL | fn require_copy(x: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr index 60bcba09e9..6fd3872877 100644 --- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Bar: std::cmp::Eq` is not satisfied - --> $DIR/where-clauses-method-unsatisfied.rs:18:7 + --> $DIR/where-clauses-method-unsatisfied.rs:18:14 | LL | x.equals(&x); - | ^^^^^^ the trait `std::cmp::Eq` is not implemented for `Bar` + | ^^ the trait `std::cmp::Eq` is not implemented for `Bar` error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr index fb69e2d141..1c859ac648 100644 --- a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `Struct: std::cmp::Eq` is not satisfied --> $DIR/where-clauses-unsatisfied.rs:6:10 | +LL | fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } + | ----- -- required by this bound in `equal` +... LL | drop(equal(&Struct, &Struct)) | ^^^^^ the trait `std::cmp::Eq` is not implemented for `Struct` - | -note: required by `equal` - --> $DIR/where-clauses-unsatisfied.rs:1:1 - | -LL | fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index dbe68b82c2..b18b36d029 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,18 +1,16 @@ error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied --> $DIR/where-for-self-2.rs:21:5 | +LL | fn foo(x: &T) + | --- +LL | where for<'a> &'a T: Bar + | --- required by this bound in `foo` +... LL | foo(&X); | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` | = help: the following implementations were found: <&'static u32 as Bar> -note: required by `foo` - --> $DIR/where-for-self-2.rs:16:1 - | -LL | / fn foo(x: &T) -LL | | where for<'a> &'a T: Bar -LL | | {} - | |__^ error: aborting due to previous error diff --git a/src/test/ui/while-let.rs b/src/test/ui/while-let.rs index 69f9de9497..53babefae8 100644 --- a/src/test/ui/while-let.rs +++ b/src/test/ui/while-let.rs @@ -1,5 +1,6 @@ // run-pass +#[allow(dead_code)] fn macros() { macro_rules! foo{ ($p:pat, $e:expr, $b:block) => {{ @@ -12,16 +13,16 @@ fn macros() { }} } - foo!(a, 1, { //~ WARN irrefutable while-let + foo!(_a, 1, { //~ WARN irrefutable while-let println!("irrefutable pattern"); }); - bar!(a, 1, { //~ WARN irrefutable while-let + bar!(_a, 1, { //~ WARN irrefutable while-let println!("irrefutable pattern"); }); } pub fn main() { - while let a = 1 { //~ WARN irrefutable while-let + while let _a = 1 { //~ WARN irrefutable while-let println!("irrefutable pattern"); break; } diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr index 348925aa97..30307ecaea 100644 --- a/src/test/ui/while-let.stderr +++ b/src/test/ui/while-let.stderr @@ -1,10 +1,10 @@ warning: irrefutable while-let pattern - --> $DIR/while-let.rs:6:13 + --> $DIR/while-let.rs:7:13 | LL | while let $p = $e $b | ^^^^^ ... -LL | / foo!(a, 1, { +LL | / foo!(_a, 1, { LL | | println!("irrefutable pattern"); LL | | }); | |_______- in this macro invocation @@ -12,20 +12,20 @@ LL | | }); = note: `#[warn(irrefutable_let_patterns)]` on by default warning: irrefutable while-let pattern - --> $DIR/while-let.rs:6:13 + --> $DIR/while-let.rs:7:13 | LL | while let $p = $e $b | ^^^^^ ... -LL | / bar!(a, 1, { +LL | / bar!(_a, 1, { LL | | println!("irrefutable pattern"); LL | | }); | |_______- in this macro invocation warning: irrefutable while-let pattern - --> $DIR/while-let.rs:24:5 + --> $DIR/while-let.rs:25:5 | -LL | / while let a = 1 { +LL | / while let _a = 1 { LL | | println!("irrefutable pattern"); LL | | break; LL | | } diff --git a/src/test/ui/wrapping-int-combinations.rs b/src/test/ui/wrapping-int-combinations.rs new file mode 100644 index 0000000000..f0bc479ee0 --- /dev/null +++ b/src/test/ui/wrapping-int-combinations.rs @@ -0,0 +1,77 @@ +// run-pass + +use std::num::Wrapping; + +macro_rules! wrapping_operation { + ($result:expr, $lhs:ident $op:tt $rhs:expr) => { + assert_eq!($result, $lhs $op $rhs); + assert_eq!($result, &$lhs $op $rhs); + assert_eq!($result, $lhs $op &$rhs); + assert_eq!($result, &$lhs $op &$rhs); + }; + ($result:expr, $op:tt $expr:expr) => { + assert_eq!($result, $op $expr); + assert_eq!($result, $op &$expr); + }; +} + +macro_rules! wrapping_assignment { + ($result:expr, $lhs:ident $op:tt $rhs:expr) => { + let mut lhs1 = $lhs; + lhs1 $op $rhs; + assert_eq!($result, lhs1); + + let mut lhs2 = $lhs; + lhs2 $op &$rhs; + assert_eq!($result, lhs2); + }; +} + +macro_rules! wrapping_test { + ($type:ty, $min:expr, $max:expr) => { + let zero: Wrapping<$type> = Wrapping(0); + let one: Wrapping<$type> = Wrapping(1); + let min: Wrapping<$type> = Wrapping($min); + let max: Wrapping<$type> = Wrapping($max); + + wrapping_operation!(min, max + one); + wrapping_assignment!(min, max += one); + wrapping_operation!(max, min - one); + wrapping_assignment!(max, min -= one); + wrapping_operation!(max, max * one); + wrapping_assignment!(max, max *= one); + wrapping_operation!(max, max / one); + wrapping_assignment!(max, max /= one); + wrapping_operation!(zero, max % one); + wrapping_assignment!(zero, max %= one); + wrapping_operation!(zero, zero & max); + wrapping_assignment!(zero, zero &= max); + wrapping_operation!(max, zero | max); + wrapping_assignment!(max, zero |= max); + wrapping_operation!(zero, max ^ max); + wrapping_assignment!(zero, max ^= max); + wrapping_operation!(zero, zero << 1usize); + wrapping_assignment!(zero, zero <<= 1usize); + wrapping_operation!(zero, zero >> 1usize); + wrapping_assignment!(zero, zero >>= 1usize); + wrapping_operation!(zero, -zero); + wrapping_operation!(max, !min); + }; +} + +fn main() { + wrapping_test!(i8, std::i8::MIN, std::i8::MAX); + wrapping_test!(i16, std::i16::MIN, std::i16::MAX); + wrapping_test!(i32, std::i32::MIN, std::i32::MAX); + wrapping_test!(i64, std::i64::MIN, std::i64::MAX); + #[cfg(not(target_os = "emscripten"))] + wrapping_test!(i128, std::i128::MIN, std::i128::MAX); + wrapping_test!(isize, std::isize::MIN, std::isize::MAX); + wrapping_test!(u8, std::u8::MIN, std::u8::MAX); + wrapping_test!(u16, std::u16::MIN, std::u16::MAX); + wrapping_test!(u32, std::u32::MIN, std::u32::MAX); + wrapping_test!(u64, std::u64::MIN, std::u64::MAX); + #[cfg(not(target_os = "emscripten"))] + wrapping_test!(u128, std::u128::MIN, std::u128::MAX); + wrapping_test!(usize, std::usize::MIN, std::usize::MAX); +} diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 63b6399bb9..c364479d8d 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -5,5 +5,5 @@ authors = ["Alex Crichton "] edition = "2018" [dependencies] -toml = "0.4" +toml = "0.5" serde = { version = "1.0", features = ["derive"] } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9ffa9391c8..f41e7dd17e 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -1,3 +1,11 @@ +//! Build a dist manifest, hash and sign everything. +//! This gets called by `promote-release` +//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release) +//! via `x.py dist hash-and-sign`; the cmdline arguments are set up +//! by rustbuild (in `src/bootstrap/dist.rs`). + +#![deny(warnings)] + use toml; use serde::Serialize; @@ -270,6 +278,7 @@ fn main() { // Do not ask for a passphrase while manually testing let mut passphrase = String::new(); if should_sign { + // `x.py` passes the passphrase via stdin. t!(io::stdin().read_to_string(&mut passphrase)); } @@ -362,6 +371,7 @@ impl Builder { } } + /// Hash all files, compute their signatures, and collect the hashes in `self.digests`. fn digest_and_sign(&mut self) { for file in t!(self.input.read_dir()).map(|e| t!(e).path()) { let filename = file.file_name().unwrap().to_str().unwrap(); @@ -532,19 +542,20 @@ impl Builder { .as_ref() .cloned() .map(|version| (version, true)) - .unwrap_or_default(); + .unwrap_or_default(); // `is_present` defaults to `false` here. - // miri needs to build std with xargo, which doesn't allow stable/beta: - // + // Miri is nightly-only; never ship it for other trains. if pkgname == "miri-preview" && self.rust_release != "nightly" { - is_present = false; // ignore it + is_present = false; // Pretend the component is entirely missing. } let targets = targets.iter().map(|name| { if is_present { + // The component generally exists, but it might still be missing for this target. let filename = self.filename(pkgname, name); let digest = match self.digests.remove(&filename) { Some(digest) => digest, + // This component does not exist for this target -- skip it. None => return (name.to_string(), Target::unavailable()), }; let xz_filename = filename.replace(".tar.gz", ".tar.xz"); diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index f6aaaa5c6e..1a42e0cac3 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -1,3 +1,5 @@ +#![deny(warnings)] + use std::env; use std::process::Command; use std::path::{Path, PathBuf}; diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index e759ad1f35..745233c151 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] diff = "0.1.10" -env_logger = { version = "0.5", default-features = false } +env_logger = { version = "0.6", default-features = false } getopts = "0.2" log = "0.4" regex = "1.0" diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 66e030e979..edb9eb7d86 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -333,10 +333,12 @@ pub fn expected_output_path( testpaths.file.with_extension(extension) } -pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED]; +pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; pub const UI_FIXED: &str = "fixed"; +pub const UI_RUN_STDERR: &str = "run.stderr"; +pub const UI_RUN_STDOUT: &str = "run.stdout"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 076ad87c70..48dd68d0f6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -137,6 +137,11 @@ impl EarlyProps { config.parse_needs_sanitizer_support(ln) { props.ignore = Ignore::Ignore; } + + if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) { + props.ignore = Ignore::Ignore; + } + } if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && @@ -326,6 +331,8 @@ pub struct TestProps { pub force_host: bool, // Check stdout for error-pattern output as well as stderr pub check_stdout: bool, + // Check stdout & stderr for output of run-pass test + pub check_run_results: bool, // For UI tests, allows compiler to generate arbitrary output to stdout pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr @@ -388,6 +395,7 @@ impl TestProps { build_aux_docs: false, force_host: false, check_stdout: false, + check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, no_prefer_dynamic: false, @@ -468,6 +476,10 @@ impl TestProps { self.check_stdout = config.parse_check_stdout(ln); } + if !self.check_run_results { + self.check_run_results = config.parse_check_run_results(ln); + } + if !self.dont_check_compiler_stdout { self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln); } @@ -616,6 +628,11 @@ impl TestProps { } self.pass_mode } + + // does not consider CLI override for pass mode + pub fn local_pass_mode(&self) -> Option { + self.pass_mode + } } fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) { @@ -712,6 +729,10 @@ impl Config { self.parse_name_directive(line, "check-stdout") } + fn parse_check_run_results(&self, line: &str) -> bool { + self.parse_name_directive(line, "check-run-results") + } + fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool { self.parse_name_directive(line, "dont-check-compiler-stdout") } @@ -819,10 +840,10 @@ impl Config { if name == "test" || util::matches_os(&self.target, name) || // target + util::matches_env(&self.target, name) || // env name == util::get_arch(&self.target) || // architecture name == util::get_pointer_width(&self.target) || // pointer width name == self.stage_id.split('-').next().unwrap() || // stage - Some(name) == util::get_env(&self.target) || // env (self.target != self.host && name == "cross-compile") || match self.compare_mode { Some(CompareMode::Nll) => name == "compare-mode-nll", diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index bde49ff391..34435819a2 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,6 +1,7 @@ #![crate_name = "compiletest"] #![feature(test)] #![feature(vec_remove_item)] +#![deny(warnings)] extern crate test; @@ -253,7 +254,7 @@ pub fn parse_config(args: Vec) -> Config { if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); println!("{}", opts.usage(&message)); - println!(""); + println!(); panic!() } @@ -265,7 +266,7 @@ pub fn parse_config(args: Vec) -> Config { if matches.opt_present("h") || matches.opt_present("help") { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); println!("{}", opts.usage(&message)); - println!(""); + println!(); panic!() } @@ -335,7 +336,7 @@ pub fn parse_config(args: Vec) -> Config { runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), - target: target, + target, host: opt_str2(matches.opt_str("host")), cdb, gdb, @@ -345,7 +346,7 @@ pub fn parse_config(args: Vec) -> Config { lldb_native_rust, llvm_version: matches.opt_str("llvm-version"), system_llvm: matches.opt_present("system-llvm"), - android_cross_path: android_cross_path, + android_cross_path, adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), adb_device_status: opt_str2(matches.opt_str("target")).contains("android") diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 05cfdf1ce5..baed27dd15 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2,6 +2,7 @@ use crate::common::{CompareMode, PassMode}; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; +use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; use crate::common::{Codegen, CodegenUnits, Rustdoc}; use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb}; @@ -288,6 +289,11 @@ enum ReadFrom { Stdin(String), } +enum TestOutput { + Compile, + Run, +} + impl<'test> TestCx<'test> { /// Code executed for each revision in turn (or, if there are no /// revisions, exactly once, with revision == None). @@ -1551,7 +1557,11 @@ impl<'test> TestCx<'test> { // want to actually assert warnings about all this code. Instead // let's just ignore unused code warnings by defaults and tests // can turn it back on if needed. - if !self.config.src_base.ends_with("rustdoc-ui") { + if !self.config.src_base.ends_with("rustdoc-ui") && + // Note that we don't call pass_mode() here as we don't want + // to set unused to allow if we've overriden the pass mode + // via command line flags. + self.props.local_pass_mode() != Some(PassMode::Run) { rustc.args(&["-A", "unused"]); } } @@ -1603,11 +1613,7 @@ impl<'test> TestCx<'test> { .args(&self.props.compile_flags); if let Some(ref linker) = self.config.linker { - rustdoc - .arg("--linker") - .arg(linker) - .arg("-Z") - .arg("unstable-options"); + rustdoc.arg(format!("-Clinker={}", linker)); } self.compose_and_run_compiler(rustdoc, None) @@ -1659,10 +1665,10 @@ impl<'test> TestCx<'test> { _ if self.config.target.contains("vxworks") => { let aux_dir = self.aux_output_dir_name(); let ProcArgs { prog, args } = self.make_run_args(); - let mut vx_run = Command::new("vx-run"); - vx_run.args(&[&prog]).args(args).envs(env.clone()); + let mut wr_run = Command::new("wr-run"); + wr_run.args(&[&prog]).args(args).envs(env.clone()); self.compose_and_run( - vx_run, + wr_run, self.config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), None, @@ -1725,6 +1731,21 @@ impl<'test> TestCx<'test> { } } + fn is_vxworks_pure_static(&self) -> bool { + if self.config.target.contains("vxworks") { + match env::var("RUST_VXWORKS_TEST_DYLINK") { + Ok(s) => s != "1", + _ => true + } + } else { + false + } + } + + fn is_vxworks_pure_dynamic(&self) -> bool { + self.config.target.contains("vxworks") && !self.is_vxworks_pure_static() + } + fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { let aux_dir = self.aux_output_dir_name(); @@ -1768,6 +1789,7 @@ impl<'test> TestCx<'test> { && !self.config.host.contains("musl")) || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") + || self.is_vxworks_pure_static() { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -1999,7 +2021,8 @@ impl<'test> TestCx<'test> { } if !is_rustdoc { - if self.config.target == "wasm32-unknown-unknown" { + if self.config.target == "wasm32-unknown-unknown" + || self.is_vxworks_pure_static() { // rustc.arg("-g"); // get any backtrace at all on errors } else if !self.props.no_prefer_dynamic { rustc.args(&["-C", "prefer-dynamic"]); @@ -2044,7 +2067,8 @@ impl<'test> TestCx<'test> { } // Use dynamic musl for tests because static doesn't allow creating dylibs - if self.config.host.contains("musl") { + if self.config.host.contains("musl") + || self.is_vxworks_pure_dynamic() { rustc.arg("-Ctarget-feature=-crt-static"); } @@ -2569,7 +2593,7 @@ impl<'test> TestCx<'test> { " actual: {}", codegen_units_to_str(&actual_item.codegen_units) ); - println!(""); + println!(); } } @@ -2934,6 +2958,61 @@ impl<'test> TestCx<'test> { } } + fn load_compare_outputs(&self, proc_res: &ProcRes, + output_kind: TestOutput, explicit_format: bool) -> usize { + + let (stderr_kind, stdout_kind) = match output_kind { + TestOutput::Compile => (UI_STDERR, UI_STDOUT), + TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT) + }; + + let expected_stderr = self.load_expected_output(stderr_kind); + let expected_stdout = self.load_expected_output(stdout_kind); + + let normalized_stdout = match output_kind { + TestOutput::Run if self.config.remote_test_client.is_some() => { + // When tests are run using the remote-test-client, the string + // 'uploaded "$TEST_BUILD_DIR/, waiting for result"' + // is printed to stdout by the client and then captured in the ProcRes, + // so it needs to be removed when comparing the run-pass test execution output + lazy_static! { + static ref REMOTE_TEST_RE: Regex = Regex::new( + "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-]+)+\", waiting for result\n" + ).unwrap(); + } + REMOTE_TEST_RE.replace( + &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), + "" + ).to_string() + } + _ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout) + }; + + let stderr = if explicit_format { + proc_res.stderr.clone() + } else { + json::extract_rendered(&proc_res.stderr) + }; + + let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); + let mut errors = 0; + match output_kind { + TestOutput::Compile => { + if !self.props.dont_check_compiler_stdout { + errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); + } + if !self.props.dont_check_compiler_stderr { + errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + } + } + TestOutput::Run => { + errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + } + } + errors + } + fn run_ui_test(&self) { // if the user specified a format in the ui test // print the output to the stderr file, otherwise extract @@ -2946,32 +3025,13 @@ impl<'test> TestCx<'test> { let proc_res = self.compile_test(); self.check_if_test_should_compile(&proc_res); - let expected_stderr = self.load_expected_output(UI_STDERR); - let expected_stdout = self.load_expected_output(UI_STDOUT); let expected_fixed = self.load_expected_output(UI_FIXED); - let normalized_stdout = - self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); - - let stderr = if explicit { - proc_res.stderr.clone() - } else { - json::extract_rendered(&proc_res.stderr) - }; - - let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); - - let mut errors = 0; - if !self.props.dont_check_compiler_stdout { - errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); - } - if !self.props.dont_check_compiler_stderr { - errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); - } - let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); + let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit); + if self.config.compare_mode.is_some() { // don't test rustfix with nll right now } else if self.config.rustfix_coverage { @@ -3049,7 +3109,17 @@ impl<'test> TestCx<'test> { if self.should_run_successfully() { let proc_res = self.exec_compiled_test(); - + let run_output_errors = if self.props.check_run_results { + self.load_compare_outputs(&proc_res, TestOutput::Run, explicit) + } else { + 0 + }; + if run_output_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occured comparing run output.", run_output_errors), + &proc_res, + ); + } if !proc_res.status.success() { self.fatal_proc_rec("test run failed!", &proc_res); } @@ -3456,7 +3526,7 @@ impl<'test> TestCx<'test> { } } } - println!(""); + println!(); } } } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 56ebea7c20..3a2ee44508 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -105,8 +105,12 @@ pub fn get_arch(triple: &str) -> &'static str { panic!("Cannot determine Architecture from triple"); } -pub fn get_env(triple: &str) -> Option<&str> { - triple.split('-').nth(3) +pub fn matches_env(triple: &str, name: &str) -> bool { + if let Some(env) = triple.split('-').nth(3) { + env.starts_with(name) + } else { + false + } } pub fn get_pointer_width(triple: &str) -> &'static str { diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index 116be234f3..992af261b8 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -3,10 +3,14 @@ authors = ["The Rust Project Developers"] name = "error_index_generator" version = "0.0.0" edition = "2018" +build = "build.rs" [dependencies] rustdoc = { path = "../../librustdoc" } +[build-dependencies] +walkdir = "2" + [[bin]] name = "error_index_generator" path = "main.rs" diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs new file mode 100644 index 0000000000..592b3f14c8 --- /dev/null +++ b/src/tools/error_index_generator/build.rs @@ -0,0 +1,57 @@ +use walkdir::WalkDir; +use std::path::PathBuf; +use std::{env, fs}; + +fn main() { + // The src directory (we are in src/tools/error_index_generator) + // Note that we could skip one of the .. but this ensures we at least loosely find the right + // directory. + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let dest = out_dir.join("error_codes.rs"); + let mut idx = 0; + for entry in WalkDir::new("../../../src") { + let entry = entry.unwrap(); + if entry.file_name() == "error_codes.rs" { + println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap()); + let file = fs::read_to_string(entry.path()).unwrap() + .replace("syntax::register_diagnostics!", "register_diagnostics!"); + let contents = format!("(|| {{\n{}\n}})();", file); + + fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap(); + + idx += 1; + } + } + + let mut all = String::new(); + all.push_str(r###" +fn register_all() -> Vec<(&'static str, Option<&'static str>)> { + let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); + macro_rules! register_diagnostics { + ($($ecode:ident: $message:expr,)*) => ( + register_diagnostics!{$($ecode:$message,)* ;} + ); + + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + $( + {long_codes.extend([ + (stringify!($ecode), Some($message)), + ].iter());} + )* + $( + {long_codes.extend([ + stringify!($code), + ].iter().cloned().map(|s| (s, None)).collect::>());} + )* + ) + } +"###); + for idx in 0..idx { + all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx)); + all.push_str("\n"); + } + all.push_str("\nlong_codes\n"); + all.push_str("}\n"); + + fs::write(&dest, all).unwrap(); +} diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index a9d1d9997f..31a802706c 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,23 +1,28 @@ #![feature(rustc_private)] +#![deny(warnings)] extern crate env_logger; extern crate syntax; -extern crate serialize as rustc_serialize; use std::collections::BTreeMap; use std::env; use std::error::Error; -use std::fs::{self, read_dir, File}; +use std::fs::File; use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::cell::RefCell; use syntax::edition::DEFAULT_EDITION; -use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, Playground}; -use rustc_serialize::json; + +pub struct ErrorMetadata { + pub description: Option, +} + +/// Mapping from error codes to metadata that can be (de)serialized. +pub type ErrorMetadataMap = BTreeMap; enum OutputFormat { HTML(HTMLFormatter), @@ -80,11 +85,7 @@ impl Formatter for HTMLFormatter { Some(_) => "error-described", None => "error-undescribed", }; - let use_desc = match info.use_site { - Some(_) => "error-used", - None => "error-unused", - }; - write!(output, "

", desc_desc, use_desc)?; + write!(output, "
", desc_desc)?; // Error title (with self-link). write!(output, @@ -199,25 +200,6 @@ impl Formatter for MarkdownFormatter { } } -/// Loads all the metadata files from `metadata_dir` into an in-memory map. -fn load_all_errors(metadata_dir: &Path) -> Result> { - let mut all_errors = BTreeMap::new(); - - for entry in read_dir(metadata_dir)? { - let path = entry?.path(); - - let metadata_str = fs::read_to_string(&path)?; - - let some_errors: ErrorMetadataMap = json::decode(&metadata_str)?; - - for (err_code, info) in some_errors { - all_errors.insert(err_code, info); - } - } - - Ok(all_errors) -} - /// Output an HTML page for the errors in `err_map` to `output_path`. fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path, formatter: T) -> Result<(), Box> { @@ -234,9 +216,13 @@ fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Pat } fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box> { - let build_arch = env::var("CFG_BUILD")?; - let metadata_dir = get_metadata_dir(&build_arch); - let err_map = load_all_errors(&metadata_dir)?; + let long_codes = register_all(); + let mut err_map = BTreeMap::new(); + for (code, desc) in long_codes { + err_map.insert(code.to_string(), ErrorMetadata { + description: desc.map(String::from), + }); + } match format { OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s), OutputFormat::HTML(h) => render_error_page(&err_map, dst, h)?, @@ -272,3 +258,5 @@ fn main() { panic!("{}", e.description()); } } + +include!(concat!(env!("OUT_DIR"), "/error_codes.rs")); diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 49c149afe1..e8a7252cb7 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -14,6 +14,8 @@ //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc, //! but this should catch the majority of "broken link" cases. +#![deny(warnings)] + use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::env; diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index b8dcba3afc..7cf3cc7663 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -7,6 +7,8 @@ ## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts ## when a new commit lands on `master` (i.e., after it passed all checks on `auto`). +from __future__ import print_function + import sys import re import os @@ -20,21 +22,26 @@ except ImportError: import urllib.request as urllib2 # List of people to ping when the status of a tool or a book changed. +# These should be collaborators of the rust-lang/rust repository (with at least +# read privileges on it). CI will fail otherwise. MAINTAINERS = { - 'miri': '@oli-obk @RalfJung @eddyb', - 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch', - 'rls': '@Xanewok', - 'rustfmt': '@topecongiro', - 'book': '@carols10cents @steveklabnik', - 'nomicon': '@frewsxcv @Gankro', - 'reference': '@steveklabnik @Havvy @matthewjasper @ehuss', - 'rust-by-example': '@steveklabnik @marioidival @projektir', - 'embedded-book': ( - '@adamgreig @andre-richter @jamesmunns @korken89 ' - '@ryankurte @thejpster @therealprof' - ), - 'edition-guide': '@ehuss @Centril @steveklabnik', - 'rustc-guide': '@mark-i-m @spastorino' + 'miri': {'oli-obk', 'RalfJung', 'eddyb'}, + 'clippy-driver': { + 'Manishearth', 'llogiq', 'mcarton', 'oli-obk', 'phansch', 'flip1995', + 'yaahc', + }, + 'rls': {'Xanewok'}, + 'rustfmt': {'topecongiro'}, + 'book': {'carols10cents', 'steveklabnik'}, + 'nomicon': {'frewsxcv', 'Gankra'}, + 'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'}, + 'rust-by-example': {'steveklabnik', 'marioidival'}, + 'embedded-book': { + 'adamgreig', 'andre-richter', 'jamesmunns', 'korken89', + 'ryankurte', 'thejpster', 'therealprof', + }, + 'edition-guide': {'ehuss', 'Centril', 'steveklabnik'}, + 'rustc-guide': {'mark-i-m', 'spastorino', 'amanjeev'}, } REPOS = { @@ -52,6 +59,50 @@ REPOS = { } +def validate_maintainers(repo, github_token): + '''Ensure all maintainers are assignable on a GitHub repo''' + next_link_re = re.compile(r'<([^>]+)>; rel="next"') + + # Load the list of assignable people in the GitHub repo + assignable = [] + url = 'https://api.github.com/repos/%s/collaborators?per_page=100' % repo + while url is not None: + response = urllib2.urlopen(urllib2.Request(url, headers={ + 'Authorization': 'token ' + github_token, + # Properly load nested teams. + 'Accept': 'application/vnd.github.hellcat-preview+json', + })) + assignable.extend(user['login'] for user in json.load(response)) + # Load the next page if available + url = None + link_header = response.headers.get('Link') + if link_header: + matches = next_link_re.match(link_header) + if matches is not None: + url = matches.group(1) + + errors = False + for tool, maintainers in MAINTAINERS.items(): + for maintainer in maintainers: + if maintainer not in assignable: + errors = True + print( + "error: %s maintainer @%s is not assignable in the %s repo" + % (tool, maintainer, repo), + ) + + if errors: + print() + print(" To be assignable, a person needs to be explicitly listed as a") + print(" collaborator in the repository settings. The simple way to") + print(" fix this is to ask someone with 'admin' privileges on the repo") + print(" to add the person or whole team as a collaborator with 'read'") + print(" privileges. Those privileges don't grant any extra permissions") + print(" so it's safe to apply them.") + print() + print("The build will fail due to this.") + exit(1) + def read_current_status(current_commit, path): '''Reads build status of `current_commit` from content of `history/*.tsv` ''' @@ -73,13 +124,12 @@ def maybe_delink(message): def issue( tool, status, - maintainers, + assignees, relevant_pr_number, relevant_pr_user, pr_reviewer, ): # Open an issue about the toolstate failure. - assignees = [x.strip() for x in maintainers.split('@') if x != ''] if status == 'test-fail': status_description = 'has failing tests' else: @@ -100,7 +150,7 @@ def issue( REPOS.get(tool), relevant_pr_user, pr_reviewer )), 'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number), - 'assignees': assignees, + 'assignees': list(assignees), 'labels': ['T-compiler', 'I-nominated'], }) print("Creating issue:\n{}".format(request)) @@ -150,22 +200,32 @@ def update_latest( old = status[os] new = s.get(tool, old) status[os] = new - if new > old: # comparing the strings, but they are ordered appropriately! + maintainers = ' '.join('@'+name for name in MAINTAINERS[tool]) + # comparing the strings, but they are ordered appropriately: + # "test-pass" > "test-fail" > "build-fail" + if new > old: # things got fixed or at least the status quo improved changed = True message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ - .format(tool, os, old, new, MAINTAINERS.get(tool)) + .format(tool, os, old, new, maintainers) elif new < old: # tests or builds are failing and were not failing before changed = True title = '💔 {} on {}: {} → {}' \ .format(tool, os, old, new) message += '{} (cc {}, @rust-lang/infra).\n' \ - .format(title, MAINTAINERS.get(tool)) - # Most tools only create issues for build failures. - # Other failures can be spurious. - if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'): - create_issue_for_status = new + .format(title, maintainers) + # See if we need to create an issue. + if tool == 'miri': + # Create issue if tests used to pass before. Don't open a *second* + # issue when we regress from "test-fail" to "build-fail". + if old == 'test-pass': + create_issue_for_status = new + else: + # Create issue if things no longer build. + # (No issue for mere test failures to avoid spurious issues.) + if new == 'build-fail': + create_issue_for_status = new if create_issue_for_status is not None: try: @@ -200,6 +260,16 @@ def update_latest( if __name__ == '__main__': + repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO') + if repo: + github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN') + if github_token: + validate_maintainers(repo, github_token) + else: + print('skipping toolstate maintainers validation since no GitHub token is present') + # When validating maintainers don't run the full script. + exit(0) + cur_commit = sys.argv[1] cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') cur_commit_msg = sys.argv[2] diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 95530b210a..d5dc9a79b5 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -1,18 +1,19 @@ -use clap::{crate_version}; +use clap::crate_version; use std::env; use std::path::{Path, PathBuf}; -use clap::{App, ArgMatches, SubCommand, AppSettings}; +use clap::{App, AppSettings, ArgMatches, SubCommand}; +use mdbook::errors::Result as Result3; use mdbook::MDBook; -use mdbook::errors::{Result as Result3}; +#[cfg(feature = "linkcheck")] +use failure::Error; #[cfg(feature = "linkcheck")] use mdbook::renderer::RenderContext; #[cfg(feature = "linkcheck")] use mdbook_linkcheck::{self, errors::BrokenLinks}; -use failure::Error; fn main() { let d_message = "-d, --dest-dir=[dest-dir] @@ -21,18 +22,22 @@ fn main() { 'A directory for your book{n}(Defaults to Current Directory when omitted)'"; let matches = App::new("rustbook") - .about("Build a book with mdBook") - .author("Steve Klabnik ") - .version(&*format!("v{}", crate_version!())) - .setting(AppSettings::SubcommandRequired) - .subcommand(SubCommand::with_name("build") - .about("Build the book from the markdown files") - .arg_from_usage(d_message) - .arg_from_usage(dir_message)) - .subcommand(SubCommand::with_name("linkcheck") - .about("Run linkcheck with mdBook 3") - .arg_from_usage(dir_message)) - .get_matches(); + .about("Build a book with mdBook") + .author("Steve Klabnik ") + .version(&*format!("v{}", crate_version!())) + .setting(AppSettings::SubcommandRequired) + .subcommand( + SubCommand::with_name("build") + .about("Build the book from the markdown files") + .arg_from_usage(d_message) + .arg_from_usage(dir_message), + ) + .subcommand( + SubCommand::with_name("linkcheck") + .about("Run linkcheck with mdBook 3") + .arg_from_usage(dir_message), + ) + .get_matches(); // Check which subcomamnd the user ran... match matches.subcommand() { @@ -46,23 +51,44 @@ fn main() { ::std::process::exit(101); } - }, + } ("linkcheck", Some(sub_matches)) => { - if let Err(err) = linkcheck(sub_matches) { - eprintln!("Error: {}", err); - - #[cfg(feature = "linkcheck")] - { - if let Ok(broken_links) = err.downcast::() { - for cause in broken_links.links().iter() { - eprintln!("\tCaused By: {}", cause); - } + #[cfg(feature = "linkcheck")] + { + if let Err(err) = linkcheck(sub_matches) { + eprintln!("Error: {}", err); + + // HACK: ignore timeouts + let actually_broken = err + .downcast::() + .map(|broken_links| { + broken_links + .links() + .iter() + .inspect(|cause| eprintln!("\tCaused By: {}", cause)) + .fold(false, |already_broken, cause| { + already_broken || !format!("{}", cause).contains("timed out") + }) + }) + .unwrap_or(false); + + if actually_broken { + std::process::exit(101); + } else { + std::process::exit(0); } } + } - ::std::process::exit(101); + #[cfg(not(feature = "linkcheck"))] + { + // This avoids the `unused_binding` lint. + println!( + "mdbook-linkcheck is disabled, but arguments were passed: {:?}", + sub_matches + ); } - }, + } (_, _) => unreachable!(), }; } @@ -77,12 +103,6 @@ pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> { mdbook_linkcheck::check_links(&render_ctx) } -#[cfg(not(feature = "linkcheck"))] -pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> { - println!("mdbook-linkcheck is disabled."); - Ok(()) -} - // Build command implementation pub fn build(args: &ArgMatches<'_>) -> Result3<()> { let book_dir = get_book_dir(args); diff --git a/src/tools/rustc-std-workspace-alloc/Cargo.toml b/src/tools/rustc-std-workspace-alloc/Cargo.toml index ef7dc812af..9e04b14756 100644 --- a/src/tools/rustc-std-workspace-alloc/Cargo.toml +++ b/src/tools/rustc-std-workspace-alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc-std-workspace-alloc" -version = "1.0.0" +version = "1.99.0" authors = ["Alex Crichton "] license = 'MIT OR Apache-2.0' description = """ diff --git a/src/tools/rustc-std-workspace-core/Cargo.toml b/src/tools/rustc-std-workspace-core/Cargo.toml index 38ca56a557..6b4e7540af 100644 --- a/src/tools/rustc-std-workspace-core/Cargo.toml +++ b/src/tools/rustc-std-workspace-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc-std-workspace-core" -version = "1.0.0" +version = "1.99.0" authors = ["Alex Crichton "] license = 'MIT OR Apache-2.0' description = """ diff --git a/src/tools/rustc-std-workspace-std/Cargo.toml b/src/tools/rustc-std-workspace-std/Cargo.toml new file mode 100644 index 0000000000..e41554b74a --- /dev/null +++ b/src/tools/rustc-std-workspace-std/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rustc-std-workspace-std" +version = "1.99.0" +authors = ["Alex Crichton "] +license = 'MIT OR Apache-2.0' +description = """ +Hack for the compiler's own build system +""" +edition = "2018" + +[lib] +path = "lib.rs" + +[dependencies] +std = { path = "../../libstd" } diff --git a/src/tools/rustc-std-workspace-std/README.md b/src/tools/rustc-std-workspace-std/README.md new file mode 100644 index 0000000000..2228907f30 --- /dev/null +++ b/src/tools/rustc-std-workspace-std/README.md @@ -0,0 +1,3 @@ +# The `rustc-std-workspace-std` crate + +See documentation for the `rustc-std-workspace-core` crate. diff --git a/src/tools/rustc-std-workspace-std/lib.rs b/src/tools/rustc-std-workspace-std/lib.rs new file mode 100644 index 0000000000..f40d09cafb --- /dev/null +++ b/src/tools/rustc-std-workspace-std/lib.rs @@ -0,0 +1 @@ +pub use std::*; diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 4ce411223d..980c975376 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -14,12 +14,6 @@ path = "lib.rs" # For documentation about what this is and why in the world these dependencies # are appearing, see `README.md`. -[build-dependencies] -# Currently Cargo/RLS depend on `failure` which depends on `synstructure` which -# enables this feature. Clippy, however, does not depend on anything that -# enables this feature. Enable it unconditionally. -syn = { version = "0.15", features = ['extra-traits'] } - [target.'cfg(windows)'.dependencies.winapi] version = "0.3" features = [ @@ -65,14 +59,10 @@ features = [ [dependencies] curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } crossbeam-utils = { version = "0.6.5", features = ["nightly"] } -parking_lot = { version = "0.7", features = ['nightly'] } -rand = { version = "0.6.1", features = ["i128_support"] } serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value"] } smallvec = { version = "0.6", features = ['union', 'may_dangle'] } -scopeguard = { version = "0.3.3", features = ["use_std", "default"] } -byteorder = { version = "1.2.7", features = ["i128"] } -syn = { version = "0.15.35", features = ["extra-traits", "full"] } +url = { version = "2.0", features = ['serde'] } [target.'cfg(not(windows))'.dependencies] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index de54eb8f57..1ed39f45d3 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -15,6 +15,7 @@ const LICENSES: &[&str] = &[ "Apache-2.0 / MIT", "MIT OR Apache-2.0", "Apache-2.0 OR MIT", + "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license "MIT", "Unlicense/MIT", "Unlicense OR MIT", @@ -90,15 +91,18 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("crossbeam-epoch"), Crate("crossbeam-utils"), Crate("datafrog"), + Crate("dlmalloc"), Crate("either"), Crate("ena"), Crate("env_logger"), Crate("filetime"), Crate("flate2"), + Crate("fortanix-sgx-abi"), Crate("fuchsia-zircon"), Crate("fuchsia-zircon-sys"), Crate("getopts"), Crate("getrandom"), + Crate("hashbrown"), Crate("humantime"), Crate("indexmap"), Crate("itertools"), @@ -159,6 +163,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("termcolor"), Crate("terminon"), Crate("termion"), + Crate("term_size"), Crate("thread_local"), Crate("ucd-util"), Crate("unicode-width"), @@ -168,6 +173,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("vcpkg"), Crate("version_check"), Crate("void"), + Crate("wasi"), Crate("winapi"), Crate("winapi-build"), Crate("winapi-i686-pc-windows-gnu"), diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 88a469ef95..6d38cfc863 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -176,7 +176,10 @@ pub fn check(path: &Path, bad: &mut bool, verbose: bool) -> CollectedFeatures { CollectedFeatures { lib: lib_features, lang: features } } -fn format_features<'a>(features: &'a Features, family: &'a str) -> impl Iterator + 'a { +fn format_features<'a>( + features: &'a Features, + family: &'a str, +) -> impl Iterator + 'a { features.iter().map(move |(name, feature)| { format!("{:<32} {:<8} {:<12} {:<8}", name, @@ -221,7 +224,15 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { } pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { - let contents = t!(fs::read_to_string(base_src_path.join("libsyntax/feature_gate.rs"))); + let mut all = collect_lang_features_in(base_src_path, "active.rs", bad); + all.extend(collect_lang_features_in(base_src_path, "accepted.rs", bad)); + all.extend(collect_lang_features_in(base_src_path, "removed.rs", bad)); + all +} + +fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features { + let path = base.join("libsyntax/feature_gate").join(file); + let contents = t!(fs::read_to_string(&path)); // We allow rustc-internal features to omit a tracking issue. // To make tidy accept omitting a tracking issue, group the list of features @@ -252,8 +263,9 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { if in_feature_group { tidy_error!( bad, - // ignore-tidy-linelength - "libsyntax/feature_gate.rs:{}: new feature group is started without ending the previous one", + "{}:{}: \ + new feature group is started without ending the previous one", + path.display(), line_number, ); } @@ -282,7 +294,8 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { Err(err) => { tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: failed to parse since: {} ({:?})", + "{}:{}: failed to parse since: {} ({:?})", + path.display(), line_number, since_str, err, @@ -294,7 +307,8 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { if prev_since > since { tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: feature {} is not sorted by since", + "{}:{}: feature {} is not sorted by \"since\" (version number)", + path.display(), line_number, name, ); @@ -308,7 +322,8 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { *bad = true; tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: no tracking issue for feature {}", + "{}:{}: no tracking issue for feature {}", + path.display(), line_number, name, ); diff --git a/src/tools/tidy/src/features/tests.rs b/src/tools/tidy/src/features/tests.rs index fa7a931ec8..994523ac1a 100644 --- a/src/tools/tidy/src/features/tests.rs +++ b/src/tools/tidy/src/features/tests.rs @@ -2,8 +2,8 @@ use super::*; #[test] fn test_find_attr_val() { - let s = r#"#[unstable(feature = "checked_duration_since", issue = "58402")]"#; - assert_eq!(find_attr_val(s, "feature"), Some("checked_duration_since")); + let s = r#"#[unstable(feature = "tidy_test_never_used_anywhere_else", issue = "58402")]"#; + assert_eq!(find_attr_val(s, "feature"), Some("tidy_test_never_used_anywhere_else")); assert_eq!(find_attr_val(s, "issue"), Some("58402")); assert_eq!(find_attr_val(s, "since"), None); } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 5deac52f08..a57238ad81 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -4,6 +4,8 @@ //! etc. This is run by default on `make check` and as part of the auto //! builders. +#![deny(warnings)] + use tidy::*; use std::process; diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 6a0d530e23..9302909968 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -15,6 +15,7 @@ use std::path::Path; +const ERROR_CODE_COLS: usize = 80; const COLS: usize = 100; const LINES: usize = 3000; @@ -51,7 +52,13 @@ enum LIUState { /// Lines of this form are allowed to be overlength, because Markdown /// offers no way to split a line in the middle of a URL, and the lengths /// of URLs to external references are beyond our control. -fn line_is_url(line: &str) -> bool { +fn line_is_url(columns: usize, line: &str) -> bool { + // more basic check for error_codes.rs, to avoid complexity in implementing two state machines + if columns == ERROR_CODE_COLS { + return line.starts_with("[") && + line.contains("]:") && line.contains("http"); + } + use self::LIUState::*; let mut state: LIUState = EXP_COMMENT_START; let is_url = |w: &str| w.starts_with("http://") || w.starts_with("https://"); @@ -75,7 +82,7 @@ fn line_is_url(line: &str) -> bool { => state = EXP_END, (_, w) - if w.len() > COLS && is_url(w) + if w.len() > columns && is_url(w) => state = EXP_END, (_, _) => {} @@ -88,8 +95,8 @@ fn line_is_url(line: &str) -> bool { /// Returns `true` if `line` is allowed to be longer than the normal limit. /// Currently there is only one exception, for long URLs, but more /// may be added in the future. -fn long_line_is_ok(line: &str) -> bool { - if line_is_url(line) { +fn long_line_is_ok(max_columns: usize, line: &str) -> bool { + if line_is_url(max_columns, line) { return true; } @@ -144,6 +151,12 @@ pub fn check(path: &Path, bad: &mut bool) { tidy_error!(bad, "{}: empty file", file.display()); } + let max_columns = if filename == "error_codes.rs" { + ERROR_CODE_COLS + } else { + COLS + }; + let can_contain = contents.contains("// ignore-tidy-") || contents.contains("# ignore-tidy-"); let mut skip_cr = contains_ignore_directive(can_contain, &contents, "cr"); @@ -162,11 +175,12 @@ pub fn check(path: &Path, bad: &mut bool) { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; - if line.chars().count() > COLS && !long_line_is_ok(line) { + if line.chars().count() > max_columns && + !long_line_is_ok(max_columns, line) { suppressible_tidy_err!( err, skip_line_length, - &format!("line longer than {} chars", COLS) + &format!("line longer than {} chars", max_columns) ); } if line.contains('\t') { diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 036349ea1c..fdb0b6d3e5 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -1,5 +1,7 @@ //! Auto-generate stub docs for the unstable book +#![deny(warnings)] + use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features}; use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names, PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR}; diff --git a/vendor/backtrace/.cargo-checksum.json b/vendor/backtrace/.cargo-checksum.json index 32de89d8ca..d135ed3dde 100644 --- a/vendor/backtrace/.cargo-checksum.json +++ b/vendor/backtrace/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6769e806a0a1958a4d5e9bb3de7f56e9c6e6df4778a96f64cf11b60535f3229d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3b4dfbf1e26517c3f6879f983ac1f586cb90035137de16c465a6da70741752d8","azure-pipelines.yml":"15f32b0abf60a41f4323ac177fcd47872e41367064eee64f2eb5c4d15710ef07","benches/benchmarks.rs":"ce5763576fa8aeb722d3b8bcdb294d8a31e80e3c5272da25525fdcc392ccc6cc","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/android-sdk.sh":"3269ef90675e8d4c2031e542cd3a55d9e060b2a094105cde982b282185936dda","ci/azure-install-rust.yml":"3a724290ab48f6d578366038bfd50d624ec6f5bf33d5ad9643dd8927ddcf7961","ci/azure-test-all.yml":"1063b68aafc41d6edf6b0a387de776aa2521bf4df8da1e5425fedf575667296f","ci/docker/aarch64-linux-android/Dockerfile":"c97f23fe2892f406d3deb7479c89e1c1dbbdbd0db456ac699f9399852300348d","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"97fa8f20c6899ee36b47371d485b64a2e96b626a2746b5f434c01eae9168b2a1","ci/docker/arm-linux-androideabi/Dockerfile":"3fe712b0927fd8fb05c1f733f0bf0d8a139bfc5a0108ba5515bd6b499976f1ab","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"41133d712ef13f05e67796857db86476b3ed9c6355d5eb56115575b06d739e04","ci/docker/armv7-linux-androideabi/Dockerfile":"39038d17a423683e0af27a050b34dea610729fb0085814ec6c81726a7f52556f","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"2a216244baad705491f249278083994bf68744a2759f51e768b2f92e0da7c360","ci/docker/i586-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/i686-linux-android/Dockerfile":"9181e5fe5503077652659bc3353c3c21fcf4fc6b03730430fb40d6adc3096079","ci/docker/i686-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"828b657e1748bcd8d331794624d5fc1cd07087a051e507eb9206757985194bf1","ci/docker/x86_64-linux-android/Dockerfile":"074bb2906ba587466490ab9d802eb817b9f23eb54aa095ee53e1a33be5569328","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"0822e270108ec39a6b93721598156031a0469ed680e62ce4acd13bbb1a952b9d","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"e1c202a6831b17e017b4737e80d5b992905895b086bbc06285fc9c337cadbc23","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"2efbba08cc8fff8d2431dde92517df7d122dc754c778820c668f1ac29a885290","ci/run-docker.sh":"c4efad39c65a38c89e90d61a9ef15136903dd4cf01a6ae8079aa005b882d751e","ci/run.sh":"30a3807c195cd86d8b8884e1228cd061aa112b26c54277beebf5108777a36fe9","ci/runtest-android.rs":"be2e49bb296b92a8e3643a6c0a70917fe7b130fa43b71a29c4e7514f45c00e7e","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"81fb66bd0f71010f9a954f667d92bf792cfd1ac90fa3a09c362767d866dc8374","src/backtrace/dbghelp.rs":"e1389870f4376538da2aa71264cee00ad1c34b424dba892a04f76bf267997d4a","src/backtrace/libunwind.rs":"8bf3183c251fabafd2c6d78be60c32345c5a819e0c5a13738220449547fc95c7","src/backtrace/mod.rs":"68a864fa0a76803df67c9e0af6213d445b28f675982fa41a5bdbe9bcc2c267c9","src/backtrace/noop.rs":"9d9a93a890cef988b691232d9d1e7d114768ada58e9591345826135cb380f01a","src/backtrace/unix_backtrace.rs":"293c6ac31e9eb8e32dc7d219f4cf5dbeb9b66bdc42dcc949d1de63233dea2666","src/capture.rs":"5ef847071f3852a6ab8315ca70af266eb3fc513897b4324e15e078891f4e0af1","src/dbghelp.rs":"519bafc50eb85df2c6f7c24c920d50c26a71b070d2e44fb545105de830c43436","src/lib.rs":"225d8bf5af4120a279978117dcf2b262662f49bf6fa56d3a5eaf286c815af0f9","src/symbolize/coresymbolication.rs":"f5442333d8c58188fe3c7749783336bd2e096ed9940d77c19ce4295dd592fb0b","src/symbolize/dbghelp.rs":"649d5ff1656e8fd84ab1088bb48054f6ea7cd0c50a09af09f72d562c17e52b6b","src/symbolize/dladdr.rs":"abaf36567a4f61c9e86e1a7bbee972fb9a683dd812da333c6743aef5b94eaefb","src/symbolize/dladdr_resolve.rs":"ec3bc5c8462cce48e97136e4867dd08a5f1b0c133e45d511745c1c3197e78405","src/symbolize/gimli.rs":"ed74b1c477910686f29422f624c4a509136c7da62875e3eb0b1829788134d018","src/symbolize/libbacktrace.rs":"7ad79d0d63de752a5f977201b0b6f0177072bc034d561f2c7a5a98dc1709dbff","src/symbolize/mod.rs":"4084354bdeb88973b1187424c23835115a58fbddea7fae51d9f8c1e62a5e2df5","src/symbolize/noop.rs":"a8581b117e1065236c12f0a4a4c49f4c1929c4e6a3283f2253bb1fd0c77e4f7a","src/types.rs":"017a00c63ad5b23aaa4e0beb46cc2df1f124f258b1cc06eba701607dcba79b9e","src/windows.rs":"cae9e70f5f63424a09dc1a7e3fc85a6f7b5d4c21b3c653ea5e77064cc11f7f0c","tests/accuracy/auxiliary.rs":"8bcf4a3a15ebed82f878c440910a07866efbc5eacea8b74f482dae297c779226","tests/accuracy/main.rs":"db2870e7fa51df01a5176e59bd87d205d83cad1599f374f273e11baf5efd41bb","tests/long_fn_name.rs":"ca2480a72e8d2c02c678f047c202cdec7efafeb2fb32d94a327c669b7c81807a","tests/skip_inner_frames.rs":"b5c9137723c8648da46396c4c631e4b7d9933cac33397ae3da588a4692322212","tests/smoke.rs":"0330093fa76bd83851f2b8efb37330ce1c1c48d2be99313074d9c727491377f7"},"package":"b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba"} \ No newline at end of file +{"files":{"Cargo.lock":"32f85dc44559be7763dad7c07a8a4529ddb35178a8aa65794f91924bc77bcc4d","Cargo.toml":"29ca7dcdb40c8417fbd97a4092851eac38eb8cde9c072fef57d3d75b29f820d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"5038903e047ac0287b2a16218109171c99a8b67242bdeaff52db51bd60b68fb0","benches/benchmarks.rs":"ce5763576fa8aeb722d3b8bcdb294d8a31e80e3c5272da25525fdcc392ccc6cc","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/android-sdk.sh":"3269ef90675e8d4c2031e542cd3a55d9e060b2a094105cde982b282185936dda","ci/docker/aarch64-linux-android/Dockerfile":"c97f23fe2892f406d3deb7479c89e1c1dbbdbd0db456ac699f9399852300348d","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"97fa8f20c6899ee36b47371d485b64a2e96b626a2746b5f434c01eae9168b2a1","ci/docker/arm-linux-androideabi/Dockerfile":"3fe712b0927fd8fb05c1f733f0bf0d8a139bfc5a0108ba5515bd6b499976f1ab","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"41133d712ef13f05e67796857db86476b3ed9c6355d5eb56115575b06d739e04","ci/docker/armv7-linux-androideabi/Dockerfile":"39038d17a423683e0af27a050b34dea610729fb0085814ec6c81726a7f52556f","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"2a216244baad705491f249278083994bf68744a2759f51e768b2f92e0da7c360","ci/docker/i586-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/i686-linux-android/Dockerfile":"9181e5fe5503077652659bc3353c3c21fcf4fc6b03730430fb40d6adc3096079","ci/docker/i686-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"828b657e1748bcd8d331794624d5fc1cd07087a051e507eb9206757985194bf1","ci/docker/x86_64-linux-android/Dockerfile":"074bb2906ba587466490ab9d802eb817b9f23eb54aa095ee53e1a33be5569328","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"0822e270108ec39a6b93721598156031a0469ed680e62ce4acd13bbb1a952b9d","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"e1c202a6831b17e017b4737e80d5b992905895b086bbc06285fc9c337cadbc23","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"2efbba08cc8fff8d2431dde92517df7d122dc754c778820c668f1ac29a885290","ci/run-docker.sh":"c4efad39c65a38c89e90d61a9ef15136903dd4cf01a6ae8079aa005b882d751e","ci/run.sh":"30a3807c195cd86d8b8884e1228cd061aa112b26c54277beebf5108777a36fe9","ci/runtest-android.rs":"be2e49bb296b92a8e3643a6c0a70917fe7b130fa43b71a29c4e7514f45c00e7e","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"81fb66bd0f71010f9a954f667d92bf792cfd1ac90fa3a09c362767d866dc8374","src/backtrace/dbghelp.rs":"e1389870f4376538da2aa71264cee00ad1c34b424dba892a04f76bf267997d4a","src/backtrace/libunwind.rs":"8bf3183c251fabafd2c6d78be60c32345c5a819e0c5a13738220449547fc95c7","src/backtrace/mod.rs":"68a864fa0a76803df67c9e0af6213d445b28f675982fa41a5bdbe9bcc2c267c9","src/backtrace/noop.rs":"9d9a93a890cef988b691232d9d1e7d114768ada58e9591345826135cb380f01a","src/backtrace/unix_backtrace.rs":"293c6ac31e9eb8e32dc7d219f4cf5dbeb9b66bdc42dcc949d1de63233dea2666","src/capture.rs":"c7c9f0a55312c9687d43118b69d4416d9c8eac1f7eaeb542807bc5e23bc18ce0","src/dbghelp.rs":"c33788eeef29bb78a1cdd7cf7f3e034b82d3686ba87d76a920692db19b26212b","src/lib.rs":"efcdd67622dd654906ae74b249f7ce785582b29fde2f0da8dea1fb398fd80a48","src/print.rs":"858b5fa67766d824cc057d355cd0bd6a47306d04415e49c43e8820b06bb57ab9","src/print/fuchsia.rs":"fcb177101037302536b590f5f14ec9ff72aca06199dedcd1091baa07a1638c10","src/symbolize/coresymbolication.rs":"f5442333d8c58188fe3c7749783336bd2e096ed9940d77c19ce4295dd592fb0b","src/symbolize/dbghelp.rs":"649d5ff1656e8fd84ab1088bb48054f6ea7cd0c50a09af09f72d562c17e52b6b","src/symbolize/dladdr.rs":"4b420b07f345f7c4e545c43f68d1b2d1f419a9228712097f35eae875b182b349","src/symbolize/dladdr_resolve.rs":"ec3bc5c8462cce48e97136e4867dd08a5f1b0c133e45d511745c1c3197e78405","src/symbolize/gimli.rs":"eaf81e6e0b3394a052219dbce8ec406a0065c989da2c6e379864112b529c92c0","src/symbolize/libbacktrace.rs":"7ad79d0d63de752a5f977201b0b6f0177072bc034d561f2c7a5a98dc1709dbff","src/symbolize/mod.rs":"930dbca01710f89ee073b33c32b4787fd771de114f48edd94e241df06dc3daad","src/symbolize/noop.rs":"a8581b117e1065236c12f0a4a4c49f4c1929c4e6a3283f2253bb1fd0c77e4f7a","src/types.rs":"85dac420ee8791281f4cdec78e86be056c84ffecc0e5e5821d91862fc0e23444","src/windows.rs":"d6ae52faf9005251bd0d977fdd363e38f0d56e4c034a5fea3982538f743c6dab","tests/accuracy/auxiliary.rs":"8bcf4a3a15ebed82f878c440910a07866efbc5eacea8b74f482dae297c779226","tests/accuracy/main.rs":"db2870e7fa51df01a5176e59bd87d205d83cad1599f374f273e11baf5efd41bb","tests/concurrent-panics.rs":"7c37df054c57c0c6694265bcaa596c1418a90cce65a569699e1b0c56bcd4bdfa","tests/long_fn_name.rs":"ca2480a72e8d2c02c678f047c202cdec7efafeb2fb32d94a327c669b7c81807a","tests/skip_inner_frames.rs":"b5c9137723c8648da46396c4c631e4b7d9933cac33397ae3da588a4692322212","tests/smoke.rs":"0330093fa76bd83851f2b8efb37330ce1c1c48d2be99313074d9c727491377f7"},"package":"5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2"} \ No newline at end of file diff --git a/vendor/backtrace/Cargo.lock b/vendor/backtrace/Cargo.lock new file mode 100644 index 0000000000..655ae378b2 --- /dev/null +++ b/vendor/backtrace/Cargo.lock @@ -0,0 +1,392 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "intervaltree 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.37" +dependencies = [ + "addr2line 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "cpp_demangle 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "compiler_builtins 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cpp_demangle" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "findshlibs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gimli" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "goblin" +version = "0.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "intervaltree" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "compiler_builtins 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum addr2line 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95b06ae5a8a3bae54910c9029a52f83203ce2001c71b10b1faae3a337fee4ab5" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" +"checksum cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "89431bba4e6b7092fb5fcd00a6f6ca596c55cc26b2f1e6dcdd08a1f4933f66b2" +"checksum compiler_builtins 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "4e32b9fc11fdb3aefbd0a4761a8d3a2b7419608b759fa14a26525df4ea5deaba" +"checksum cpp_demangle 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "d30c0c4ba59fc4951d15cce1b9ba3b448a2b5d601964768fe7cd69c09cc69028" +"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +"checksum findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1260d61e4fe2a6ab845ffdc426a0bd68ffb240b91cf0ec5a8d1170cec535bd8" +"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e3fa261d919c1ae9d1e4533c4a2f99e10938603c4208d56c05bec7a872b661b0" +"checksum intervaltree 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af39074dd8d5eff756ddea3d8f34c7ae287d4dadb6f29fb1b67ca6b3f5036482" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/backtrace/Cargo.toml b/vendor/backtrace/Cargo.toml index a1d59aa6c6..c92382d36d 100644 --- a/vendor/backtrace/Cargo.toml +++ b/vendor/backtrace/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "backtrace" -version = "0.3.34" +version = "0.3.37" authors = ["The Rust Project Developers"] autoexamples = true autotests = true @@ -49,8 +49,13 @@ edition = "2018" name = "accuracy" required-features = ["std", "dbghelp", "libbacktrace", "libunwind"] edition = "2018" + +[[test]] +name = "concurrent-panics" +harness = false +required-features = ["std"] [dependencies.addr2line] -version = "0.9.0" +version = "0.10.0" features = ["std"] optional = true default-features = false @@ -81,8 +86,8 @@ version = "0.5.0" optional = true [dependencies.goblin] -version = "0.0.23" -features = ["std"] +version = "0.0.24" +features = ["elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "std"] optional = true default-features = false @@ -120,23 +125,7 @@ serialize-rustc = ["rustc-serialize"] serialize-serde = ["serde"] std = [] unix-backtrace = [] -verify-winapi = ["winapi/dbghelp", "winapi/handleapi", "winapi/libloaderapi", "winapi/minwindef", "winapi/processthreadsapi", "winapi/winbase", "winapi/winnt"] -[target."cfg(not(any(target_os = \"macos\", windows)))".dependencies.goblin] -version = "0.0.23" -features = ["elf32", "elf64"] -optional = true -default-features = false -[target."cfg(target_os = \"macos\")".dependencies.goblin] -version = "0.0.23" -features = ["mach32", "mach64"] -optional = true -default-features = false -[target."cfg(windows)".dependencies.goblin] -version = "0.0.23" -features = ["pe32", "pe64"] -optional = true -default-features = false - +verify-winapi = ["winapi/dbghelp", "winapi/handleapi", "winapi/libloaderapi", "winapi/minwindef", "winapi/processthreadsapi", "winapi/synchapi", "winapi/winbase", "winapi/winnt"] [target."cfg(windows)".dependencies.winapi] version = "0.3.3" optional = true diff --git a/vendor/backtrace/README.md b/vendor/backtrace/README.md index 06a5f9041a..9713f0c3c2 100644 --- a/vendor/backtrace/README.md +++ b/vendor/backtrace/README.md @@ -1,7 +1,5 @@ # backtrace-rs -[![Build Status](https://dev.azure.com/rust-lang/backtrace-rs/_apis/build/status/rust-lang.backtrace-rs?branchName=master)](https://dev.azure.com/rust-lang/backtrace-rs/_build/latest?definitionId=12&branchName=master) - [Documentation](https://docs.rs/backtrace) A library for acquiring backtraces at runtime for Rust. This library aims to diff --git a/vendor/backtrace/azure-pipelines.yml b/vendor/backtrace/azure-pipelines.yml deleted file mode 100644 index af702fa72b..0000000000 --- a/vendor/backtrace/azure-pipelines.yml +++ /dev/null @@ -1,161 +0,0 @@ -trigger: - - master - -jobs: - - job: MSRV - pool: - vmImage: ubuntu-16.04 - steps: - - checkout: self - submodules: true - - template: ci/azure-install-rust.yml - - script: cargo build - displayName: "Build crate" - variables: - TOOLCHAIN: 1.32.0 - - - job: Docker - pool: - vmImage: ubuntu-16.04 - steps: - - checkout: self - submodules: true - - template: ci/azure-install-rust.yml - - bash: rustup target add $TARGET - displayName: "Install rust cross target" - - bash: | - set -e - cargo generate-lockfile - ./ci/run-docker.sh $TARGET - displayName: "Run tests in docker" - strategy: - matrix: - aarch64: - TARGET: aarch64-unknown-linux-gnu - armhf: - TARGET: arm-unknown-linux-gnueabihf - armv7: - TARGET: armv7-unknown-linux-gnueabihf - i586: - TARGET: i586-unknown-linux-gnu - i686: - TARGET: i686-unknown-linux-gnu - powerpc64: - TARGET: powerpc64-unknown-linux-gnu - mingw: - TARGET: x86_64-pc-windows-gnu - x86_64: - TARGET: x86_64-unknown-linux-gnu - gnu: - TARGET: x86_64-unknown-linux-musl - - android-arm: - TARGET: arm-linux-androideabi - android-armv7: - TARGET: armv7-linux-androideabi - android-aarch64: - TARGET: aarch64-linux-android - android-i686: - TARGET: i686-linux-android - android-x86_64: - TARGET: x86_64-linux-android - - - job: Linux - pool: - vmImage: ubuntu-16.04 - steps: - - template: ci/azure-test-all.yml - strategy: - matrix: - stable: - TOOLCHAIN: stable - beta: - TOOLCHAIN: beta - nightly: - TOOLCHAIN: nightly - - - job: macOS - pool: - vmImage: macos-10.13 - steps: - - template: ci/azure-test-all.yml - strategy: - matrix: - x86_64: - TARGET: x86_64-apple-darwin - - - job: iOS - pool: - vmImage: macos-10.13 - steps: - - checkout: self - submodules: true - - template: ci/azure-install-rust.yml - - script: rustup target add $TARGET - displayName: "Install rust cross target" - - bash: | - set -e - export SDK_PATH=`xcrun --show-sdk-path --sdk $SDK` - export RUSTFLAGS="-C link-arg=-isysroot -C link-arg=$SDK_PATH" - cargo test --no-run --target $TARGET - displayName: "Build for iOS" - strategy: - matrix: - aarch64: - TARGET: aarch64-apple-ios - SDK: iphoneos - armv7: - TARGET: armv7-apple-ios - SDK: iphoneos - armv7s: - TARGET: armv7s-apple-ios - SDK: iphoneos - i386: - TARGET: i386-apple-ios - SDK: iphonesimulator - x86_64: - TARGET: x86_64-apple-ios - SDK: iphonesimulator - - - job: wasm - pool: - vmImage: ubuntu-16.04 - steps: - - checkout: self - submodules: true - - template: ci/azure-install-rust.yml - - script: rustup target add wasm32-unknown-unknown - displayName: "Install rust cross target" - - script: cargo build --target wasm32-unknown-unknown - displayName: "Build for wasm" - - - job: Windows - pool: - vmImage: vs2017-win2016 - steps: - - template: ci/azure-test-all.yml - strategy: - matrix: - x86_64-msvc: - TARGET: x86_64-pc-windows-msvc - i686-msvc: - TARGET: i686-pc-windows-msvc - # this looks to be required to get full fidelity of backtrace - # information on 32-bit MSVC - RUSTFLAGS: -Cforce-frame-pointers - x86_64-gnu: - TARGET: x86_64-pc-windows-gnu - i686-gnu: - TARGET: i686-pc-windows-gnu - - - job: Windows_arm64 - pool: - vmImage: windows-2019 - steps: - - template: ci/azure-install-rust.yml - - script: rustup target add aarch64-pc-windows-msvc - displayName: "Install rust cross target" - - script: cargo test --no-run --target aarch64-pc-windows-msvc - displayName: "Build for arm64" - - script: cargo test --no-run --target aarch64-pc-windows-msvc --features verify-winapi - displayName: "Build for arm64" diff --git a/vendor/backtrace/ci/azure-install-rust.yml b/vendor/backtrace/ci/azure-install-rust.yml deleted file mode 100644 index cf9525ec13..0000000000 --- a/vendor/backtrace/ci/azure-install-rust.yml +++ /dev/null @@ -1,25 +0,0 @@ -steps: - - bash: | - set -e - toolchain=$TOOLCHAIN - if [ "$toolchain" = "" ]; then - toolchain=stable - fi - if command -v rustup; then - rustup update --no-self-update $toolchain - rustup default $toolchain - else - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain - echo "##vso[task.prependpath]$HOME/.cargo/bin" - fi - displayName: Install rust (unix) - condition: ne( variables['Agent.OS'], 'Windows_NT' ) - - - bash: rustup update --no-self-update stable-$TARGET && rustup default stable-$TARGET - displayName: Install rust (windows) - condition: eq( variables['Agent.OS'], 'Windows_NT' ) - - - script: | - rustc -Vv - cargo -V - displayName: Query rust and cargo versions diff --git a/vendor/backtrace/ci/azure-test-all.yml b/vendor/backtrace/ci/azure-test-all.yml deleted file mode 100644 index bab4150bb7..0000000000 --- a/vendor/backtrace/ci/azure-test-all.yml +++ /dev/null @@ -1,57 +0,0 @@ -steps: - - checkout: self - submodules: true - - template: azure-install-rust.yml - - - bash: cargo build --manifest-path crates/backtrace-sys/Cargo.toml - displayName: "Build backtrace-sys" - - bash: cargo build - displayName: "Build backtrace" - - bash: cargo test - displayName: "Test backtrace" - - bash: cargo test --features 'gimli-symbolize' - displayName: "Test backtrace (gimli-symbolize)" - - bash: cargo test --no-default-features - displayName: "Test backtrace (-default)" - - bash: cargo test --no-default-features --features 'std' - displayName: "Test backtrace (-default + std)" - - bash: cargo test --no-default-features --features 'libunwind std' - displayName: "Test backtrace (-default + libunwind)" - - bash: cargo test --no-default-features --features 'libunwind dladdr std' - displayName: "Test backtrace (-default + libunwind + dladdr)" - - bash: cargo test --no-default-features --features 'libunwind libbacktrace std' - displayName: "Test backtrace (-default + libunwind + libbacktrace)" - - bash: cargo test --no-default-features --features 'libunwind libbacktrace dbghelp std' - displayName: "Test backtrace (-default + libunwind + libbacktrace + dbghelp)" - - bash: cargo test --no-default-features --features 'libunwind coresymbolication dbghelp std' - displayName: "Test backtrace (-default + libunwind + coresymbolication + dbghelp)" - - bash: cargo test --no-default-features --features 'libunwind coresymbolication dbghelp std libbacktrace' - displayName: "Test backtrace (-default + libunwind + coresymbolication + dbghelp + libbacktrace)" - - bash: cargo test --no-default-features --features 'unix-backtrace std' - displayName: "Test backtrace (-default + unix-backtrace)" - - bash: cargo test --no-default-features --features 'unix-backtrace dladdr std' - displayName: "Test backtrace (-default + unix-backtrace + dladdr)" - - bash: cargo test --no-default-features --features 'unix-backtrace libbacktrace std' - displayName: "Test backtrace (-default + unix-backtrace + libbacktrace)" - - bash: cargo test --no-default-features --features 'unix-backtrace coresymbolication std' - displayName: "Test backtrace (-default + unix-backtrace + coresymbolication)" - - bash: cargo test --no-default-features --features 'serialize-serde std' - displayName: "Test backtrace (-default + serialize-serde + std)" - - bash: cargo test --no-default-features --features 'serialize-rustc std' - displayName: "Test backtrace (-default + serialize-rustc + std)" - - bash: cargo test --no-default-features --features 'serialize-rustc serialize-serde std' - displayName: "Test backtrace (-default + serialize-rustc + serialize-serde + std)" - - bash: cargo test --no-default-features --features 'cpp_demangle std' - displayName: "Test backtrace (-default + cpp_demangle + std)" - - bash: cargo test --no-default-features --features 'dbghelp std' - displayName: "Test backtrace (-default + dbghelp + std)" - - bash: cargo test --no-default-features --features 'dbghelp std verify-winapi' - displayName: "Test backtrace (-default + dbghelp + std + verify-winapi)" - - bash: cd ./crates/cpp_smoke_test && cargo test - displayName: "Test cpp_smoke_test" - - bash: cd ./crates/without_debuginfo && cargo test --features libbacktrace - displayName: "Test without debuginfo (libbacktrace)" - - bash: cd ./crates/without_debuginfo && cargo test --features 'libbacktrace coresymbolication' - displayName: "Test without debuginfo (coresymbolication)" - - bash: cd ./crates/without_debuginfo && cargo test --features 'libbacktrace gimli-symbolize' - displayName: "Test without debuginfo (gimli-symbolize)" diff --git a/vendor/backtrace/src/capture.rs b/vendor/backtrace/src/capture.rs index 59a461e50b..7b37bd1bcf 100644 --- a/vendor/backtrace/src/capture.rs +++ b/vendor/backtrace/src/capture.rs @@ -1,11 +1,12 @@ -use crate::{resolve, resolve_frame, trace, Symbol, SymbolName}; +use crate::PrintFmt; +use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName}; use std::ffi::c_void; use std::fmt; use std::path::{Path, PathBuf}; use std::prelude::v1::*; #[cfg(feature = "serde")] -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; /// Representation of an owned and self-contained backtrace. /// @@ -325,66 +326,36 @@ impl BacktraceSymbol { impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "stack backtrace:")?; - - let iter = if fmt.alternate() { - self.frames.iter() + let full = fmt.alternate(); + let (frames, style) = if full { + (&self.frames[..], PrintFmt::Full) } else { - self.frames[self.actual_start_index..].iter() + (&self.frames[self.actual_start_index..], PrintFmt::Short) }; - for (idx, frame) in iter.enumerate() { - // To reduce TCB size in Sgx enclave, we do not want to implement symbol resolution functionality. - // Rather, we can print the offset of the address here, which could be later mapped to - // correct function. - let ip: *mut c_void; - #[cfg(target_env = "sgx")] - { - ip = usize::wrapping_sub( - frame.ip() as _, - std::os::fortanix_sgx::mem::image_base() as _, - ) as _; - } - #[cfg(not(target_env = "sgx"))] - { - ip = frame.ip(); - } - - write!(fmt, "\n{:4}: ", idx)?; - - let symbols = match frame.symbols { - Some(ref s) => s, - None => { - write!(fmt, " ({:?})", ip)?; - continue; + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = std::env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| { + let path = path.into_path_buf(); + if !full { + if let Ok(cwd) = &cwd { + if let Ok(suffix) = path.strip_prefix(cwd) { + return fmt::Display::fmt(&suffix.display(), fmt); + } } - }; - if symbols.len() == 0 { - write!(fmt, " ({:?})", ip)?; - continue; } + fmt::Display::fmt(&path.display(), fmt) + }; - for (idx, symbol) in symbols.iter().enumerate() { - if idx != 0 { - write!(fmt, "\n ")?; - } - - if let Some(name) = symbol.name() { - write!(fmt, "{}", name)?; - } else { - write!(fmt, "")?; - } - - if idx == 0 { - write!(fmt, " ({:?})", ip)?; - } - - if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { - write!(fmt, "\n at {}:{}", file.display(), line)?; - } - } + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + f.frame().backtrace_frame(frame)?; } - + f.finish()?; Ok(()) } } diff --git a/vendor/backtrace/src/dbghelp.rs b/vendor/backtrace/src/dbghelp.rs index 8db4e7637e..05ffef2ac8 100644 --- a/vendor/backtrace/src/dbghelp.rs +++ b/vendor/backtrace/src/dbghelp.rs @@ -244,45 +244,127 @@ dbghelp! { } } -pub struct Init; +pub struct Init { + lock: HANDLE, +} -/// Unsafe because this requires external synchronization, must be done -/// inside of the same lock as all other backtrace operations. +/// Initialize all support necessary to access `dbghelp` API functions from this +/// crate. /// -/// Note that the `Dbghelp` returned must also be dropped within the same -/// lock. +/// Note that this function is **safe**, it internally has its own +/// synchronization. Also note that it is safe to call this function multiple +/// times recursively. #[cfg(all(windows, feature = "dbghelp"))] -pub unsafe fn init() -> Result { - // Calling `SymInitializeW` is quite expensive, so we only do so once per - // process. - static mut INITIALIZED: bool = false; - if INITIALIZED { - return Ok(Init); - } +pub fn init() -> Result { + use core::sync::atomic::{AtomicUsize, Ordering::SeqCst}; - // Actually load `dbghelp.dll` into the process here, returning an error if - // that fails. - DBGHELP.ensure_open()?; + unsafe { + // First thing we need to do is to synchronize this function. This can + // be called concurrently from other threads or recursively within one + // thread. Note that it's trickier than that though because what we're + // using here, `dbghelp`, *also* needs to be synchronized with all other + // callers to `dbghelp` in this process. + // + // Typically there aren't really that many calls to `dbghelp` within the + // same process and we can probably safely assume that we're the only + // ones accessing it. There is, however, one primary other user we have + // to worry about which is ironically ourselves, but in the standard + // library. The Rust standard library depends on this crate for + // backtrace support, and this crate also exists on crates.io. This + // means that if the standard library is printing a panic backtrace it + // may race with this crate coming from crates.io, causing segfaults. + // + // To help solve this synchronization problem we employ a + // Windows-specific trick here (it is, after all, a Windows-specific + // restriction about synchronization). We create a *session-local* named + // mutex to protect this call. The intention here is that the standard + // library and this crate don't have to share Rust-level APIs to + // synchronize here but can instead work behind the scenes to make sure + // they're synchronizing with one another. That way when this function + // is called through the standard library or through crates.io we can be + // sure that the same mutex is being acquired. + // + // So all of that is to say that the first thing we do here is we + // atomically create a `HANDLE` which is a named mutex on Windows. We + // synchronize a bit with other threads sharing this function + // specifically and ensure that only one handle is created per instance + // of this function. Note that the handle is never closed once it's + // stored in the global. + // + // After we've actually go the lock we simply acquire it, and our `Init` + // handle we hand out will be responsible for dropping it eventually. + static LOCK: AtomicUsize = AtomicUsize::new(0); + let mut lock = LOCK.load(SeqCst); + if lock == 0 { + lock = CreateMutexA( + ptr::null_mut(), + 0, + "Local\\RustBacktraceMutex\0".as_ptr() as _, + ) as usize; + if lock == 0 { + return Err(()); + } + if let Err(other) = LOCK.compare_exchange(0, lock, SeqCst, SeqCst) { + debug_assert!(other != 0); + CloseHandle(lock as HANDLE); + lock = other; + } + } + debug_assert!(lock != 0); + let lock = lock as HANDLE; + let r = WaitForSingleObjectEx(lock, INFINITE, FALSE); + debug_assert_eq!(r, 0); + let ret = Init { lock }; + + // Ok, phew! Now that we're all safely synchronized, let's actually + // start processing everything. First up we need to ensure that + // `dbghelp.dll` is actually loaded in this process. We do this + // dynamically to avoid a static dependency. This has historically been + // done to work around weird linking issues and is intended at making + // binaries a bit more portable since this is largely just a debugging + // utility. + // + // Once we've opened `dbghelp.dll` we need to call some initialization + // functions in it, and that's detailed more below. We only do this + // once, though, so we've got a global boolean indicating whether we're + // done yet or not. + DBGHELP.ensure_open()?; - let orig = DBGHELP.SymGetOptions().unwrap()(); + static mut INITIALIZED: bool = false; + if INITIALIZED { + return Ok(ret); + } - // Ensure that the `SYMOPT_DEFERRED_LOADS` flag is set, because - // according to MSVC's own docs about this: "This is the fastest, most - // efficient way to use the symbol handler.", so let's do that! - DBGHELP.SymSetOptions().unwrap()(orig | SYMOPT_DEFERRED_LOADS); + let orig = DBGHELP.SymGetOptions().unwrap()(); - // Actually initialize symbols with MSVC. Note that this can fail, but we - // ignore it. There's not a ton of prior art for this per se, but LLVM - // internally seems to ignore the return value here and one of the - // sanitizer libraries in LLVM prints a scary warning if this fails but - // basically ignores it in the long run. - // - // One case this comes up a lot for Rust is that the standard library and - // this crate on crates.io both want to compete for `SymInitializeW`. The - // standard library historically wanted to initialize then cleanup most of - // the time, but now that it's using this crate it means that someone will - // get to initialization first and the other will pick up that - // initialization. - DBGHELP.SymInitializeW().unwrap()(GetCurrentProcess(), ptr::null_mut(), TRUE); - Ok(Init) + // Ensure that the `SYMOPT_DEFERRED_LOADS` flag is set, because + // according to MSVC's own docs about this: "This is the fastest, most + // efficient way to use the symbol handler.", so let's do that! + DBGHELP.SymSetOptions().unwrap()(orig | SYMOPT_DEFERRED_LOADS); + + // Actually initialize symbols with MSVC. Note that this can fail, but we + // ignore it. There's not a ton of prior art for this per se, but LLVM + // internally seems to ignore the return value here and one of the + // sanitizer libraries in LLVM prints a scary warning if this fails but + // basically ignores it in the long run. + // + // One case this comes up a lot for Rust is that the standard library and + // this crate on crates.io both want to compete for `SymInitializeW`. The + // standard library historically wanted to initialize then cleanup most of + // the time, but now that it's using this crate it means that someone will + // get to initialization first and the other will pick up that + // initialization. + DBGHELP.SymInitializeW().unwrap()(GetCurrentProcess(), ptr::null_mut(), TRUE); + INITIALIZED = true; + Ok(ret) + } +} + +impl Drop for Init { + fn drop(&mut self) { + unsafe { + let r = ReleaseMutex(self.lock); + debug_assert!(r != 0); + } + } } diff --git a/vendor/backtrace/src/lib.rs b/vendor/backtrace/src/lib.rs index e950826e6b..9490312a05 100644 --- a/vendor/backtrace/src/lib.rs +++ b/vendor/backtrace/src/lib.rs @@ -86,6 +86,9 @@ mod types; #[cfg(feature = "std")] pub use crate::symbolize::clear_symbol_cache; +mod print; +pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; + cfg_if::cfg_if! { if #[cfg(feature = "std")] { pub use crate::backtrace::trace; diff --git a/vendor/backtrace/src/print.rs b/vendor/backtrace/src/print.rs new file mode 100644 index 0000000000..5e798bfa22 --- /dev/null +++ b/vendor/backtrace/src/print.rs @@ -0,0 +1,268 @@ +use crate::BytesOrWideString; +use core::ffi::c_void; +use core::fmt; + +const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); + +#[cfg(target_os = "fuchsia")] +mod fuchsia; + +/// A formatter for backtraces. +/// +/// This type can be used to print a backtrace regardless of where the backtrace +/// itself comes from. If you have a `Backtrace` type then its `Debug` +/// implementation already uses this printing format. +pub struct BacktraceFmt<'a, 'b> { + fmt: &'a mut fmt::Formatter<'b>, + frame_index: usize, + format: PrintFmt, + print_path: &'a mut (FnMut(&mut fmt::Formatter, BytesOrWideString) -> fmt::Result + 'b), +} + +/// The styles of printing that we can print +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum PrintFmt { + /// Prints a terser backtrace which ideally only contains relevant information + Short, + /// Prints a backtrace that contains all possible information + Full, + #[doc(hidden)] + __Nonexhaustive, +} + +impl<'a, 'b> BacktraceFmt<'a, 'b> { + /// Create a new `BacktraceFmt` which will write output to the provided + /// `fmt`. + /// + /// The `format` argument will control the style in which the backtrace is + /// printed, and the `print_path` argument will be used to print the + /// `BytesOrWideString` instances of filenames. This type itself doesn't do + /// any printing of filenames, but this callback is required to do so. + pub fn new( + fmt: &'a mut fmt::Formatter<'b>, + format: PrintFmt, + print_path: &'a mut (FnMut(&mut fmt::Formatter, BytesOrWideString) -> fmt::Result + 'b), + ) -> Self { + BacktraceFmt { + fmt, + frame_index: 0, + format, + print_path, + } + } + + /// Prints a preamble for the backtrace about to be printed. + /// + /// This is required on some platforms for backtraces to be fully + /// sumbolicated later, and otherwise this should just be the first method + /// you call after creating a `BacktraceFmt`. + pub fn add_context(&mut self) -> fmt::Result { + self.fmt.write_str("stack backtrace:\n")?; + #[cfg(target_os = "fuchsia")] + fuchsia::print_dso_context(self.fmt)?; + Ok(()) + } + + /// Adds a frame to the backtrace output. + /// + /// This commit returns an RAII instance of a `BacktraceFrameFmt` which can be used + /// to actually print a frame, and on destruction it will increment the + /// frame counter. + pub fn frame(&mut self) -> BacktraceFrameFmt<'_, 'a, 'b> { + BacktraceFrameFmt { + fmt: self, + symbol_index: 0, + } + } + + /// Completes the backtrace output. + /// + /// This is currently a no-op but is added for future compatibility with + /// backtrace formats. + pub fn finish(&mut self) -> fmt::Result { + // Currently a no-op-- including this hook to allow for future additions. + Ok(()) + } +} + +/// A formatter for just one frame of a backtrace. +/// +/// This type is created by the `BacktraceFmt::frame` function. +pub struct BacktraceFrameFmt<'fmt, 'a, 'b> { + fmt: &'fmt mut BacktraceFmt<'a, 'b>, + symbol_index: usize, +} + +impl BacktraceFrameFmt<'_, '_, '_> { + /// Prints a `BacktraceFrame` with this frame formatter. + /// + /// This will recusrively print all `BacktraceSymbol` instances within the + /// `BacktraceFrame`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[cfg(feature = "std")] + pub fn backtrace_frame(&mut self, frame: &crate::BacktraceFrame) -> fmt::Result { + let symbols = frame.symbols(); + for symbol in symbols { + self.backtrace_symbol(frame, symbol)?; + } + if symbols.is_empty() { + self.print_raw(frame.ip(), None, None, None)?; + } + Ok(()) + } + + /// Prints a `BacktraceSymbol` within a `BacktraceFrame`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[cfg(feature = "std")] + pub fn backtrace_symbol( + &mut self, + frame: &crate::BacktraceFrame, + symbol: &crate::BacktraceSymbol, + ) -> fmt::Result { + self.print_raw( + frame.ip(), + symbol.name(), + // TODO: this isn't great that we don't end up printing anything + // with non-utf8 filenames. Thankfully almost everything is utf8 so + // this shouldn't be too too bad. + symbol + .filename() + .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))), + symbol.lineno(), + )?; + Ok(()) + } + + /// Prints a raw traced `Frame` and `Symbol`, typically from within the raw + /// callbacks of this crate. + pub fn symbol(&mut self, frame: &crate::Frame, symbol: &crate::Symbol) -> fmt::Result { + self.print_raw( + frame.ip(), + symbol.name(), + symbol.filename_raw(), + symbol.lineno(), + )?; + Ok(()) + } + + /// Adds a raw frame to the backtrace output. + /// + /// This method, unlike the previous, takes the raw arguments in case + /// they're being source from different locations. Note that this may be + /// called multiple times for one frame. + pub fn print_raw( + &mut self, + frame_ip: *mut c_void, + symbol_name: Option, + filename: Option, + lineno: Option, + ) -> fmt::Result { + // Fuchsia is unable to symbolize within a process so it has a special + // format which can be used to symbolize later. Print that instead of + // printing addresses in our own format here. + if cfg!(target_os = "fuchsia") { + self.print_raw_fuchsia(frame_ip)?; + } else { + self.print_raw_generic(frame_ip, symbol_name, filename, lineno)?; + } + self.symbol_index += 1; + Ok(()) + } + + #[allow(unused_mut)] + fn print_raw_generic( + &mut self, + mut frame_ip: *mut c_void, + symbol_name: Option, + filename: Option, + lineno: Option, + ) -> fmt::Result { + // No need to print "null" frames, it basically just means that the + // system backtrace was a bit eager to trace back super far. + if let PrintFmt::Short = self.fmt.format { + if frame_ip.is_null() { + return Ok(()); + } + } + + // To reduce TCB size in Sgx enclave, we do not want to implement symbol + // resolution functionality. Rather, we can print the offset of the + // address here, which could be later mapped to correct function. + #[cfg(all(feature = "std", target_env = "sgx"))] + { + frame_ip = + usize::wrapping_sub(frame_ip, std::os::fortanix_sgx::mem::image_base() as _) as _; + } + + // Print the index of the frame as well as the optional instruction + // pointer of the frame. If we're beyond the first symbol of this frame + // though we just print appropriate whitespace. + if self.symbol_index == 0 { + write!(self.fmt.fmt, "{:4}: ", self.fmt.frame_index)?; + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{:1$?} - ", frame_ip, HEX_WIDTH)?; + } + } else { + write!(self.fmt.fmt, " ")?; + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH + 3)?; + } + } + + // Next up write out the symbol name, using the alternate formatting for + // more information if we're a full backtrace. Here we also handle + // symbols which don't have a name, + match (symbol_name, &self.fmt.format) { + (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "{:#}", name)?, + (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "{}", name)?, + (None, _) | (_, PrintFmt::__Nonexhaustive) => write!(self.fmt.fmt, "")?, + } + self.fmt.fmt.write_str("\n")?; + + // And last up, print out the filename/line number if they're available. + if let (Some(file), Some(line)) = (filename, lineno) { + self.print_fileline(file, line)?; + } + + Ok(()) + } + + fn print_fileline(&mut self, file: BytesOrWideString, line: u32) -> fmt::Result { + // Filename/line are printed on lines under the symbol name, so print + // some appropriate whitespace to sort of right-align ourselves. + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH)?; + } + write!(self.fmt.fmt, " at ")?; + + // Delegate to our internal callback to print the filename and then + // print out the line number. + (self.fmt.print_path)(self.fmt.fmt, file)?; + write!(self.fmt.fmt, ":{}\n", line)?; + Ok(()) + } + + fn print_raw_fuchsia(&mut self, frame_ip: *mut c_void) -> fmt::Result { + // We only care about the first symbol of a frame + if self.symbol_index == 0 { + self.fmt.fmt.write_str("{{{bt:")?; + write!(self.fmt.fmt, "{}:{:?}", self.fmt.frame_index, frame_ip)?; + self.fmt.fmt.write_str("}}}\n")?; + } + Ok(()) + } +} + +impl Drop for BacktraceFrameFmt<'_, '_, '_> { + fn drop(&mut self) { + self.fmt.frame_index += 1; + } +} diff --git a/vendor/backtrace/src/print/fuchsia.rs b/vendor/backtrace/src/print/fuchsia.rs new file mode 100644 index 0000000000..83dd8eee9e --- /dev/null +++ b/vendor/backtrace/src/print/fuchsia.rs @@ -0,0 +1,432 @@ +use core::fmt::{self, Write}; +use core::mem::{size_of, transmute}; +use core::slice::from_raw_parts; +use libc::c_char; + +extern "C" { + // dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer + // for every DSO that has been linked into the process. dl_iterate_phdr also + // ensures that the dynamic linker is locked from start to finish of the + // iteration. If the callback returns a non-zero value the iteration is + // terminated early. 'data' will be passed as the third argument to the + // callback on each call. 'size' gives the size of the dl_phdr_info. + #[allow(improper_ctypes)] + fn dl_iterate_phdr( + f: extern "C" fn(info: &dl_phdr_info, size: usize, data: &mut DsoPrinter) -> i32, + data: &mut DsoPrinter, + ) -> i32; +} + +// We need to parse out the build ID and some basic program header data +// which means that we need a bit of stuff from the ELF spec as well. + +const PT_LOAD: u32 = 1; +const PT_NOTE: u32 = 4; + +// Now we have to replicate, bit for bit, the structure of the dl_phdr_info +// type used by fuchsia's current dynamic linker. Chromium also has this ABI +// boundary as well as crashpad. Eventully we'd like to move these cases to +// use elf-search but we'd need to provide that in the SDK and that has not +// yet been done. Thus we (and they) are stuck having to use this method +// which incurs a tight coupling with the fuchsia libc. + +#[allow(non_camel_case_types)] +#[repr(C)] +struct dl_phdr_info { + addr: *const u8, + name: *const c_char, + phdr: *const Elf_Phdr, + phnum: u16, + adds: u64, + subs: u64, + tls_modid: usize, + tls_data: *const u8, +} + +impl dl_phdr_info { + fn program_headers(&self) -> PhdrIter<'_> { + PhdrIter { + phdrs: self.phdr_slice(), + base: self.addr, + } + } + // We have no way of knowing of checking if e_phoff and e_phnum are valid. + // libc should ensure this for us however so it's safe to form a slice here. + fn phdr_slice(&self) -> &[Elf_Phdr] { + unsafe { from_raw_parts(self.phdr, self.phnum as usize) } + } +} + +struct PhdrIter<'a> { + phdrs: &'a [Elf_Phdr], + base: *const u8, +} + +impl<'a> Iterator for PhdrIter<'a> { + type Item = Phdr<'a>; + fn next(&mut self) -> Option { + self.phdrs.split_first().map(|(phdr, new_phdrs)| { + self.phdrs = new_phdrs; + Phdr { + phdr, + base: self.base, + } + }) + } +} + +// Elf_Phdr represents a 64-bit ELF program header in the endianness of the target +// architecture. +#[allow(non_camel_case_types)] +#[derive(Clone, Debug)] +#[repr(C)] +struct Elf_Phdr { + p_type: u32, + p_flags: u32, + p_offset: u64, + p_vaddr: u64, + p_paddr: u64, + p_filesz: u64, + p_memsz: u64, + p_align: u64, +} + +// Phdr represents a valid ELF program header and its contents. +struct Phdr<'a> { + phdr: &'a Elf_Phdr, + base: *const u8, +} + +impl<'a> Phdr<'a> { + // We have no way of checking if p_addr or p_memsz are valid. Fuchsia's libc + // parses the notes first however so by virtue of being here these headers + // must be valid. NoteIter does not require the underlying data to be valid + // but it does require the bounds to be valid. We trust that libc has ensured + // that this is the case for us here. + fn notes(&self) -> NoteIter<'a> { + unsafe { + NoteIter::new( + self.base.add(self.phdr.p_offset as usize), + self.phdr.p_memsz as usize, + ) + } + } +} + +// The note type for build IDs. +const NT_GNU_BUILD_ID: u32 = 3; + +// Elf_Nhdr represents an ELF note header in the endianness of the target. +#[allow(non_camel_case_types)] +#[repr(C)] +struct Elf_Nhdr { + n_namesz: u32, + n_descsz: u32, + n_type: u32, +} + +// Note represents an ELF note (header + contents). The name is left as a u8 +// slice because it is not always null terminated and rust makes it easy enough +// to check that the bytes match eitherway. +struct Note<'a> { + name: &'a [u8], + desc: &'a [u8], + tipe: u32, +} + +// NoteIter lets you safely iterate over a note segment. It terminates as soon +// as an error occurs or there are no more notes. If you iterate over invalid +// data it will function as though no notes were found. +struct NoteIter<'a> { + base: &'a [u8], + error: bool, +} + +impl<'a> NoteIter<'a> { + // It is an invariant of function that the pointer and size given denote a + // valid range of bytes that can all be read. The contents of these bytes + // can be anything but the range must be valid for this to be safe. + unsafe fn new(base: *const u8, size: usize) -> Self { + NoteIter { + base: from_raw_parts(base, size), + error: false, + } + } +} + +// align_to aligns 'x' to 'to'-byte alignment assuming 'to' is a power of 2. +// This follows a standard pattern in C/C++ ELF parsing code where +// (x + to - 1) & -to is used. Rust does not let you negate usize so I use +// 2's-complement conversion to recreate that. +fn align_to(x: usize, to: usize) -> usize { + (x + to - 1) & (!to + 1) +} + +// take_bytes_align4 consumes num bytes from the slice (if present) and +// additionally ensures that the final slice is properlly aligned. If an +// either the number of bytes requested is too large or the slice can't be +// realigned afterwards due to not enough remaining bytes existing, None is +// returned and the slice is not modified. +fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> { + if bytes.len() < align_to(num, 4) { + return None; + } + let (out, bytes_new) = bytes.split_at(num); + *bytes = &bytes_new[align_to(num, 4) - num..]; + Some(out) +} + +// This function has no real invariants the caller must uphold other than +// perhaps that 'bytes' should be aligned for performance (and on some +// architectures correctness). The values in the Elf_Nhdr fields might +// be nonsense but this function ensures no such thing. +fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> { + if size_of::() > bytes.len() { + return None; + } + // This is safe as long as there is enough space and we just confirmed that + // in the if statement above so this should not be unsafe. + let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) }; + // Note that sice_of::() is always 4-byte aligned. + *bytes = &bytes[size_of::()..]; + Some(out) +} + +impl<'a> Iterator for NoteIter<'a> { + type Item = Note<'a>; + fn next(&mut self) -> Option { + // Check if we've reached the end. + if self.base.len() == 0 || self.error { + return None; + } + // We transmute out an nhdr but we carefully consider the resulting + // struct. We don't trust the namesz or descsz and we make no unsafe + // decisions based on the type. So even if we get out complete garbage + // we should still be safe. + let nhdr = take_nhdr(&mut self.base)?; + let name = take_bytes_align4(nhdr.n_namesz as usize, &mut self.base)?; + let desc = take_bytes_align4(nhdr.n_descsz as usize, &mut self.base)?; + Some(Note { + name: name, + desc: desc, + tipe: nhdr.n_type, + }) + } +} + +struct Perm(u32); + +/// Indicates that a segment is executable. +const PERM_X: u32 = 0b00000001; +/// Indicates that a segment is writable. +const PERM_W: u32 = 0b00000010; +/// Indicates that a segment is readable. +const PERM_R: u32 = 0b00000100; + +impl core::fmt::Display for Perm { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let v = self.0; + if v & PERM_R != 0 { + f.write_char('r')? + } + if v & PERM_W != 0 { + f.write_char('w')? + } + if v & PERM_X != 0 { + f.write_char('x')? + } + Ok(()) + } +} + +/// Represents an ELF segment at runtime. +struct Segment { + /// Gives the runtime virtual address of this segment's contents. + addr: usize, + /// Gives the memory size of this segment's contents. + size: usize, + /// Gives the module virtual address of this segment with the ELF file. + mod_rel_addr: usize, + /// Gives the permissions found in the ELF file. These permissions are not + /// necessarily the permissions present at runtime however. + flags: Perm, +} + +/// Lets one iterate over Segments from a DSO. +struct SegmentIter<'a> { + phdrs: &'a [Elf_Phdr], + base: usize, +} + +impl Iterator for SegmentIter<'_> { + type Item = Segment; + + fn next(&mut self) -> Option { + self.phdrs.split_first().and_then(|(phdr, new_phdrs)| { + self.phdrs = new_phdrs; + if phdr.p_type != PT_LOAD { + self.next() + } else { + Some(Segment { + addr: phdr.p_vaddr as usize + self.base, + size: phdr.p_memsz as usize, + mod_rel_addr: phdr.p_vaddr as usize, + flags: Perm(phdr.p_flags), + }) + } + }) + } +} + +/// Represents an ELF DSO (Dynamic Shared Object). This type references +/// the data stored in the actual DSO rather than making its own copy. +struct Dso<'a> { + /// The dynamic linker always gives us a name, even if the name is empty. + /// In the case of the main executable this name will be empty. In the case + /// of a shared object it will be the soname (see DT_SONAME). + name: &'a str, + /// On Fuchsia virtually all binaries have build IDs but this is not a strict + /// requierment. There's no way to match up DSO information with a real ELF + /// file afterwards if there is no build_id so we require that every DSO + /// have one here. DSO's without a build_id are ignored. + build_id: &'a [u8], + + base: usize, + phdrs: &'a [Elf_Phdr], +} + +impl Dso<'_> { + /// Returns an iterator over Segments in this DSO. + fn segments(&self) -> SegmentIter<'_> { + SegmentIter { + phdrs: self.phdrs.as_ref(), + base: self.base, + } + } +} + +struct HexSlice<'a> { + bytes: &'a [u8], +} + +impl fmt::Display for HexSlice<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for byte in self.bytes { + write!(f, "{:x}", byte)?; + } + Ok(()) + } +} + +fn get_build_id<'a>(info: &'a dl_phdr_info) -> Option<&'a [u8]> { + for phdr in info.program_headers() { + if phdr.phdr.p_type == PT_NOTE { + for note in phdr.notes() { + if note.tipe == NT_GNU_BUILD_ID && (note.name == b"GNU\0" || note.name == b"GNU") { + return Some(note.desc); + } + } + } + } + None +} + +/// These errors encode issues that arise while parsing information about +/// each DSO. +enum Error { + /// NameError means that an error occurred while converting a C style string + /// into a rust string. + NameError(core::str::Utf8Error), + /// BuildIDError means that we didn't find a build ID. This could either be + /// because the DSO had no build ID or because the segment containing the + /// build ID was malformed. + BuildIDError, +} + +/// Calls either 'dso' or 'error' for each DSO linked into the process by the +/// dynamic linker. +/// +/// # Arguments +/// +/// * `visitor` - A DsoPrinter that will have one of eats methods called foreach DSO. +fn for_each_dso(mut visitor: &mut DsoPrinter) { + extern "C" fn callback(info: &dl_phdr_info, _size: usize, visitor: &mut DsoPrinter) -> i32 { + // dl_iterate_phdr ensures that info.name will point to a valid + // location. + let name_len = unsafe { libc::strlen(info.name) }; + let name_slice: &[u8] = + unsafe { core::slice::from_raw_parts(info.name as *const u8, name_len) }; + let name = match core::str::from_utf8(name_slice) { + Ok(name) => name, + Err(err) => { + return visitor.error(Error::NameError(err)) as i32; + } + }; + let build_id = match get_build_id(info) { + Some(build_id) => build_id, + None => { + return visitor.error(Error::BuildIDError) as i32; + } + }; + visitor.dso(Dso { + name: name, + build_id: build_id, + phdrs: info.phdr_slice(), + base: info.addr as usize, + }) as i32 + } + unsafe { dl_iterate_phdr(callback, &mut visitor) }; +} + +struct DsoPrinter<'a, 'b> { + writer: &'a mut core::fmt::Formatter<'b>, + module_count: usize, + error: core::fmt::Result, +} + +impl DsoPrinter<'_, '_> { + fn dso(&mut self, dso: Dso<'_>) -> bool { + let mut write = || { + write!( + self.writer, + "{{{{{{module:{:#x}:{}:elf:{}}}}}}}\n", + self.module_count, + dso.name, + HexSlice { + bytes: dso.build_id.as_ref() + } + )?; + for seg in dso.segments() { + write!( + self.writer, + "{{{{{{mmap:{:#x}:{:#x}:load:{:#x}:{}:{:#x}}}}}}}\n", + seg.addr, seg.size, self.module_count, seg.flags, seg.mod_rel_addr + )?; + } + self.module_count += 1; + Ok(()) + }; + match write() { + Ok(()) => false, + Err(err) => { + self.error = Err(err); + true + } + } + } + fn error(&mut self, _error: Error) -> bool { + false + } +} + +/// This function prints the Fuchsia symbolizer markup for all information contained in a DSO. +pub fn print_dso_context(out: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + out.write_str("{{{reset}}}\n")?; + let mut visitor = DsoPrinter { + writer: out, + module_count: 0, + error: Ok(()), + }; + for_each_dso(&mut visitor); + visitor.error +} diff --git a/vendor/backtrace/src/symbolize/dladdr.rs b/vendor/backtrace/src/symbolize/dladdr.rs index 84f1622d81..9509e9986c 100644 --- a/vendor/backtrace/src/symbolize/dladdr.rs +++ b/vendor/backtrace/src/symbolize/dladdr.rs @@ -63,7 +63,9 @@ cfg_if::cfg_if! { inner: mem::zeroed(), _marker: marker::PhantomData, }; - if libc::dladdr(addr as *mut _, &mut info.inner) != 0 { + // Skip null addresses to avoid calling into libc and having it do + // things with the dynamic symbol table for no reason. + if !addr.is_null() && libc::dladdr(addr as *mut _, &mut info.inner) != 0 { cb(info) } } diff --git a/vendor/backtrace/src/symbolize/gimli.rs b/vendor/backtrace/src/symbolize/gimli.rs index 7af1e5a8cc..c1f4be50e2 100644 --- a/vendor/backtrace/src/symbolize/gimli.rs +++ b/vendor/backtrace/src/symbolize/gimli.rs @@ -18,8 +18,9 @@ use findshlibs::{self, Segment, SharedLibrary}; use libc::c_void; use memmap::Mmap; use std::env; +use std::ffi::OsString; use std::fs::File; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::prelude::v1::*; const MAPPINGS_CACHE_SIZE: usize = 4; @@ -207,6 +208,10 @@ cfg_if::cfg_if! { struct Object<'a> { elf: Elf<'a>, data: &'a [u8], + // List of pre-parsed and sorted symbols by base address. The + // boolean indicates whether it comes from the dynamic symbol table + // or the normal symbol table, affecting where it's symbolicated. + syms: Vec<(goblin::elf::Sym, bool)>, } impl<'a> Object<'a> { @@ -215,7 +220,32 @@ cfg_if::cfg_if! { if !elf.little_endian { return None; } - Some(Object { elf, data }) + let mut syms = elf + .syms + .iter() + .map(|s| (s, false)) + .chain(elf.dynsyms.iter().map(|s| (s, true))) + // Only look at function/object symbols. This mirrors what + // libbacktrace does and in general we're only symbolicating + // function addresses in theory. Object symbols correspond + // to data, and maybe someone's crazy enough to have a + // function go into static data? + .filter(|(s, _)| { + s.is_function() || s.st_type() == goblin::elf::sym::STT_OBJECT + }) + // skip anything that's in an undefined section header, + // since it means it's an imported function and we're only + // symbolicating with locally defined functions. + .filter(|(s, _)| { + s.st_shndx != goblin::elf::section_header::SHN_UNDEF as usize + }) + .collect::>(); + syms.sort_unstable_by_key(|s| s.0.st_value); + Some(Object { + syms, + elf, + data, + }) } fn section(&self, name: &str) -> Option<&'a [u8]> { @@ -233,9 +263,22 @@ cfg_if::cfg_if! { } fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> { - let sym = self.elf.syms.iter() - .find(|sym| sym.st_value <= addr && addr <= sym.st_value + sym.st_size)?; - Some(self.elf.strtab.get(sym.st_name)?.ok()?.as_bytes()) + // Same sort of binary search as Windows above + let i = match self.syms.binary_search_by_key(&addr, |s| s.0.st_value) { + Ok(i) => i, + Err(i) => i.checked_sub(1)?, + }; + let (sym, dynamic) = self.syms.get(i)?; + if sym.st_value <= addr && addr <= sym.st_value + sym.st_size { + let strtab = if *dynamic { + &self.elf.dynstrtab + } else { + &self.elf.strtab + }; + Some(strtab.get(sym.st_name)?.ok()?.as_bytes()) + } else { + None + } } } } @@ -318,46 +361,128 @@ impl Mapping { .next() } } +} - // Ensure the 'static lifetimes don't leak. - fn rent(&self, mut f: F) - where - F: FnMut(&Context<'_>), - { - f(&self.cx) - } +#[derive(Default)] +struct Cache { + /// All known shared libraries that have been loaded. + libraries: Vec, + + /// Mappings cache where we retain parsed dwarf information. + /// + /// This list has a fixed capacity for its entire liftime which never + /// increases. The `usize` element of each pair is an index into `libraries` + /// above where `usize::max_value()` represents the current executable. The + /// `Mapping` is corresponding parsed dwarf information. + /// + /// Note that this is basically an LRU cache and we'll be shifting things + /// around in here as we symbolize addresses. + mappings: Vec<(usize, Mapping)>, } -type Cache = Vec<(PathBuf, Mapping)>; +struct Library { + name: OsString, + segments: Vec, + bias: findshlibs::Bias, +} -// unsafe because this is required to be externally synchronized -unsafe fn with_cache(f: impl FnOnce(&mut Cache)) { - // A very small, very simple LRU cache for debug info mappings. - // - // The hit rate should be very high, since the typical stack doesn't cross - // between many shared libraries. - // - // The `addr2line::Context` structures are pretty expensive to create. Its - // cost is expected to be amortized by subsequent `locate` queries, which - // leverage the structures built when constructing `addr2line::Context`s to - // get nice speedups. If we didn't have this cache, that amortization would - // never happen, and symbolicating backtraces would be ssssllllooooowwww. - static mut MAPPINGS_CACHE: Option = None; - - f(MAPPINGS_CACHE.get_or_insert_with(|| Vec::with_capacity(MAPPINGS_CACHE_SIZE))) +struct LibrarySegment { + len: usize, + stated_virtual_memory_address: findshlibs::Svma, } // unsafe because this is required to be externally synchronized pub unsafe fn clear_symbol_cache() { - with_cache(|cache| cache.clear()); + Cache::with_global(|cache| cache.mappings.clear()); } -unsafe fn with_mapping_for_path(path: PathBuf, f: F) -where - F: FnMut(&Context<'_>), -{ - with_cache(|cache| { - let idx = cache.iter().position(|&(ref p, _)| p == &path); +impl Cache { + fn new() -> Cache { + let mut libraries = Vec::new(); + // Iterate over all loaded shared libraries and cache information we + // learn about them. This way we only load information here once instead + // of once per symbol. + findshlibs::TargetSharedLibrary::each(|so| { + use findshlibs::IterationControl::*; + libraries.push(Library { + name: so.name().to_owned(), + segments: so + .segments() + .map(|s| LibrarySegment { + len: s.len(), + stated_virtual_memory_address: s.stated_virtual_memory_address(), + }) + .collect(), + bias: so.virtual_memory_bias(), + }); + Continue + }); + + Cache { + mappings: Vec::with_capacity(MAPPINGS_CACHE_SIZE), + libraries, + } + } + + // unsafe because this is required to be externally synchronized + unsafe fn with_global(f: impl FnOnce(&mut Self)) { + // A very small, very simple LRU cache for debug info mappings. + // + // The hit rate should be very high, since the typical stack doesn't cross + // between many shared libraries. + // + // The `addr2line::Context` structures are pretty expensive to create. Its + // cost is expected to be amortized by subsequent `locate` queries, which + // leverage the structures built when constructing `addr2line::Context`s to + // get nice speedups. If we didn't have this cache, that amortization would + // never happen, and symbolicating backtraces would be ssssllllooooowwww. + static mut MAPPINGS_CACHE: Option = None; + + f(MAPPINGS_CACHE.get_or_insert_with(|| Cache::new())) + } + + fn avma_to_svma(&self, addr: *const u8) -> Option<(usize, findshlibs::Svma)> { + // Note that for now `findshlibs` is unimplemented on Windows, so we + // just unhelpfully assume that the address is an SVMA. Surprisingly it + // seems to at least somewhat work on Wine on Linux though... + // + // This probably means ASLR on Windows is busted. + if cfg!(windows) { + let addr = findshlibs::Svma(addr); + return Some((usize::max_value(), addr)); + } + + self.libraries + .iter() + .enumerate() + .filter_map(|(i, lib)| { + // First up, test if this `lib` has any segment containing the + // `addr` (handling relocation). If this check passes then we + // can continue below and actually translate the address. + // + // Note that this is an inlining of `contains_avma` in the + // `findshlibs` crate here. + if !lib.segments.iter().any(|s| { + let svma = s.stated_virtual_memory_address; + let start = unsafe { svma.0.offset(lib.bias.0) as usize }; + let end = start + s.len; + let address = addr as usize; + start <= address && address < end + }) { + return None; + } + + // Now that we know `lib` contains `addr`, do the equiavlent of + // `avma_to_svma` in the `findshlibs` crate. + let reverse_bias = -lib.bias.0; + let svma = findshlibs::Svma(unsafe { addr.offset(reverse_bias) }); + Some((i, svma)) + }) + .next() + } + + fn mapping_for_lib<'a>(&'a mut self, lib: usize) -> Option<&'a Context<'a>> { + let idx = self.mappings.iter().position(|(idx, _)| *idx == lib); // Invariant: after this conditional completes without early returning // from an error, the cache entry for this path is at index 0. @@ -365,27 +490,35 @@ where if let Some(idx) = idx { // When the mapping is already in the cache, move it to the front. if idx != 0 { - let entry = cache.remove(idx); - cache.insert(0, entry); + let entry = self.mappings.remove(idx); + self.mappings.insert(0, entry); } } else { // When the mapping is not in the cache, create a new mapping, // insert it into the front of the cache, and evict the oldest cache // entry if necessary. - let mapping = match Mapping::new(&path) { - None => return, - Some(m) => m, + let storage; + let path = match self.libraries.get(lib) { + Some(lib) => &lib.name, + None => { + storage = env::current_exe().ok()?.into(); + &storage + } }; + let mapping = Mapping::new(path.as_ref())?; - if cache.len() == MAPPINGS_CACHE_SIZE { - cache.pop(); + if self.mappings.len() == MAPPINGS_CACHE_SIZE { + self.mappings.pop(); } - cache.insert(0, (path, mapping)); + self.mappings.insert(0, (lib, mapping)); } - cache[0].1.rent(f); - }); + let cx: &'a Context<'static> = &self.mappings[0].1.cx; + // don't leak the `'static` lifetime, make sure it's scoped to just + // ourselves + Some(unsafe { mem::transmute::<&'a Context<'static>, &'a Context<'a>>(cx) }) + } } pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) { @@ -396,65 +529,23 @@ pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) { called: false, }; - // First, find the file containing the segment that the given AVMA (after - // relocation) address falls within. Use the containing segment to compute - // the SVMA (before relocation) address. - // - // Note that the OS APIs that `SharedLibrary::each` is implemented with hold - // a lock for the duration of the `each` call, so we want to keep this - // section as short as possible to avoid contention with other threads - // capturing backtraces. - // - // Also note that for now `findshlibs` is unimplemented on Windows, so we - // just unhelpfully assume that the address is an SVMA. Surprisingly it - // seems to at least somewhat work on Wine on Linux though... - let (addr, path) = if cfg!(windows) { - let addr = findshlibs::Svma(addr as *mut u8 as *const u8); - (addr, String::new()) - } else { - let addr = findshlibs::Avma(addr as *mut u8 as *const u8); - let mut so_info = None; - findshlibs::TargetSharedLibrary::each(|so| { - use findshlibs::IterationControl::*; - - for segment in so.segments() { - if segment.contains_avma(so, addr) { - let addr = so.avma_to_svma(addr); - let path = so.name().to_string_lossy(); - so_info = Some((addr, path.to_string())); - return Break; - } - } - - Continue - }); - match so_info { + Cache::with_global(|cache| { + let (lib, addr) = match cache.avma_to_svma(addr as *const u8) { + Some(pair) => pair, None => return, - Some((a, p)) => (a, p), - } - }; - - // Second, fixup the path. Empty path means that this address falls within - // the main executable, not a shared library. - let path = if path.is_empty() { - match env::current_exe() { - Err(_) => return, - Ok(p) => p, - } - } else { - PathBuf::from(path) - }; + }; - // Finally, get a cached mapping or create a new mapping for this file, and - // evaluate the DWARF info to find the file/line/name for this address. - with_mapping_for_path(path, |cx| { - let mut called = false; + // Finally, get a cached mapping or create a new mapping for this file, and + // evaluate the DWARF info to find the file/line/name for this address. + let cx = match cache.mapping_for_lib(lib) { + Some(cx) => cx, + None => return, + }; if let Ok(mut frames) = cx.dwarf.find_frames(addr.0 as u64) { while let Ok(Some(mut frame)) = frames.next() { let function = frame.function.take(); let name = function.as_ref().and_then(|f| f.raw_name().ok()); let name = name.as_ref().map(|n| n.as_bytes()); - called = true; cb.call(Symbol::Frame { addr: addr.0 as *mut c_void, frame, @@ -463,7 +554,7 @@ pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) { } } - if !called { + if !cb.called { if let Some(name) = cx.object.search_symtab(addr.0 as u64) { cb.call(Symbol::Symtab { addr: addr.0 as *mut c_void, diff --git a/vendor/backtrace/src/symbolize/mod.rs b/vendor/backtrace/src/symbolize/mod.rs index 2aaf19f35c..ade1e74cb8 100644 --- a/vendor/backtrace/src/symbolize/mod.rs +++ b/vendor/backtrace/src/symbolize/mod.rs @@ -496,6 +496,7 @@ cfg_if::cfg_if! { unsafe fn clear_symbol_cache_imp() {} } else if #[cfg(all(unix, not(target_os = "emscripten"), + not(target_os = "fuchsia"), feature = "dladdr"))] { mod dladdr_resolve; use self::dladdr_resolve::resolve as resolve_imp; @@ -505,6 +506,7 @@ cfg_if::cfg_if! { mod noop; use self::noop::resolve as resolve_imp; use self::noop::Symbol as SymbolImp; + #[allow(unused)] unsafe fn clear_symbol_cache_imp() {} } } diff --git a/vendor/backtrace/src/types.rs b/vendor/backtrace/src/types.rs index be522129f5..f7bcb17da3 100644 --- a/vendor/backtrace/src/types.rs +++ b/vendor/backtrace/src/types.rs @@ -6,6 +6,7 @@ cfg_if::cfg_if! { use std::fmt; use std::path::PathBuf; use std::prelude::v1::*; + use std::str; } } @@ -47,32 +48,30 @@ impl<'a> BytesOrWideString<'a> { pub fn into_path_buf(self) -> PathBuf { #[cfg(unix)] { - use self::BytesOrWideString::*; use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; - match self { - Bytes(slice) => PathBuf::from(OsStr::from_bytes(slice)), - _ => unreachable!(), + if let BytesOrWideString::Bytes(slice) = self { + return PathBuf::from(OsStr::from_bytes(slice)); } } #[cfg(windows)] { - use self::BytesOrWideString::*; use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; - match self { - Wide(slice) => PathBuf::from(OsString::from_wide(slice)), - _ => unreachable!(), + if let BytesOrWideString::Wide(slice) = self { + return PathBuf::from(OsString::from_wide(slice)); } } - #[cfg(all(not(windows), not(unix)))] - { - unreachable!() + if let BytesOrWideString::Bytes(b) = self { + if let Ok(s) = str::from_utf8(b) { + return PathBuf::from(s); + } } + unreachable!() } } diff --git a/vendor/backtrace/src/windows.rs b/vendor/backtrace/src/windows.rs index 2a9f70899b..a2305704aa 100644 --- a/vendor/backtrace/src/windows.rs +++ b/vendor/backtrace/src/windows.rs @@ -28,6 +28,7 @@ cfg_if::cfg_if! { pub use winapi::um::winnt::*; pub use winapi::um::fileapi::*; pub use winapi::um::minwinbase::*; + pub use winapi::um::synchapi::*; } } else { pub use core::ffi::c_void; @@ -314,6 +315,7 @@ ffi! { pub const FILE_SHARE_WRITE: DWORD = 0x2; pub const OPEN_EXISTING: DWORD = 0x3; pub const GENERIC_READ: DWORD = 0x80000000; + pub const INFINITE: DWORD = !0; pub type DWORD = u32; pub type PDWORD = *mut u32; @@ -363,6 +365,17 @@ ffi! { dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, ) -> HANDLE; + pub fn CreateMutexA( + attrs: LPSECURITY_ATTRIBUTES, + initial: BOOL, + name: LPCSTR, + ) -> HANDLE; + pub fn ReleaseMutex(hMutex: HANDLE) -> BOOL; + pub fn WaitForSingleObjectEx( + hHandle: HANDLE, + dwMilliseconds: DWORD, + bAlertable: BOOL, + ) -> DWORD; } } diff --git a/vendor/backtrace/tests/concurrent-panics.rs b/vendor/backtrace/tests/concurrent-panics.rs new file mode 100644 index 0000000000..ac1d61d652 --- /dev/null +++ b/vendor/backtrace/tests/concurrent-panics.rs @@ -0,0 +1,72 @@ +use std::env; +use std::panic; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; +use std::sync::Arc; +use std::thread; + +const PANICS: usize = 100; +const THREADS: usize = 8; +const VAR: &str = "__THE_TEST_YOU_ARE_LUKE"; + +fn main() { + // These run in docker containers on CI where they can't re-exec the test, + // so just skip these for CI. No other reason this can't run on those + // platforms though. + if cfg!(unix) && (cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64")) { + println!("test result: ok"); + return; + } + + if env::var(VAR).is_err() { + parent(); + } else { + child(); + } +} + +fn parent() { + let me = env::current_exe().unwrap(); + let result = Command::new(&me) + .env("RUST_BACKTRACE", "1") + .env(VAR, "1") + .output() + .unwrap(); + if result.status.success() { + println!("test result: ok"); + return; + } + println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout)); + println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr)); + println!("code: {}", result.status); + panic!(); +} + +fn child() { + let done = Arc::new(AtomicBool::new(false)); + let done2 = done.clone(); + let a = thread::spawn(move || { + while !done2.load(SeqCst) { + format!("{:?}", backtrace::Backtrace::new()); + } + }); + + let threads = (0..THREADS) + .map(|_| { + thread::spawn(|| { + for _ in 0..PANICS { + assert!(panic::catch_unwind(|| { + panic!(); + }) + .is_err()); + } + }) + }) + .collect::>(); + for thread in threads { + thread.join().unwrap(); + } + + done.store(true, SeqCst); + a.join().unwrap(); +} diff --git a/vendor/byteorder/.cargo-checksum.json b/vendor/byteorder/.cargo-checksum.json index e46d9f0bc0..28e4e34dd4 100644 --- a/vendor/byteorder/.cargo-checksum.json +++ b/vendor/byteorder/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"dc0a497d6932b874a32c1a457e344bdcd27a1767a174d163f19d66b837477a08","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"9f119d940ff1131bb71fb7c2b10c36ae91b45dbcf010975ccc555268a5b79165","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"97c01a66dbff4615acd49a8c3a85d137bf29cc113fa514910195bb11aef445bc","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"5dbfb724aa137efdff2cf0faeb728a3d302eda097ba5189de2d82314ce500654","src/io.rs":"d9759a25c625aa341b23bdb489144b1e9554db11bc2fa799a2a6ecfbc442ea5e","src/lib.rs":"fd18e7969a80314537ba41b3c460284975c0d4df4b72f27527506cb5bd889ae8"},"package":"94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"} \ No newline at end of file +{"files":{"CHANGELOG.md":"51f0eb3b6139fc1a908d41a7b3cba7d58d684700986b3518f82e5af254c39e8e","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"51bf020d4e355a8548f1e1bbcb35828f457bb96874fb4124317c6485d74d00c6","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"b2dd89866b56f619661b90e8b3b7d3f741b0a8d5710e229df86843ae0881284f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"80e43e07f34bc6d3ebe4f37cea79ba02cafce6cf30b737a1db65de55f2c38ca5","build.rs":"088c35c11be1e443c4462c7fe2863bcf885805e7b0f3dc7d83e6091ff197e779","src/io.rs":"8f22d1b0e01fa4ce9c7c5cd727dbc40ca35c22d9c82fe8d324d9d83d37cdcc4a","src/lib.rs":"7ee13d5784c7d8e79a8bd8810868584b8780d96fddcd3d727b69f8c861fd7cb1"},"package":"a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"} \ No newline at end of file diff --git a/vendor/byteorder/CHANGELOG.md b/vendor/byteorder/CHANGELOG.md index 066878b219..020beb4649 100644 --- a/vendor/byteorder/CHANGELOG.md +++ b/vendor/byteorder/CHANGELOG.md @@ -1,3 +1,46 @@ +1.3.0 +===== +This new minor release now enables `i128` support automatically on Rust +compilers that support 128-bit integers. The `i128` feature is now a no-op, but +continues to exist for backward compatibility purposes. The crate continues to +maintain compatibility with Rust 1.12.0. + +This release also deprecates the `ByteOrder` trait methods +`read_f32_into_unchecked` and `read_f64_into_unchecked` in favor of +`read_f32_into` and `read_f64_into`. This was an oversight from the 1.2 release +where the corresponding methods on `ReadBytesExt` were deprecated. + +`quickcheck` and `rand` were bumped to `0.8` and `0.6`, respectively. + +A few small documentation related bugs have been fixed. + + +1.2.7 +===== +This patch release excludes some CI files from the crate release and updates +the license field to use `OR` instead of `/`. + + +1.2.6 +===== +This patch release fixes some test compilation errors introduced by an +over-eager release of 1.2.5. + + +1.2.5 +===== +This patch release fixes some typos in the docs, adds doc tests to methods on +`WriteByteExt` and bumps the quickcheck dependency to `0.7`. + + +1.2.4 +===== +This patch release adds support for 48-bit integers by adding the following +methods to the `ByteOrder` trait: `read_u48`, `read_i48`, `write_u48` and +`write_i48`. Corresponding methods have been added to the `ReadBytesExt` and +`WriteBytesExt` traits as well. + + 1.2.3 ===== This patch release removes the use of `feature(i128_type)` from byteorder, diff --git a/vendor/byteorder/Cargo.toml b/vendor/byteorder/Cargo.toml index 4ddaae793a..fb2acad122 100644 --- a/vendor/byteorder/Cargo.toml +++ b/vendor/byteorder/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,8 +12,9 @@ [package] name = "byteorder" -version = "1.2.7" +version = "1.3.2" authors = ["Andrew Gallant "] +build = "build.rs" exclude = ["/ci/*"] description = "Library for reading/writing numbers in big-endian and little-endian." homepage = "https://github.com/BurntSushi/byteorder" @@ -29,12 +30,15 @@ opt-level = 3 [lib] name = "byteorder" bench = false +[dev-dependencies.doc-comment] +version = "0.3" + [dev-dependencies.quickcheck] -version = "0.7" +version = "0.8" default-features = false [dev-dependencies.rand] -version = "0.5" +version = "0.6" [features] default = ["std"] diff --git a/vendor/byteorder/README.md b/vendor/byteorder/README.md index f282ab72e0..8940b29519 100644 --- a/vendor/byteorder/README.md +++ b/vendor/byteorder/README.md @@ -1,5 +1,5 @@ -This crate provides convenience methods for encoding and decoding numbers in -either big-endian or little-endian order. +This crate provides convenience methods for encoding and decoding +numbers in either big-endian or little-endian order. [![Build status](https://api.travis-ci.org/BurntSushi/byteorder.svg)](https://travis-ci.org/BurntSushi/byteorder) [![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder) @@ -54,3 +54,10 @@ in a `no_std` context, add the following to your `Cargo.toml`: [dependencies] byteorder = { version = "1", default-features = false } ``` + + +### Alternatives + +Note that as of Rust 1.32, the standard numeric types provide built-in methods +like `to_le_bytes` and `from_le_bytes`, which support some of the same use +cases. diff --git a/vendor/byteorder/benches/bench.rs b/vendor/byteorder/benches/bench.rs index 39824766a9..d53d25e4b5 100644 --- a/vendor/byteorder/benches/bench.rs +++ b/vendor/byteorder/benches/bench.rs @@ -148,108 +148,108 @@ bench_num!(int_6, read_int, 6, [1, 2, 3, 4, 5, 6]); bench_num!(int_7, read_int, 7, [1, 2, 3, 4, 5, 6, 7]); bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(u128, MAX, read_u128, write_u128, 16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(i128, MAX, read_i128, write_i128, 16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_1, read_uint128, 1, [1]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_2, read_uint128, 2, [1, 2]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_3, read_uint128, 3, [1, 2, 3]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_4, read_uint128, 4, [1, 2, 3, 4]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_5, read_uint128, 5, [1, 2, 3, 4, 5]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_6, read_uint128, 6, [1, 2, 3, 4, 5, 6]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_7, read_uint128, 7, [1, 2, 3, 4, 5, 6, 7]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_8, read_uint128, 8, [1, 2, 3, 4, 5, 6, 7, 8]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_9, read_uint128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_10, read_uint128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_11, read_uint128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_12, read_uint128, 12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_13, read_uint128, 13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_14, read_uint128, 14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_15, read_uint128, 15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(uint128_16, read_uint128, 16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_1, read_int128, 1, [1]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_2, read_int128, 2, [1, 2]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_3, read_int128, 3, [1, 2, 3]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_4, read_int128, 4, [1, 2, 3, 4]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_5, read_int128, 5, [1, 2, 3, 4, 5]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_6, read_int128, 6, [1, 2, 3, 4, 5, 6]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_7, read_int128, 7, [1, 2, 3, 4, 5, 6, 7]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_8, read_int128, 8, [1, 2, 3, 4, 5, 6, 7, 8]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_9, read_int128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_10, read_int128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_11, read_int128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_12, read_int128, 12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_13, read_int128, 13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_14, read_int128, 14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_15, read_int128, 15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] bench_num!(int128_16, read_int128, 16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); diff --git a/vendor/byteorder/build.rs b/vendor/byteorder/build.rs new file mode 100644 index 0000000000..002135b645 --- /dev/null +++ b/vendor/byteorder/build.rs @@ -0,0 +1,87 @@ +use std::env; +use std::ffi::OsString; +use std::io::{self, Write}; +use std::process::Command; + +fn main() { + let version = match Version::read() { + Ok(version) => version, + Err(err) => { + writeln!( + &mut io::stderr(), + "failed to parse `rustc --version`: {}", + err + ).unwrap(); + return; + } + }; + enable_i128(version); +} + +fn enable_i128(version: Version) { + if version < (Version { major: 1, minor: 26, patch: 0 }) { + return; + } + + println!("cargo:rustc-cfg=byteorder_i128"); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +struct Version { + major: u32, + minor: u32, + patch: u32, +} + +impl Version { + fn read() -> Result { + let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc")); + let output = Command::new(&rustc) + .arg("--version") + .output() + .unwrap() + .stdout; + Version::parse(&String::from_utf8(output).unwrap()) + } + + fn parse(mut s: &str) -> Result { + if !s.starts_with("rustc ") { + return Err(format!("unrecognized version string: {}", s)); + } + s = &s["rustc ".len()..]; + + let parts: Vec<&str> = s.split(".").collect(); + if parts.len() < 3 { + return Err(format!("not enough version parts: {:?}", parts)); + } + + let mut num = String::new(); + for c in parts[0].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let major = try!(num.parse::().map_err(|e| e.to_string())); + + num.clear(); + for c in parts[1].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let minor = try!(num.parse::().map_err(|e| e.to_string())); + + num.clear(); + for c in parts[2].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let patch = try!(num.parse::().map_err(|e| e.to_string())); + + Ok(Version { major: major, minor: minor, patch: patch }) + } +} diff --git a/vendor/byteorder/src/io.rs b/vendor/byteorder/src/io.rs index 74cf9dd3d9..ed6a848451 100644 --- a/vendor/byteorder/src/io.rs +++ b/vendor/byteorder/src/io.rs @@ -370,7 +370,7 @@ pub trait ReadBytesExt: io::Read { /// ]); /// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::().unwrap()); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128(&mut self) -> Result { let mut buf = [0; 16]; @@ -391,14 +391,13 @@ pub trait ReadBytesExt: io::Read { /// Read a signed 128 bit big-endian integer from a `Read`: /// /// ```rust - /// #![feature(i128_type)] /// use std::io::Cursor; /// use byteorder::{BigEndian, ReadBytesExt}; /// /// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// assert_eq!(i128::min_value(), rdr.read_i128::().unwrap()); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_i128(&mut self) -> Result { let mut buf = [0; 16]; @@ -457,7 +456,7 @@ pub trait ReadBytesExt: io::Read { } /// Reads an unsigned n-bytes integer from the underlying reader. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_uint128(&mut self, nbytes: usize) -> Result { let mut buf = [0; 16]; @@ -466,7 +465,7 @@ pub trait ReadBytesExt: io::Read { } /// Reads a signed n-bytes integer from the underlying reader. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_int128(&mut self, nbytes: usize) -> Result { let mut buf = [0; 16]; @@ -672,7 +671,7 @@ pub trait ReadBytesExt: io::Read { /// rdr.read_u128_into::(&mut dst).unwrap(); /// assert_eq!([517, 768], dst); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128_into( &mut self, @@ -686,6 +685,42 @@ pub trait ReadBytesExt: io::Read { Ok(()) } + /// Reads a sequence of signed 8 bit integers from the underlying reader. + /// + /// The given buffer is either filled completely or an error is returned. + /// If an error is returned, the contents of `dst` are unspecified. + /// + /// Note that since each `i8` is a single byte, no byte order conversions + /// are used. This method is included because it provides a safe, simple + /// way for the caller to read into a `&mut [i8]` buffer. (Without this + /// method, the caller would have to either use `unsafe` code or convert + /// each byte to `i8` individually.) + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read a sequence of signed 8 bit integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![2, 251, 3]); + /// let mut dst = [0; 3]; + /// rdr.read_i8_into(&mut dst).unwrap(); + /// assert_eq!([2, -5, 3], dst); + /// ``` + #[inline] + fn read_i8_into(&mut self, dst: &mut [i8]) -> Result<()> { + let buf = unsafe { slice_to_u8_mut(dst) }; + self.read_exact(buf) + } + /// Reads a sequence of signed 16 bit integers from the underlying /// reader. /// @@ -822,7 +857,7 @@ pub trait ReadBytesExt: io::Read { /// rdr.read_i128_into::(&mut dst).unwrap(); /// assert_eq!([517, 768], dst); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_i128_into( &mut self, @@ -1373,7 +1408,7 @@ pub trait WriteBytesExt: io::Write { } /// Writes an unsigned 128 bit integer to the underlying writer. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_u128(&mut self, n: u128) -> Result<()> { let mut buf = [0; 16]; @@ -1382,7 +1417,7 @@ pub trait WriteBytesExt: io::Write { } /// Writes a signed 128 bit integer to the underlying writer. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_i128(&mut self, n: i128) -> Result<()> { let mut buf = [0; 16]; @@ -1466,7 +1501,7 @@ pub trait WriteBytesExt: io::Write { /// /// If the given integer is not representable in the given number of bytes, /// this method panics. If `nbytes > 16`, this method panics. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_uint128( &mut self, @@ -1482,7 +1517,7 @@ pub trait WriteBytesExt: io::Write { /// /// If the given integer is not representable in the given number of bytes, /// this method panics. If `nbytes > 16`, this method panics. - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_int128( &mut self, diff --git a/vendor/byteorder/src/lib.rs b/vendor/byteorder/src/lib.rs index 77bfdcfca8..db4d24d812 100644 --- a/vendor/byteorder/src/lib.rs +++ b/vendor/byteorder/src/lib.rs @@ -1,6 +1,6 @@ /*! -This crate provides convenience methods for encoding and decoding numbers -in either [big-endian or little-endian order]. +This crate provides convenience methods for encoding and decoding numbers in +either [big-endian or little-endian order]. The organization of the crate is pretty simple. A trait, [`ByteOrder`], specifies byte conversion methods for each type of number in Rust (sans numbers that have @@ -49,6 +49,12 @@ when built with the `i128` feature enabled. This crate can also be used without the standard library. +# Alternatives + +Note that as of Rust 1.32, the standard numeric types provide built-in methods +like `to_le_bytes` and `from_le_bytes`, which support some of the same use +cases. + [big-endian or little-endian order]: https://en.wikipedia.org/wiki/Endianness [`ByteOrder`]: trait.ByteOrder.html [`BigEndian`]: enum.BigEndian.html @@ -67,6 +73,13 @@ This crate can also be used without the standard library. #[cfg(feature = "std")] extern crate core; +#[cfg(test)] +#[macro_use] +extern crate doc_comment; + +#[cfg(test)] +doctest!("../README.md"); + use core::fmt::Debug; use core::hash::Hash; use core::ptr::copy_nonoverlapping; @@ -84,7 +97,7 @@ fn extend_sign(val: u64, nbytes: usize) -> i64 { (val << shift) as i64 >> shift } -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] #[inline] fn extend_sign128(val: u128, nbytes: usize) -> i128 { let shift = (16 - nbytes) * 8; @@ -97,7 +110,7 @@ fn unextend_sign(val: i64, nbytes: usize) -> u64 { (val << shift) as u64 >> shift } -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] #[inline] fn unextend_sign128(val: i128, nbytes: usize) -> u128 { let shift = (16 - nbytes) * 8; @@ -125,7 +138,7 @@ fn pack_size(n: u64) -> usize { } } -#[cfg(feature = "i128")] +#[cfg(byteorder_i128)] #[inline] fn pack_size128(n: u128) -> usize { if n < 1 << 8 { @@ -200,8 +213,8 @@ mod private { /// use byteorder::{ByteOrder, BigEndian}; /// /// let mut buf = [0; 2]; -/// BigEndian::write_i16(&mut buf, -50_000); -/// assert_eq!(-50_000, BigEndian::read_i16(&buf)); +/// BigEndian::write_i16(&mut buf, -5_000); +/// assert_eq!(-5_000, BigEndian::read_i16(&buf)); /// ``` /// /// [`BigEndian`]: enum.BigEndian.html @@ -314,7 +327,7 @@ pub trait ByteOrder /// LittleEndian::write_u128(&mut buf, 1_000_000); /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn read_u128(buf: &[u8]) -> u128; /// Reads an unsigned n-bytes integer from `buf`. @@ -355,7 +368,7 @@ pub trait ByteOrder /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3); /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn read_uint128(buf: &[u8], nbytes: usize) -> u128; /// Writes an unsigned 16 bit integer `n` to `buf`. @@ -372,8 +385,8 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut buf = [0; 2]; - /// LittleEndian::write_u16(&mut buf, 1_000_000); - /// assert_eq!(1_000_000, LittleEndian::read_u16(&buf)); + /// LittleEndian::write_u16(&mut buf, 1_000); + /// assert_eq!(1_000, LittleEndian::read_u16(&buf)); /// ``` fn write_u16(buf: &mut [u8], n: u16); @@ -474,7 +487,7 @@ pub trait ByteOrder /// LittleEndian::write_u128(&mut buf, 1_000_000); /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn write_u128(buf: &mut [u8], n: u128); /// Writes an unsigned integer `n` to `buf` using only `nbytes`. @@ -515,7 +528,7 @@ pub trait ByteOrder /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3); /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize); /// Reads a signed 16 bit integer from `buf`. @@ -645,7 +658,7 @@ pub trait ByteOrder /// LittleEndian::write_i128(&mut buf, -1_000_000_000); /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_i128(buf: &[u8]) -> i128 { Self::read_u128(buf) as i128 @@ -692,7 +705,7 @@ pub trait ByteOrder /// LittleEndian::write_int128(&mut buf, -1_000, 3); /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_int128(buf: &[u8], nbytes: usize) -> i128 { extend_sign128(Self::read_uint128(buf, nbytes), nbytes) @@ -871,7 +884,7 @@ pub trait ByteOrder /// LittleEndian::write_i128(&mut buf, -1_000_000_000); /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_i128(buf: &mut [u8], n: i128) { Self::write_u128(buf, n as u128) @@ -918,7 +931,7 @@ pub trait ByteOrder /// LittleEndian::write_int128(&mut buf, -1_000, 3); /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3)); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) { Self::write_uint128(buf, unextend_sign128(n, nbytes), nbytes) @@ -1062,7 +1075,7 @@ pub trait ByteOrder /// LittleEndian::read_u128_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn read_u128_into(src: &[u8], dst: &mut [u128]); /// Reads signed 16 bit integers from `src` to `dst`. @@ -1079,7 +1092,7 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 8]; - /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// let numbers_given = [1, 2, 0x0f, 0xee]; /// LittleEndian::write_i16_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0; 4]; @@ -1173,7 +1186,7 @@ pub trait ByteOrder /// LittleEndian::read_i128_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_i128_into(src: &[u8], dst: &mut [i128]) { let dst = unsafe { @@ -1197,21 +1210,52 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 16]; - /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0.0; 4]; - /// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got); + /// LittleEndian::read_f32_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` #[inline] - fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) { + fn read_f32_into(src: &[u8], dst: &mut [f32]) { let dst = unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len()) }; Self::read_u32_into(src, dst); } + /// **DEPRECATED**. + /// + /// This method is deprecated. Use `read_f32_into` instead. + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; + /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + #[inline] + #[deprecated(since="1.3.0", note="please use `read_f32_into` instead")] + fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) { + Self::read_f32_into(src, dst); + } + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from /// `src` into `dst`. /// @@ -1227,21 +1271,53 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 32]; - /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0.0; 4]; - /// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got); + /// LittleEndian::read_f64_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` #[inline] - fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) { + fn read_f64_into(src: &[u8], dst: &mut [f64]) { let dst = unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len()) }; Self::read_u64_into(src, dst); } + /// **DEPRECATED**. + /// + /// This method is deprecated. Use `read_f64_into` instead. + /// + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; + /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + #[inline] + #[deprecated(since="1.3.0", note="please use `read_f64_into` instead")] + fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) { + Self::read_f64_into(src, dst); + } + /// Writes unsigned 16 bit integers from `src` into `dst`. /// /// # Panics @@ -1332,7 +1408,7 @@ pub trait ByteOrder /// LittleEndian::read_u128_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn write_u128_into(src: &[u128], dst: &mut [u8]); /// Writes signed 16 bit integers from `src` into `dst`. @@ -1349,7 +1425,7 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 8]; - /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// let numbers_given = [1, 2, 0x0f, 0xee]; /// LittleEndian::write_i16_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0; 4]; @@ -1440,7 +1516,7 @@ pub trait ByteOrder /// LittleEndian::read_i128_into(&bytes, &mut numbers_got); /// assert_eq!(numbers_given, numbers_got); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn write_i128_into(src: &[i128], dst: &mut [u8]) { let src = unsafe { slice::from_raw_parts(src.as_ptr() as *const u128, src.len()) @@ -1463,12 +1539,12 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 16]; - /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0.0; 4]; /// unsafe { - /// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got); + /// LittleEndian::read_f32_into(&bytes, &mut numbers_got); /// } /// assert_eq!(numbers_given, numbers_got); /// ``` @@ -1494,12 +1570,12 @@ pub trait ByteOrder /// use byteorder::{ByteOrder, LittleEndian}; /// /// let mut bytes = [0; 32]; - /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); /// /// let mut numbers_got = [0.0; 4]; /// unsafe { - /// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got); + /// LittleEndian::read_f64_into(&bytes, &mut numbers_got); /// } /// assert_eq!(numbers_given, numbers_got); /// ``` @@ -1584,7 +1660,7 @@ pub trait ByteOrder /// BigEndian::from_slice_u128(&mut numbers); /// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] fn from_slice_u128(numbers: &mut [u128]); /// Converts the given slice of signed 16 bit integers to a particular @@ -1600,9 +1676,9 @@ pub trait ByteOrder /// ```rust /// use byteorder::{ByteOrder, BigEndian}; /// - /// let mut numbers = [5, 65000]; + /// let mut numbers = [5, 6500]; /// BigEndian::from_slice_i16(&mut numbers); - /// assert_eq!(numbers, [5i16.to_be(), 65000i16.to_be()]); + /// assert_eq!(numbers, [5i16.to_be(), 6500i16.to_be()]); /// ``` #[inline] fn from_slice_i16(src: &mut [i16]) { @@ -1679,7 +1755,7 @@ pub trait ByteOrder /// BigEndian::from_slice_i128(&mut numbers); /// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]); /// ``` - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn from_slice_i128(src: &mut [i128]) { let src = unsafe { @@ -1782,8 +1858,8 @@ pub type LE = LittleEndian; /// use byteorder::{ByteOrder, NetworkEndian, BigEndian}; /// /// let mut buf = [0; 2]; -/// BigEndian::write_i16(&mut buf, -50_000); -/// assert_eq!(-50_000, NetworkEndian::read_i16(&buf)); +/// BigEndian::write_i16(&mut buf, -5_000); +/// assert_eq!(-5_000, NetworkEndian::read_i16(&buf)); /// ``` /// /// [`BigEndian`]: enum.BigEndian.html @@ -1894,7 +1970,7 @@ impl ByteOrder for BigEndian { read_num_bytes!(u64, 8, buf, to_be) } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128(buf: &[u8]) -> u128 { read_num_bytes!(u128, 16, buf, to_be) @@ -1912,7 +1988,7 @@ impl ByteOrder for BigEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len()); @@ -1940,7 +2016,7 @@ impl ByteOrder for BigEndian { write_num_bytes!(u64, 8, n, buf, to_be); } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_u128(buf: &mut [u8], n: u128) { write_num_bytes!(u128, 16, n, buf, to_be); @@ -1959,7 +2035,7 @@ impl ByteOrder for BigEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { assert!(pack_size128(n) <= nbytes && nbytes <= 16); @@ -1988,7 +2064,7 @@ impl ByteOrder for BigEndian { read_slice!(src, dst, 8, to_be); } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128_into(src: &[u8], dst: &mut [u128]) { read_slice!(src, dst, 16, to_be); @@ -2021,7 +2097,7 @@ impl ByteOrder for BigEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_u128_into(src: &[u128], dst: &mut [u8]) { if cfg!(target_endian = "big") { @@ -2058,7 +2134,7 @@ impl ByteOrder for BigEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn from_slice_u128(numbers: &mut [u128]) { if cfg!(target_endian = "little") { @@ -2109,7 +2185,7 @@ impl ByteOrder for LittleEndian { read_num_bytes!(u64, 8, buf, to_le) } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128(buf: &[u8]) -> u128 { read_num_bytes!(u128, 16, buf, to_le) @@ -2126,7 +2202,7 @@ impl ByteOrder for LittleEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len()); @@ -2153,7 +2229,7 @@ impl ByteOrder for LittleEndian { write_num_bytes!(u64, 8, n, buf, to_le); } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_u128(buf: &mut [u8], n: u128) { write_num_bytes!(u128, 16, n, buf, to_le); @@ -2169,7 +2245,7 @@ impl ByteOrder for LittleEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16); @@ -2195,7 +2271,7 @@ impl ByteOrder for LittleEndian { read_slice!(src, dst, 8, to_le); } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn read_u128_into(src: &[u8], dst: &mut [u128]) { read_slice!(src, dst, 16, to_le); @@ -2228,7 +2304,7 @@ impl ByteOrder for LittleEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn write_u128_into(src: &[u128], dst: &mut [u8]) { if cfg!(target_endian = "little") { @@ -2265,7 +2341,7 @@ impl ByteOrder for LittleEndian { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] #[inline] fn from_slice_u128(numbers: &mut [u128]) { if cfg!(target_endian = "big") { @@ -2306,8 +2382,11 @@ mod test { extern crate rand; use self::quickcheck::{QuickCheck, StdGen, Testable}; - use self::rand::{Rng, thread_rng}; - #[cfg(feature = "i128")] use self::quickcheck::{Arbitrary, Gen}; + use self::rand::thread_rng; + #[cfg(byteorder_i128)] + use self::rand::Rng; + #[cfg(byteorder_i128)] + use self::quickcheck::{Arbitrary, Gen}; pub const U24_MAX: u32 = 16_777_215; pub const I24_MAX: i32 = 8_388_607; @@ -2327,7 +2406,7 @@ mod test { #[derive(Clone, Debug)] pub struct Wi128(pub T); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] impl Wi128 { pub fn clone(&self) -> T { self.0.clone() @@ -2340,7 +2419,7 @@ mod test { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] impl Arbitrary for Wi128 { fn arbitrary(gen: &mut G) -> Wi128 { let max = calc_max!(::core::u128::MAX, gen.size(), 16); @@ -2351,7 +2430,7 @@ mod test { } } - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] impl Arbitrary for Wi128 { fn arbitrary(gen: &mut G) -> Wi128 { let max = calc_max!(::core::i128::MAX, gen.size(), 16); @@ -2464,9 +2543,9 @@ mod test { qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32); qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_u128, Wi128, 16 + 1, read_u128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_i128, Wi128, 16 + 1, read_i128, write_i128); qc_byte_order!(prop_uint_1, @@ -2486,52 +2565,52 @@ mod test { qc_byte_order!(prop_uint_8, u64, calc_max!(super::U64_MAX, 8), 8, read_uint, write_uint); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_1, Wi128, 1, 1, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_2, Wi128, 2, 2, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_3, Wi128, 3, 3, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_4, Wi128, 4, 4, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_5, Wi128, 5, 5, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_6, Wi128, 6, 6, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_7, Wi128, 7, 7, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_8, Wi128, 8, 8, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_9, Wi128, 9, 9, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_10, Wi128, 10, 10, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_11, Wi128, 11, 11, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_12, Wi128, 12, 12, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_13, Wi128, 13, 13, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_14, Wi128, 14, 14, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_15, Wi128, 15, 15, read_uint128, write_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_uint128_16, Wi128, 16, 16, read_uint128, write_uint128); @@ -2552,52 +2631,52 @@ mod test { qc_byte_order!(prop_int_8, i64, calc_max!(super::I64_MAX, 8), 8, read_int, write_int); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_1, Wi128, 1, 1, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_2, Wi128, 2, 2, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_3, Wi128, 3, 3, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_4, Wi128, 4, 4, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_5, Wi128, 5, 5, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_6, Wi128, 6, 6, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_7, Wi128, 7, 7, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_8, Wi128, 8, 8, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_9, Wi128, 9, 9, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_10, Wi128, 10, 10, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_11, Wi128, 11, 11, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_12, Wi128, 12, 12, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_13, Wi128, 13, 13, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_14, Wi128, 14, 14, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_15, Wi128, 15, 15, read_int128, write_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_byte_order!(prop_int128_16, Wi128, 16, 16, read_int128, write_int128); @@ -2692,9 +2771,9 @@ mod test { too_small!(small_i64, 7, 0, read_i64, write_i64); too_small!(small_f32, 3, 0.0, read_f32, write_f32); too_small!(small_f64, 7, 0.0, read_f64, write_f64); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_u128, 15, 0, read_u128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_i128, 15, 0, read_i128, write_i128); too_small!(small_uint_1, 1, read_uint); @@ -2705,35 +2784,35 @@ mod test { too_small!(small_uint_6, 6, read_uint); too_small!(small_uint_7, 7, read_uint); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_1, 1, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_2, 2, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_3, 3, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_4, 4, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_5, 5, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_6, 6, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_7, 7, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_8, 8, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_9, 9, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_10, 10, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_11, 11, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_12, 12, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_13, 13, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_14, 14, read_uint128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_uint128_15, 15, read_uint128); too_small!(small_int_1, 1, read_int); @@ -2744,35 +2823,35 @@ mod test { too_small!(small_int_6, 6, read_int); too_small!(small_int_7, 7, read_int); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_1, 1, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_2, 2, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_3, 3, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_4, 4, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_5, 5, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_6, 6, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_7, 7, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_8, 8, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_9, 9, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_10, 10, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_11, 11, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_12, 12, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_13, 13, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_14, 14, read_int128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] too_small!(small_int128_15, 15, read_int128); // Test that reading/writing slices enforces the correct lengths. @@ -2860,16 +2939,16 @@ mod test { slice_lengths!( slice_len_too_big_i64, read_i64_into, write_i64_into, 17, [0, 0]); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] slice_lengths!( slice_len_too_small_u128, read_u128_into, write_u128_into, 31, [0, 0]); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] slice_lengths!( slice_len_too_big_u128, read_u128_into, write_u128_into, 33, [0, 0]); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] slice_lengths!( slice_len_too_small_i128, read_i128_into, write_i128_into, 31, [0, 0]); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] slice_lengths!( slice_len_too_big_i128, read_i128_into, write_i128_into, 33, [0, 0]); @@ -3016,9 +3095,9 @@ mod stdtests { qc_bytes_ext!(prop_ext_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_u128, Wi128, 16 + 1, read_u128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_i128, Wi128, 16 + 1, read_i128, write_i128); qc_bytes_ext!(prop_ext_uint_1, @@ -3038,52 +3117,52 @@ mod stdtests { qc_bytes_ext!(prop_ext_uint_8, u64, calc_max!(::test::U64_MAX, 8), 8, read_uint, write_u64); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_1, Wi128, 1, 1, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_2, Wi128, 2, 2, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_3, Wi128, 3, 3, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_4, Wi128, 4, 4, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_5, Wi128, 5, 5, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_6, Wi128, 6, 6, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_7, Wi128, 7, 7, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_8, Wi128, 8, 8, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_9, Wi128, 9, 9, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_10, Wi128, 10, 10, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_11, Wi128, 11, 11, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_12, Wi128, 12, 12, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_13, Wi128, 13, 13, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_14, Wi128, 14, 14, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_15, Wi128, 15, 15, read_uint128, write_u128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_uint128_16, Wi128, 16, 16, read_uint128, write_u128); @@ -3104,52 +3183,52 @@ mod stdtests { qc_bytes_ext!(prop_ext_int_8, i64, calc_max!(::test::I64_MAX, 8), 8, read_int, write_i64); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_1, Wi128, 1, 1, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_2, Wi128, 2, 2, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_3, Wi128, 3, 3, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_4, Wi128, 4, 4, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_5, Wi128, 5, 5, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_6, Wi128, 6, 6, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_7, Wi128, 7, 7, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_8, Wi128, 8, 8, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_9, Wi128, 9, 9, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_10, Wi128, 10, 10, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_11, Wi128, 11, 11, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_12, Wi128, 12, 12, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_13, Wi128, 13, 13, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_14, Wi128, 14, 14, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_15, Wi128, 15, 15, read_int128, write_i128); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_bytes_ext!(prop_ext_int128_16, Wi128, 16, 16, read_int128, write_i128); @@ -3235,15 +3314,15 @@ mod stdtests { qc_slice!(prop_slice_i32, i32, read_i32_into, write_i32_into, 0); qc_slice!(prop_slice_u64, u64, read_u64_into, write_u64_into, 0); qc_slice!(prop_slice_i64, i64, read_i64_into, write_i64_into, 0); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_slice!( prop_slice_u128, Wi128, read_u128_into, write_u128_into, 0); - #[cfg(feature = "i128")] + #[cfg(byteorder_i128)] qc_slice!( prop_slice_i128, Wi128, read_i128_into, write_i128_into, 0); qc_slice!( - prop_slice_f32, f32, read_f32_into_unchecked, write_f32_into, 0.0); + prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0); qc_slice!( - prop_slice_f64, f64, read_f64_into_unchecked, write_f64_into, 0.0); + prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0); } diff --git a/vendor/clap/.cargo-checksum.json b/vendor/clap/.cargo-checksum.json index 1a5d55654b..7b80c092c4 100644 --- a/vendor/clap/.cargo-checksum.json +++ b/vendor/clap/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"82d98018ed415b62e8d0d971f3f75cb1a2bef55c68cf6e0003f7c0caf9faeb50","CONTRIBUTORS.md":"9b0d3eee116dda23705b732c19b777ebb2b998a6e4554027ae3f61715376b4bc","Cargo.toml":"05f6200c73fa08b82d7e0606194843035c7acb18da9fe29d563c1565d64256b5","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"fb69db01448bcbd2d4e51a832d82ca36a074480a80687141219de0a7f6677804","SPONSORS.md":"f8dec21e2cf3f8bff118ad206cd4657950688749085e291e09566914d7a1a1c5","clap-test.rs":"b5ca72dedfe1e71c250c42a01a52a3f5f9ea2bb14d9fe09093e73b71880f79fd","index.html":"36f9ce4465266f3af9a259444b01c4239200473cabfc848f789f75b322a3ea8f","justfile":"811b2dec57aec46e570aeeb9945018cf87fe65f6d5b27cdb9ffca79d906910f6","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"7758da02684f9e01a4f498982accc5dfa94aebfdc257876ce26a47857202bd5f","src/app/meta.rs":"86f2f871e3d867fd190a8103429b640b77e0caeabb03ad78e7a92f929eeb5582","src/app/mod.rs":"633f0f126a5917285d66e1b19e8153d6939534aabdde02cf5dbf3c2c81446b54","src/app/parser.rs":"75fd0c8e0ebf06531f47fc523a1aa6d19aad6115cb987021bf6c76d25fb315d1","src/app/settings.rs":"31f8d217f12f77705dde33ba5c9293f213cca5d2fdcacd9350ded0b096e1c886","src/app/usage.rs":"b96e80083ea7e6b761b2c018e595400568289d89da59be54adbfaedd6eae5ab7","src/app/validator.rs":"c893fba08fb92ab3c96b41d4a21e3094cf1d4ac7794ddbfd594a158da4c37a18","src/args/any_arg.rs":"e43a208ca10985964975d2c308c8c8156643063951761d8a0d59c3350926c51b","src/args/arg.rs":"d2d97d93dd42bfbc29fd39b89d7a67d76c4f100dc8ade9eb8678bd79a5e88d8f","src/args/arg_builder/base.rs":"49591af68854d3120a20f9f76522f375b3e0ca353abbf7dbe1c142b844e7c29e","src/args/arg_builder/flag.rs":"01045643f07ded517d98ddb6267b5b1b776893f6c74ab6515940f76267448402","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"e73031991e561ea7e61574f719207034df0fa3acdd28735502d8511f00d7adbf","src/args/arg_builder/positional.rs":"897df6cda52b67728103c7b2c0750f91326880b751204f4ab15852b18be0d929","src/args/arg_builder/switched.rs":"832ef0284a0ceb2da6d03a98f864526a255bf7debfceec47a0018cf78f209dc3","src/args/arg_builder/valued.rs":"20998bf790a58206b27cf8b09f6740812d507336042a2026f203f99af4500ed5","src/args/arg_matcher.rs":"3e2ce8ce09ccc6349b1dcdc609801eb593ed553a2df21e94ac4f50cde3ab1e87","src/args/arg_matches.rs":"bd4fd0ece3e067d7a354d2daf9603295d03024c74d841f73c1537bdd257b1e31","src/args/group.rs":"27ce8153a0f9ec44636936ec9a2f7d01d5cbc53b1bf3a395d3cdfcd4ad5b7ce2","src/args/macros.rs":"57f248e2694f9413cbbaf9087813ed4f27064f5f8e29eaf4ec41ec2b274ae806","src/args/matched_arg.rs":"164abab30c38c61ff05a2a2dd0194d75e3bebda09a839a3f717bc560fc304aa4","src/args/mod.rs":"21d7ddc2ef26f4c6e3b9434a63450235e99cf7143f9d59c447d5ed0fa26cb5d1","src/args/settings.rs":"199c53d550e2090b6290ee77903382cd611b8d78626314d2d3d28281419a09c4","src/args/subcommand.rs":"40d3178fb6f0e9d3dc99959bd45ebe4655f64e7e18145ff7a5e9632ac36b8006","src/completions/bash.rs":"f9b487a5a6b675176309329a47962b95c626b9c8b3e62554c9a117a04c900c1f","src/completions/elvish.rs":"ad5bd2bd82d3ac05b67fce249a45d53eb08de6f5731f7458e6f15db19ef3bb66","src/completions/fish.rs":"6551bd7e73d54211b775ea03fa4adcbddbdcdb3de7a147f325c2848d693476e8","src/completions/macros.rs":"6fed51ae20ed545f2306fab82d4fb7656ef285ccc439284a74cbabd0a6cb88ec","src/completions/mod.rs":"e985c7a9bcb0f4c61e23bc62fba1a68e56a6176437f53fd5a88833358b6067f7","src/completions/powershell.rs":"0fff28a41c9777a8fd8deed1eaba906f23aeda53a38daa888e905bff23db01ce","src/completions/shell.rs":"df5455bc0616f76f83034002d9df47ce16d4090ed5fccc3c0ae182d0f0c5504c","src/completions/zsh.rs":"7c339fa96f4a39e1e33a0053662fba30a030a7692c092e4a0831c1ed7d5d6f53","src/errors.rs":"39d6192b012a8cbebf7220ef74144c9e8d3d9d342720af5d2e76a5af9c601439","src/fmt.rs":"7afbd78efba9936a1c776e86c65207b8bdff7bdb2d62b5d042b39f477b843bd1","src/lib.rs":"7af78443540ae53912985e65b6a279c4eeced5b051bf09ea83fd956249c37af3","src/macros.rs":"2aefd4c9223c7224385d4fb619cf084fa181b28b3f5c3173eef75cb0ac82e927","src/map.rs":"10c57678b453673aa2d78f72de2d44510271eb2f9771a8d203952353581318a8","src/osstringext.rs":"40a09d5bc42906fe284ded5741cbdece596b09b3aba747580d53d0e3e7d368ed","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"aaf08a30ab8594f415ee0a376596f668c5e2ba4ee6ab3c312239f4cbad6d5930","src/usage_parser.rs":"5dda6ef41b4c3773ab461ac7150fbdcc58ecbda7751723a0848fcb95a4312cb2"},"package":"b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"} \ No newline at end of file +{"files":{"CHANGELOG.md":"d47947db3628b2252ab3de239c414b76ccf9f34d9360891ed8ff609fec2a0e1d","CONTRIBUTORS.md":"9b0d3eee116dda23705b732c19b777ebb2b998a6e4554027ae3f61715376b4bc","Cargo.toml":"0b06f3af4bf311d8edd24d972b6429e0f67e0af104e640fbdc30ab0f060a127b","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"331532d72815424660938ce5db596a7ef8f10107e54d8f1af2b13458f65354c2","SPONSORS.md":"640b56e535db654d7bf14b1fe63bc837dcfde37a85f14eb4f404663fe1b72af9","clap-test.rs":"b5ca72dedfe1e71c250c42a01a52a3f5f9ea2bb14d9fe09093e73b71880f79fd","justfile":"9ee43d53fda234044fee4edd1ecdac9f19864c7f00a4ea5cb2b6a8a0287c93e3","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"7758da02684f9e01a4f498982accc5dfa94aebfdc257876ce26a47857202bd5f","src/app/meta.rs":"86f2f871e3d867fd190a8103429b640b77e0caeabb03ad78e7a92f929eeb5582","src/app/mod.rs":"6216afa7addb1e1fab70cc20c2b18c1a68219e564cda2a748b314dff548a5fab","src/app/parser.rs":"b2af9a9bb90156cfbcb7256ad8816069e7aaa71bd9545f2777121906ad6c38cf","src/app/settings.rs":"69cb028c8b2f59be1da907492ad004fe77a2c61bbf9e9492cf83d3aabd4713a4","src/app/usage.rs":"b96e80083ea7e6b761b2c018e595400568289d89da59be54adbfaedd6eae5ab7","src/app/validator.rs":"86602bdb395e6c8965293deab2a950bf0a320babb3269cb608768efbb5b1af5a","src/args/any_arg.rs":"e43a208ca10985964975d2c308c8c8156643063951761d8a0d59c3350926c51b","src/args/arg.rs":"4d05c9b4c681d93b52edf73f4d4e58467e5c5ad5edec861831b1c19f6a8372e7","src/args/arg_builder/base.rs":"49591af68854d3120a20f9f76522f375b3e0ca353abbf7dbe1c142b844e7c29e","src/args/arg_builder/flag.rs":"01045643f07ded517d98ddb6267b5b1b776893f6c74ab6515940f76267448402","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"e73031991e561ea7e61574f719207034df0fa3acdd28735502d8511f00d7adbf","src/args/arg_builder/positional.rs":"897df6cda52b67728103c7b2c0750f91326880b751204f4ab15852b18be0d929","src/args/arg_builder/switched.rs":"832ef0284a0ceb2da6d03a98f864526a255bf7debfceec47a0018cf78f209dc3","src/args/arg_builder/valued.rs":"20998bf790a58206b27cf8b09f6740812d507336042a2026f203f99af4500ed5","src/args/arg_matcher.rs":"3e2ce8ce09ccc6349b1dcdc609801eb593ed553a2df21e94ac4f50cde3ab1e87","src/args/arg_matches.rs":"3a209f6b4c4c094cd0749a99e7bd5e3f1823b1cfac569cdb6b0133a4d0dc9586","src/args/group.rs":"dc8d872b58eeba7e8ece44bf02cf3f6bd701e80e4612c1911906b9b70e0a8172","src/args/macros.rs":"57f248e2694f9413cbbaf9087813ed4f27064f5f8e29eaf4ec41ec2b274ae806","src/args/matched_arg.rs":"164abab30c38c61ff05a2a2dd0194d75e3bebda09a839a3f717bc560fc304aa4","src/args/mod.rs":"21d7ddc2ef26f4c6e3b9434a63450235e99cf7143f9d59c447d5ed0fa26cb5d1","src/args/settings.rs":"3e8356b3da158764c51f9c8bf4ab79e9328f65cb1c0822f86febdd8921b2abf4","src/args/subcommand.rs":"40d3178fb6f0e9d3dc99959bd45ebe4655f64e7e18145ff7a5e9632ac36b8006","src/completions/bash.rs":"eed3ab7c53ecd0546134fb8de01fcb4b5577e61d1082311521d3d20db5d42b9c","src/completions/elvish.rs":"ad5bd2bd82d3ac05b67fce249a45d53eb08de6f5731f7458e6f15db19ef3bb66","src/completions/fish.rs":"6551bd7e73d54211b775ea03fa4adcbddbdcdb3de7a147f325c2848d693476e8","src/completions/macros.rs":"6fed51ae20ed545f2306fab82d4fb7656ef285ccc439284a74cbabd0a6cb88ec","src/completions/mod.rs":"e985c7a9bcb0f4c61e23bc62fba1a68e56a6176437f53fd5a88833358b6067f7","src/completions/powershell.rs":"0fff28a41c9777a8fd8deed1eaba906f23aeda53a38daa888e905bff23db01ce","src/completions/shell.rs":"df5455bc0616f76f83034002d9df47ce16d4090ed5fccc3c0ae182d0f0c5504c","src/completions/zsh.rs":"7c339fa96f4a39e1e33a0053662fba30a030a7692c092e4a0831c1ed7d5d6f53","src/errors.rs":"b2a385e4fd1400a86ecee582602026a10a308227a4f284ec9ec9826f07cde4e2","src/fmt.rs":"0949d2f4bcf7b42c9bf7cd43bfc41c05943b978e7e0232ed0571b34862e7fc9b","src/lib.rs":"e07260bf5bf2eacd20e9d895dddae4e872e7d4874ed1999adf35b142058be308","src/macros.rs":"392c5e8063464ec456e08f56776ddfdd1118b48300ee1e58a6d3f1d49aaa992a","src/map.rs":"10c57678b453673aa2d78f72de2d44510271eb2f9771a8d203952353581318a8","src/osstringext.rs":"40a09d5bc42906fe284ded5741cbdece596b09b3aba747580d53d0e3e7d368ed","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"77f259db5dc35e55e495bbeefbf62d709990d02ef00503afe633cae2ff0f1f3c","src/usage_parser.rs":"5dda6ef41b4c3773ab461ac7150fbdcc58ecbda7751723a0848fcb95a4312cb2"},"package":"5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"} \ No newline at end of file diff --git a/vendor/clap/CHANGELOG.md b/vendor/clap/CHANGELOG.md index cbb06a37d1..d1fdd401af 100644 --- a/vendor/clap/CHANGELOG.md +++ b/vendor/clap/CHANGELOG.md @@ -1,3 +1,44 @@ + +## v2.33.0 (2019-04-06) + +#### New Sponsor + +* Stephen Oats is now a sponsor \o/ ([823457c0](https://github.com/kbknapp/clap-rs/commit/823457c0ef5e994ed7080cf62addbfe1aa3b1833)) +* **SPONSORS.md:** fixes Josh Triplett's info in the sponsor document ([24cb5740](https://github.com/kbknapp/clap-rs/commit/24cb574090a11159b48bba105d5ec2dfb0a20e4e)) + +#### Features + +* **Completions:** adds completion support for Elvish. ([e9d0562a](https://github.com/kbknapp/clap-rs/commit/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9)) +* There is a new setting to disable automatic building of `--help` and `-h` flags (`AppSettings::DisableAutoHelp`) + +#### Improvements + +* **arg_matches.rs:** add Debug implementations ([47192b7a](https://github.com/kbknapp/clap-rs/commit/47192b7a2d84ec716b81ae4af621e008a8762dc9)) +* **macros:** Support shorthand syntax for ArgGroups ([df9095e7](https://github.com/kbknapp/clap-rs/commit/df9095e75bb1e7896415251d0d4ffd8a0ebcd559)) + +#### Documentation + +* Refer to macOS rather than OSX. ([ab0d767f](https://github.com/kbknapp/clap-rs/commit/ab0d767f3a5a57e2bbb97d0183c2ef63c8c77a6c)) +* **README.md:** use https for all links ([96a7639a](https://github.com/kbknapp/clap-rs/commit/96a7639a36bcb184c3f45348986883115ef1ab3a)) + +#### Bug Fixes + +* add debug assertion for missing args in subcommand ArgGroup ([2699d9e5](https://github.com/kbknapp/clap-rs/commit/2699d9e51e7eadc258ba64c4e347c5d1fef61343)) +* Restore compat with Rust 1.21 ([6b263de1](https://github.com/kbknapp/clap-rs/commit/6b263de1d42ede692ec5ee55019ad2fc6386f92e)) +* Dont mention unused subcommands ([ef92e2b6](https://github.com/kbknapp/clap-rs/commit/ef92e2b639ed305bdade4741f60fa85cb0101c5a)) +* **OsValues:** Add `ExactSizeIterator` implementation ([356c69e5](https://github.com/kbknapp/clap-rs/commit/356c69e508fd25a9f0ea2d27bf80ae1d9a8d88f4)) +* **arg_enum!:** + * Fix comma position for valid values. ([1f1f9ff3](https://github.com/kbknapp/clap-rs/commit/1f1f9ff3fa38a43231ef8be9cfea89a32e53f518)) + * Invalid expansions of some trailing-comma patterns ([7023184f](https://github.com/kbknapp/clap-rs/commit/7023184fca04e852c270341548d6a16207d13862)) +* **completions:** improve correctness of completions when whitespace is involved ([5a08ff29](https://github.com/kbknapp/clap-rs/commit/5a08ff295b2aa6ce29420df6252a0e3ff4441bdc)) +* **help message:** Unconditionally uses long description for subcommands ([6acc8b6a](https://github.com/kbknapp/clap-rs/commit/6acc8b6a621a765cbf513450188000d943676a30), closes [#897](https://github.com/kbknapp/clap-rs/issues/897)) +* **macros:** fixes broken pattern which prevented calling multi-argument Arg methods ([9e7a352e](https://github.com/kbknapp/clap-rs/commit/9e7a352e13aaf8025d80f2bac5c47fb32528672b)) +* **parser:** Better interaction between AllowExternalSubcommands and SubcommandRequired ([9601c95a](https://github.com/kbknapp/clap-rs/commit/9601c95a03d2b82bf265c328b4769238f1b79002)) + +#### Minimum Required Rust + +* As of this release, `clap` requires `rustc 1.31.0` or greater. + ## v2.32.0 (2018-06-26) diff --git a/vendor/clap/Cargo.toml b/vendor/clap/Cargo.toml index ba5c78e627..c76ceb42b7 100644 --- a/vendor/clap/Cargo.toml +++ b/vendor/clap/Cargo.toml @@ -12,17 +12,17 @@ [package] name = "clap" -version = "2.32.0" +version = "2.33.0" authors = ["Kevin K. "] exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"] -description = "A simple to use, efficient, and full featured Command Line Argument Parser\n" +description = "A simple to use, efficient, and full-featured Command Line Argument Parser\n" homepage = "https://clap.rs/" documentation = "https://docs.rs/clap/" readme = "README.md" keywords = ["argument", "cli", "arg", "parser", "parse"] categories = ["command-line-interface"] license = "MIT" -repository = "https://github.com/kbknapp/clap-rs" +repository = "https://github.com/clap-rs/clap" [package.metadata.docs.rs] features = ["doc"] [profile.test] @@ -33,14 +33,6 @@ debug = true debug-assertions = true rpath = false -[profile.doc] -opt-level = 0 -lto = false -codegen-units = 4 -debug = true -debug-assertions = true -rpath = false - [profile.bench] opt-level = 3 lto = true @@ -76,7 +68,7 @@ version = "~0.0.166" optional = true [dependencies.strsim] -version = "0.7.0" +version = "0.8" optional = true [dependencies.term_size] @@ -84,7 +76,7 @@ version = "0.3.0" optional = true [dependencies.textwrap] -version = "0.10.0" +version = "0.11.0" [dependencies.unicode-width] version = "0.1.4" @@ -97,13 +89,13 @@ optional = true version = "0.3.5" optional = true [dev-dependencies.lazy_static] -version = "1" +version = "1.3" [dev-dependencies.regex] version = "1" [dev-dependencies.version-sync] -version = "0.5" +version = "0.8" [features] color = ["ansi_term", "atty"] @@ -121,20 +113,20 @@ yaml = ["yaml-rust"] version = "0.11" optional = true [badges.appveyor] -repository = "kbknapp/clap-rs" +repository = "clap-rs/clap" [badges.coveralls] branch = "master" -repository = "kbknapp/clap-rs" +repository = "clap-rs/clap" [badges.is-it-maintained-issue-resolution] -repository = "kbknapp/clap-rs" +repository = "clap-rs/clap" [badges.is-it-maintained-open-issues] -repository = "kbknapp/clap-rs" +repository = "clap-rs/clap" [badges.maintenance] status = "actively-developed" [badges.travis-ci] -repository = "kbknapp/clap-rs" +repository = "clap-rs/clap" diff --git a/vendor/clap/README.md b/vendor/clap/README.md index a9305db39b..c95f494066 100644 --- a/vendor/clap/README.md +++ b/vendor/clap/README.md @@ -1,9 +1,9 @@ clap ==== -[![Crates.io](https://img.shields.io/crates/v/clap.svg)](https://crates.io/crates/clap) [![Crates.io](https://img.shields.io/crates/d/clap.svg)](https://crates.io/crates/clap) [![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/kbknapp/clap-rs/blob/master/LICENSE-MIT) [![Coverage Status](https://coveralls.io/repos/kbknapp/clap-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/kbknapp/clap-rs?branch=master) [![Join the chat at https://gitter.im/kbknapp/clap-rs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kbknapp/clap-rs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Crates.io](https://img.shields.io/crates/v/clap.svg)](https://crates.io/crates/clap) [![Crates.io](https://img.shields.io/crates/d/clap.svg)](https://crates.io/crates/clap) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/clap-rs/clap/blob/master/LICENSE-MIT) [![Coverage Status](https://coveralls.io/repos/kbknapp/clap-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/kbknapp/clap-rs?branch=master) [![Join the chat at https://gitter.im/kbknapp/clap-rs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kbknapp/clap-rs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Linux: [![Build Status](https://travis-ci.org/kbknapp/clap-rs.svg?branch=master)](https://travis-ci.org/kbknapp/clap-rs) +Linux: [![Build Status](https://travis-ci.org/clap-rs/clap.svg?branch=master)](https://travis-ci.org/clap-rs/clap) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/ejg8c33dn31nhv36/branch/master?svg=true)](https://ci.appveyor.com/project/kbknapp/clap-rs/branch/master) Command Line Argument Parser for Rust @@ -17,7 +17,6 @@ It is a simple-to-use, efficient, and full-featured library for parsing command Table of Contents ================= -* [What's New](#whats-new) * [About](#about) * [FAQ](#faq) * [Features](#features) @@ -40,38 +39,6 @@ Table of Contents Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) -## What's New - -Here's whats new in 2.32.0: - -* `clap` requires `rustc 1.21.0` or greater. -* **Completions:** adds completion support for Elvish. ([e9d0562a](https://github.com/kbknapp/clap-rs/commit/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9)) -* **ArgGroup and macros:** Support shorthand syntax for ArgGroups ([df9095e7](https://github.com/kbknapp/clap-rs/commit/df9095e75bb1e7896415251d0d4ffd8a0ebcd559)) -* **OsValues:** Add `ExactSizeIterator` implementation ([356c69e5](https://github.com/kbknapp/clap-rs/commit/356c69e508fd25a9f0ea2d27bf80ae1d9a8d88f4)) -* **arg_enum!:** Invalid expansions of some trailing-comma patterns ([7023184f](https://github.com/kbknapp/clap-rs/commit/7023184fca04e852c270341548d6a16207d13862)) -* **help messages:** Unconditionally uses long description for subcommands ([6acc8b6a](https://github.com/kbknapp/clap-rs/commit/6acc8b6a621a765cbf513450188000d943676a30), closes [#897](https://github.com/kbknapp/clap-rs/issues/897)) -* **Docs:** Refer to macOS rather than OSX. ([ab0d767f](https://github.com/kbknapp/clap-rs/commit/ab0d767f3a5a57e2bbb97d0183c2ef63c8c77a6c)) - -Here's whats new in 2.31.x: - -* **Fish Completions:** fixes a bug that only allowed a single completion in in Fish Shell -* **AllowExternalSubcommands**: fixes a bug where external subcommands would be blocked by a similarly named subcommand -* Fixes some typos in the `README.md` -* **AllowMissingPositional:** improves the ability of `AppSetting::AllowMissingPositional` to allow "skipping" to the last positional arg with the `--` operator -* **Arg Indices:** adds the ability to query argument value indices - * implements an `Indices` iterator - * adds the documentation for the arg index querying methods -* **Improves PowerShell completions** - Uses the short help tool-tip for PowerShell completion scripts -* Adds WASM support (clap now compiles on WASM!) -* **Raw Args** adds a convenience function to `Arg` that allows implying all of `Arg::last` `Arg::allow_hyphen_values` and `Arg::multiple(true)` -* **CONTRIBUTING.md:** fix url to clippy upstream repo -* **Values Documentation:** improves the docs example of the Values iterator -* Updates README.md to hint that the `wrap_help` feature is a thing -* Use `codegen-units = 1` in release and bench profiles to improve bench performance -* Fix some typos and markdown issues in the docs - -For full details, see [CHANGELOG.md](https://github.com/kbknapp/clap-rs/blob/master/CHANGELOG.md) - ## About `clap` is used to parse *and validate* the string of command line arguments provided by a user at runtime. You provide the list of valid possibilities, and `clap` handles the rest. This means you focus on your *applications* functionality, and less on the parsing and validating of arguments. @@ -82,7 +49,7 @@ Once `clap` parses the user provided string of arguments, it returns the matches ## FAQ -For a full FAQ and more in depth details, see [the wiki page](https://github.com/kbknapp/clap-rs/wiki/FAQ) +For a full FAQ and more in depth details, see [the wiki page](https://github.com/clap-rs/clap/wiki/FAQ) ### Comparisons @@ -110,7 +77,7 @@ Because `docopt` is doing a ton of work to parse your help messages and determin #### All else being equal, what are some reasons *not* to use `clap`? (The Anti Pitch) -Depending on the style in which you choose to define the valid arguments, `clap` can be very verbose. `clap` also offers so many finetuning knobs and dials, that learning everything can seem overwhelming. I strive to keep the simple cases simple, but when turning all those custom dials it can get complex. `clap` is also opinionated about parsing. Even though so much can be tweaked and tuned with `clap` (and I'm adding more all the time), there are still certain features which `clap` implements in specific ways which may be contrary to some users use-cases. Finally, `clap` is "stringly typed" when referring to arguments which can cause typos in code. This particular paper-cut is being actively worked on, and should be gone in v3.x. +Depending on the style in which you choose to define the valid arguments, `clap` can be very verbose. `clap` also offers so many fine-tuning knobs and dials, that learning everything can seem overwhelming. I strive to keep the simple cases simple, but when turning all those custom dials it can get complex. `clap` is also opinionated about parsing. Even though so much can be tweaked and tuned with `clap` (and I'm adding more all the time), there are still certain features which `clap` implements in specific ways which may be contrary to some users use-cases. Finally, `clap` is "stringly typed" when referring to arguments which can cause typos in code. This particular paper-cut is being actively worked on, and should be gone in v3.x. ## Features @@ -241,7 +208,7 @@ fn main() { } ``` -One could also optionally decleare their CLI in YAML format and keep your Rust source tidy +One could also optionally declare their CLI in YAML format and keep your Rust source tidy or support multiple localized translations by having different YAML files for each localization. First, create the `cli.yml` file to hold your CLI options, but it could be called anything we like: @@ -279,7 +246,7 @@ subcommands: Since this feature requires additional dependencies that not everyone may want, it is *not* compiled in by default and we need to enable a feature flag in Cargo.toml: -Simply change your `clap = "2.32"` to `clap = {version = "2.32", features = ["yaml"]}`. +Simply change your `clap = "2.33"` to `clap = {version = "2.33", features = ["yaml"]}`. Finally we create our `main.rs` file just like we would have with the previous two examples: @@ -343,18 +310,18 @@ Examples of each method can be found in the [examples/](examples) directory of t To try out the pre-built examples, use the following steps: -* Clone the repository `$ git clone https://github.com/kbknapp/clap-rs && cd clap-rs/` +* Clone the repository `$ git clone https://github.com/clap-rs/clap && cd clap-rs/` * Compile the example `$ cargo build --example ` * Run the help info `$ ./target/debug/examples/ --help` * Play with the arguments! -* You can also do a onetime run via `$ cargo run --example -- [args to example] +* You can also do a onetime run via `$ cargo run --example -- [args to example]` ### BYOB (Build Your Own Binary) To test out `clap`'s default auto-generated help/version follow these steps: * Create a new cargo project `$ cargo new fake --bin && cd fake` * Add `clap` to your `Cargo.toml` -* + ```toml [dependencies] clap = "2" @@ -380,7 +347,7 @@ For full usage, add `clap` as a dependency in your `Cargo.toml` () to use from c ```toml [dependencies] -clap = "~2.32" +clap = "~2.33" ``` (**note**: If you are concerned with supporting a minimum version of Rust that is *older* than the current stable Rust minus 2 stable releases, it's recommended to use the `~major.minor.patch` style versions in your `Cargo.toml` which will only update the patch version automatically. For more information see the [Compatibility Policy](#compatibility-policy)) @@ -403,7 +370,7 @@ To disable these, add this to your `Cargo.toml`: ```toml [dependencies.clap] -version = "2.32" +version = "2.33" default-features = false ``` @@ -411,7 +378,7 @@ You can also selectively enable only the features you'd like to include, by addi ```toml [dependencies.clap] -version = "2.32" +version = "2.33" default-features = false # Cherry-pick the features you'd like to use @@ -460,7 +427,7 @@ In order to keep from being surprised of breaking changes, it is **highly** reco ```toml [dependencies] -clap = "~2.32" +clap = "~2.33" ``` This will cause *only* the patch version to be updated upon a `cargo update` call, and therefore cannot break due to new features, or bumped minimum versions of Rust. @@ -477,20 +444,20 @@ Right now Cargo's version resolution is pretty naive, it's just a brute-force se # In one Cargo.toml [dependencies] -clap = "~2.32.0" +clap = "~2.33.0" # In another Cargo.toml [dependencies] -clap = "2.31.0" +clap = "2.33.0" ``` This is inherently an unresolvable crate graph in Cargo right now. Cargo requires there's only one major version of a crate, and being in the same workspace these two crates must share a version. This is impossible in this location, though, as these version constraints cannot be met. #### Minimum Version of Rust -`clap` will officially support current stable Rust, minus two releases, but may work with prior releases as well. For example, current stable Rust at the time of this writing is 1.21.0, meaning `clap` is guaranteed to compile with 1.19.0 and beyond. +`clap` will officially support current stable Rust, minus two releases, but may work with prior releases as well. For example, current stable Rust at the time of this writing is 1.32.0, meaning `clap` is guaranteed to compile with 1.30.0 and beyond. -At the 1.22.0 stable release, `clap` will be guaranteed to compile with 1.20.0 and beyond, etc. +At the 1.33.0 stable release, `clap` will be guaranteed to compile with 1.31.0 and beyond, etc. Upon bumping the minimum version of Rust (assuming it's within the stable-2 range), it *must* be clearly annotated in the `CHANGELOG.md` @@ -516,7 +483,7 @@ covering this specific target. There are several excellent crates which can be used with `clap`, I recommend checking them all out! If you've got a crate that would be a good fit to be used with `clap` open an issue and let me know, I'd love to add it! * [`structopt`](https://github.com/TeXitoi/structopt) - This crate allows you to define a struct, and build a CLI from it! No more "stringly typed" and it uses `clap` behind the scenes! (*Note*: There is work underway to pull this crate into mainline `clap`). -* [`assert_cli`](https://github.com/killercup/assert_cli) - This crate allows you test your CLIs in a very intuitive and functional way! +* [`assert_cli`](https://github.com/assert-rs/assert_cli) - This crate allows you test your CLIs in a very intuitive and functional way! ## Recent Breaking Changes diff --git a/vendor/clap/SPONSORS.md b/vendor/clap/SPONSORS.md index d55b9ca5c6..67f5544f9b 100644 --- a/vendor/clap/SPONSORS.md +++ b/vendor/clap/SPONSORS.md @@ -1,10 +1,17 @@ -The following is a list of [sponsors](https://clap.rs/sponsorship/) for the clap-rs project: +Below is a list of sponsors for the clap-rs project -[Noelia Seva-Gonzalez](https://noeliasg.com/about/) -Noelia Seva-Gonzalez +If you are interested in becoming a sponsor for this project please our [sponsorship page](https://clap.rs/sponsorship/). -[Rob Tsuk](https://github.com/rtsuk) -Rob Tsuk +## Recurring Sponsors: + +| [Noelia Seva-Gonzalez](https://noeliasg.com/about/) | [messense](https://github.com/messense) | [Josh](https://joshtriplett.org) | Stephen Oats | +|:-:|:-:|:-:|:-:| +|Noelia Seva-Gonzalez | Messense | Josh Triplett | Stephen Oats | + + +## Single-Donation and Former Sponsors: + +| [Rob Tsuk](https://github.com/rtsuk)| | | +|:-:|:-:|:-:| +|Rob Tsuk| | | -[messense](https://github.com/messense) -Messense diff --git a/vendor/clap/index.html b/vendor/clap/index.html deleted file mode 100644 index 600dff9323..0000000000 --- a/vendor/clap/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/clap/justfile b/vendor/clap/justfile index e9385c6bf9..0768764b30 100644 --- a/vendor/clap/justfile +++ b/vendor/clap/justfile @@ -5,7 +5,7 @@ echo "the following is a list of contributors:" > CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md - githubcontrib --owner kbknapp --repo clap-rs --sha master --cols 6 --format md --showlogin true --sortBy contributions --sortOrder desc >> CONTRIBUTORS.md + githubcontrib --owner clap-rs --repo clap --sha master --cols 6 --format md --showlogin true --sortBy contributions --sortOrder desc >> CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md echo "" >> CONTRIBUTORS.md echo "This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list)" >> CONTRIBUTORS.md diff --git a/vendor/clap/src/app/mod.rs b/vendor/clap/src/app/mod.rs index f2d9d52bcf..3a1a3831e3 100644 --- a/vendor/clap/src/app/mod.rs +++ b/vendor/clap/src/app/mod.rs @@ -149,8 +149,8 @@ impl<'a, 'b> App<'a, 'b> { /// # } /// ``` /// [`App`]: ./struct.App.html - /// [`examples/17_yaml.rs`]: https://github.com/kbknapp/clap-rs/blob/master/examples/17_yaml.rs - /// [`examples/17_yaml.yml`]: https://github.com/kbknapp/clap-rs/blob/master/examples/17_yaml.yml + /// [`examples/17_yaml.rs`]: https://github.com/clap-rs/clap/blob/master/examples/17_yaml.rs + /// [`examples/17_yaml.yml`]: https://github.com/clap-rs/clap/blob/master/examples/17_yaml.yml /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html #[cfg(feature = "yaml")] pub fn from_yaml(yaml: &'a Yaml) -> App<'a, 'a> { App::from(yaml) } @@ -174,7 +174,7 @@ impl<'a, 'b> App<'a, 'b> { /// # ; /// ``` /// [`crate_authors!`]: ./macro.crate_authors!.html - /// [`examples/`]: https://github.com/kbknapp/clap-rs/tree/master/examples + /// [`examples/`]: https://github.com/clap-rs/clap/tree/master/examples pub fn author>(mut self, author: S) -> Self { self.p.meta.author = Some(author.into()); self @@ -332,7 +332,7 @@ impl<'a, 'b> App<'a, 'b> { /// # ; /// ``` /// [`crate_version!`]: ./macro.crate_version!.html - /// [`examples/`]: https://github.com/kbknapp/clap-rs/tree/master/examples + /// [`examples/`]: https://github.com/clap-rs/clap/tree/master/examples /// [`App::long_version`]: ./struct.App.html#method.long_version pub fn version>(mut self, ver: S) -> Self { self.p.meta.version = Some(ver.into()); @@ -363,7 +363,7 @@ impl<'a, 'b> App<'a, 'b> { /// # ; /// ``` /// [`crate_version!`]: ./macro.crate_version!.html - /// [`examples/`]: https://github.com/kbknapp/clap-rs/tree/master/examples + /// [`examples/`]: https://github.com/clap-rs/clap/tree/master/examples /// [`App::version`]: ./struct.App.html#method.version pub fn long_version>(mut self, ver: S) -> Self { self.p.meta.long_version = Some(ver.into()); @@ -560,8 +560,9 @@ impl<'a, 'b> App<'a, 'b> { /// .template("{bin} ({version}) - {usage}") /// # ; /// ``` - /// **NOTE:**The template system is, on purpose, very simple. Therefore the tags have to written - /// in the lowercase and without spacing. + /// **NOTE:** The template system is, on purpose, very simple. Therefore the tags have to be + /// written in lowercase and without spacing. + /// /// [`App::about`]: ./struct.App.html#method.about /// [`App::after_help`]: ./struct.App.html#method.after_help /// [`App::before_help`]: ./struct.App.html#method.before_help @@ -820,7 +821,7 @@ impl<'a, 'b> App<'a, 'b> { /// .arg_from_usage("-c --config= 'Sets a configuration file to use'") /// # ; /// ``` - /// [arguments]: ./struct.Arg.html + /// [argument]: ./struct.Arg.html /// [`Arg`]: ./struct.Arg.html /// [`Arg::from_usage`]: ./struct.Arg.html#method.from_usage pub fn arg_from_usage(mut self, usage: &'a str) -> Self { @@ -1186,13 +1187,6 @@ impl<'a, 'b> App<'a, 'b> { /// [`-h` (short)]: ./struct.Arg.html#method.help /// [`--help` (long)]: ./struct.Arg.html#method.long_help pub fn print_long_help(&mut self) -> ClapResult<()> { - // If there are global arguments, or settings we need to propagate them down to subcommands - // before parsing incase we run into a subcommand - self.p.propagate_globals(); - self.p.propagate_settings(); - self.p.derive_display_order(); - - self.p.create_help_and_version(); let out = io::stdout(); let mut buf_w = BufWriter::new(out.lock()); self.write_long_help(&mut buf_w) @@ -1222,7 +1216,7 @@ impl<'a, 'b> App<'a, 'b> { /// [`--help` (long)]: ./struct.Arg.html#method.long_help pub fn write_help(&self, w: &mut W) -> ClapResult<()> { // PENDING ISSUE: 808 - // https://github.com/kbknapp/clap-rs/issues/808 + // https://github.com/clap-rs/clap/issues/808 // If there are global arguments, or settings we need to propagate them down to subcommands // before parsing incase we run into a subcommand // self.p.propagate_globals(); @@ -1252,6 +1246,8 @@ impl<'a, 'b> App<'a, 'b> { /// [`-h` (short)]: ./struct.Arg.html#method.help /// [`--help` (long)]: ./struct.Arg.html#method.long_help pub fn write_long_help(&mut self, w: &mut W) -> ClapResult<()> { + // If there are global arguments, or settings we need to propagate them down to subcommands + // before parsing incase we run into a subcommand self.p.propagate_globals(); self.p.propagate_settings(); self.p.derive_display_order(); @@ -1668,6 +1664,7 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> { } yaml_str!(a, yaml, version); + yaml_str!(a, yaml, long_version); yaml_str!(a, yaml, author); yaml_str!(a, yaml, bin_name); yaml_str!(a, yaml, about); diff --git a/vendor/clap/src/app/parser.rs b/vendor/clap/src/app/parser.rs index 0f1e0efe5d..decfde4f8d 100644 --- a/vendor/clap/src/app/parser.rs +++ b/vendor/clap/src/app/parser.rs @@ -135,7 +135,7 @@ where } #[inline] - fn app_debug_asserts(&mut self) -> bool { + fn app_debug_asserts(&self) -> bool { assert!(self.verify_positionals()); let should_err = self.groups.iter().all(|g| { g.args.iter().all(|arg| { @@ -512,11 +512,11 @@ where pub fn unset(&mut self, s: AS) { self.settings.unset(s) } #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))] - pub fn verify_positionals(&mut self) -> bool { + pub fn verify_positionals(&self) -> bool { // Because you must wait until all arguments have been supplied, this is the first chance // to make assertions on positional argument indexes // - // Firt we verify that the index highest supplied index, is equal to the number of + // First we verify that the index highest supplied index, is equal to the number of // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3 // but no 2) if let Some((idx, p)) = self.positionals.iter().rev().next() { @@ -871,6 +871,7 @@ where let mut subcmd_name: Option = None; let mut needs_val_of: ParseResult<'a> = ParseResult::NotFound; let mut pos_counter = 1; + let mut sc_is_external = false; while let Some(arg) = it.next() { let arg_os = arg.into(); debugln!( @@ -928,7 +929,7 @@ where } if arg_os.starts_with(b"--") { - needs_val_of = self.parse_long_arg(matcher, &arg_os)?; + needs_val_of = self.parse_long_arg(matcher, &arg_os, it)?; debugln!( "Parser:get_matches_with: After parse_long_arg {:?}", needs_val_of @@ -1115,6 +1116,7 @@ where name: sc_name, matches: sc_m.into(), }); + sc_is_external = true; } else if !((self.is_set(AS::AllowLeadingHyphen) || self.is_set(AS::AllowNegativeNumbers)) && arg_os.starts_with(b"-")) @@ -1154,32 +1156,34 @@ where } } - if let Some(ref pos_sc_name) = subcmd_name { - let sc_name = { - find_subcmd!(self, pos_sc_name) - .expect(INTERNAL_ERROR_MSG) - .p - .meta - .name - .clone() - }; - self.parse_subcommand(&*sc_name, matcher, it)?; - } else if self.is_set(AS::SubcommandRequired) { - let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name); - return Err(Error::missing_subcommand( - bn, - &usage::create_error_usage(self, matcher, None), - self.color(), - )); - } else if self.is_set(AS::SubcommandRequiredElseHelp) { - debugln!("Parser::get_matches_with: SubcommandRequiredElseHelp=true"); - let mut out = vec![]; - self.write_help_err(&mut out)?; - return Err(Error { - message: String::from_utf8_lossy(&*out).into_owned(), - kind: ErrorKind::MissingArgumentOrSubcommand, - info: None, - }); + if !sc_is_external { + if let Some(ref pos_sc_name) = subcmd_name { + let sc_name = { + find_subcmd!(self, pos_sc_name) + .expect(INTERNAL_ERROR_MSG) + .p + .meta + .name + .clone() + }; + self.parse_subcommand(&*sc_name, matcher, it)?; + } else if self.is_set(AS::SubcommandRequired) { + let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name); + return Err(Error::missing_subcommand( + bn, + &usage::create_error_usage(self, matcher, None), + self.color(), + )); + } else if self.is_set(AS::SubcommandRequiredElseHelp) { + debugln!("Parser::get_matches_with: SubcommandRequiredElseHelp=true"); + let mut out = vec![]; + self.write_help_err(&mut out)?; + return Err(Error { + message: String::from_utf8_lossy(&*out).into_owned(), + kind: ErrorKind::MissingArgumentOrSubcommand, + info: None, + }); + } } // In case the last arg was new, we need to process it's overrides @@ -1362,6 +1366,8 @@ where } pub fn args_in_group(&self, group: &str) -> Vec { + debug_assert!(self.app_debug_asserts()); + let mut g_vec = vec![]; let mut args = vec![]; @@ -1413,7 +1419,7 @@ where pub fn create_help_and_version(&mut self) { debugln!("Parser::create_help_and_version;"); // name is "hclap_help" because flags are sorted by name - if !self.contains_long("help") { + if !self.is_set(AS::DisableHelpFlags) && !self.contains_long("help") { debugln!("Parser::create_help_and_version: Building --help"); if self.help_short.is_none() && !self.contains_short('h') { self.help_short = Some('h'); @@ -1554,11 +1560,16 @@ where } } - fn parse_long_arg( + fn parse_long_arg( &mut self, matcher: &mut ArgMatcher<'a>, full_arg: &OsStr, - ) -> ClapResult> { + it: &mut Peekable, + ) -> ClapResult> + where + I: Iterator, + T: Into + Clone, + { // maybe here lifetime should be 'a debugln!("Parser::parse_long_arg;"); @@ -1614,8 +1625,14 @@ where } debugln!("Parser::parse_long_arg: Didn't match anything"); - self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher) - .map(|_| ParseResult::NotFound) + + let args_rest: Vec<_> = it.map(|x| x.clone().into()).collect(); + let args_rest2: Vec<_> = args_rest.iter().map(|x| x.to_str().expect(INVALID_UTF8)).collect(); + self.did_you_mean_error( + arg.to_str().expect(INVALID_UTF8), + matcher, + &args_rest2[..] + ).map(|_| ParseResult::NotFound) } #[cfg_attr(feature = "lints", allow(len_zero))] @@ -1872,9 +1889,9 @@ where Ok(ParseResult::Flag) } - fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { + fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>, args_rest: &[&str]) -> ClapResult<()> { // Didn't match a flag or option - let suffix = suggestions::did_you_mean_flag_suffix(arg, longs!(self), &self.subcommands); + let suffix = suggestions::did_you_mean_flag_suffix(arg, &args_rest, longs!(self), &self.subcommands); // Add the arg to the matches to build a proper usage string if let Some(name) = suffix.1 { diff --git a/vendor/clap/src/app/settings.rs b/vendor/clap/src/app/settings.rs index 4aa64d337b..ec0399722b 100644 --- a/vendor/clap/src/app/settings.rs +++ b/vendor/clap/src/app/settings.rs @@ -47,6 +47,7 @@ bitflags! { const INFER_SUBCOMMANDS = 1 << 38; const CONTAINS_LAST = 1 << 39; const ARGS_OVERRIDE_SELF = 1 << 40; + const DISABLE_HELP_FLAGS = 1 << 41; } } @@ -89,6 +90,7 @@ impl AppFlags { DontDelimitTrailingValues => Flags::DONT_DELIM_TRAIL, DontCollapseArgsInUsage => Flags::DONT_COLLAPSE_ARGS, DeriveDisplayOrder => Flags::DERIVE_DISP_ORDER, + DisableHelpFlags => Flags::DISABLE_HELP_FLAGS, DisableHelpSubcommand => Flags::DISABLE_HELP_SC, DisableVersion => Flags::DISABLE_VERSION, GlobalVersion => Flags::GLOBAL_VERSION, @@ -165,6 +167,7 @@ pub enum AppSettings { /// [`ArgMatches::os_values_of`]: ./struct.ArgMatches.html#method.os_values_of /// [`ArgMatches::lossy_value_of`]: ./struct.ArgMatches.html#method.lossy_value_of /// [`ArgMatches::lossy_values_of`]: ./struct.ArgMatches.html#method.lossy_values_of + /// [`SubCommand`]: ./struct.SubCommand.html AllowInvalidUtf8, /// Essentially sets [`Arg::overrides_with("itself")`] for all arguments. @@ -511,6 +514,37 @@ pub enum AppSettings { /// [`Arg::use_delimiter(false)`]: ./struct.Arg.html#method.use_delimiter DontDelimitTrailingValues, + /// Disables `-h` and `--help` [`App`] without affecting any of the [`SubCommand`]s + /// (Defaults to `false`; application *does* have help flags) + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, AppSettings, ErrorKind}; + /// let res = App::new("myprog") + /// .setting(AppSettings::DisableHelpFlags) + /// .get_matches_from_safe(vec![ + /// "myprog", "-h" + /// ]); + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); + /// ``` + /// + /// ```rust + /// # use clap::{App, SubCommand, AppSettings, ErrorKind}; + /// let res = App::new("myprog") + /// .setting(AppSettings::DisableHelpFlags) + /// .subcommand(SubCommand::with_name("test")) + /// .get_matches_from_safe(vec![ + /// "myprog", "test", "-h" + /// ]); + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind, ErrorKind::HelpDisplayed); + /// ``` + /// [`SubCommand`]: ./struct.SubCommand.html + /// [`App`]: ./struct.App.html + DisableHelpFlags, + /// Disables the `help` subcommand /// /// # Examples @@ -562,6 +596,7 @@ pub enum AppSettings { /// assert_eq!(res.unwrap_err().kind, ErrorKind::VersionDisplayed); /// ``` /// [`SubCommand`]: ./struct.SubCommand.html + /// [`App`]: ./struct.App.html DisableVersion, /// Displays the arguments and [`SubCommand`]s in the help message in the order that they were @@ -884,7 +919,7 @@ pub enum AppSettings { /// Disables `-V` and `--version` for all [`SubCommand`]s /// (Defaults to `false`; subcommands *do* have version flags.) /// - /// **NOTE:** This setting must be set **prior** adding any subcommands + /// **NOTE:** This setting must be set **prior** to adding any subcommands. /// /// # Examples /// @@ -903,7 +938,7 @@ pub enum AppSettings { /// [`SubCommand`]: ./struct.SubCommand.html VersionlessSubcommands, - /// Will display a message "Press [ENTER]/[RETURN] to continue..." and wait for user before + /// Will display a message "Press \[ENTER\]/\[RETURN\] to continue..." and wait for user before /// exiting /// /// This is most useful when writing an application which is run from a GUI shortcut, or on @@ -948,6 +983,7 @@ impl FromStr for AppSettings { type Err = String; fn from_str(s: &str) -> Result::Err> { match &*s.to_ascii_lowercase() { + "disablehelpflags" => Ok(AppSettings::DisableHelpFlags), "argrequiredelsehelp" => Ok(AppSettings::ArgRequiredElseHelp), "argsnegatesubcommands" => Ok(AppSettings::ArgsNegateSubcommands), "allowinvalidutf8" => Ok(AppSettings::AllowInvalidUtf8), @@ -993,6 +1029,10 @@ mod test { #[test] fn app_settings_fromstr() { + assert_eq!( + "disablehelpflags".parse::().unwrap(), + AppSettings::DisableHelpFlags + ); assert_eq!( "argsnegatesubcommands".parse::().unwrap(), AppSettings::ArgsNegateSubcommands diff --git a/vendor/clap/src/app/validator.rs b/vendor/clap/src/app/validator.rs index fce4cf2969..181b831d0b 100644 --- a/vendor/clap/src/app/validator.rs +++ b/vendor/clap/src/app/validator.rs @@ -401,8 +401,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> { } else { false }; - // Issue 665 (https://github.com/kbknapp/clap-rs/issues/665) - // Issue 1105 (https://github.com/kbknapp/clap-rs/issues/1105) + // Issue 665 (https://github.com/clap-rs/clap/issues/665) + // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) if a.takes_value() && !min_vals_zero && ma.vals.is_empty() { return Err(Error::empty_value( a, diff --git a/vendor/clap/src/args/arg.rs b/vendor/clap/src/args/arg.rs index 7c020bf133..50a30abb7a 100644 --- a/vendor/clap/src/args/arg.rs +++ b/vendor/clap/src/args/arg.rs @@ -139,6 +139,7 @@ impl<'a, 'b> Arg<'a, 'b> { "conflicts_with" => yaml_vec_or_str!(v, a, conflicts_with), "overrides_with" => yaml_vec_or_str!(v, a, overrides_with), "possible_values" => yaml_vec_or_str!(v, a, possible_value), + "case_insensitive" => yaml_to_bool!(a, v, case_insensitive), "required_unless_one" => yaml_vec_or_str!(v, a, required_unless), "required_unless_all" => { a = yaml_vec_or_str!(v, a, required_unless); @@ -2301,7 +2302,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// **NOTE:** Implicitly sets [`Arg::hidden_short_help(true)`] and [`Arg::hidden_long_help(true)`] /// when set to true - /// + /// /// **NOTE:** This does **not** hide the argument from usage strings on error /// /// # Examples @@ -3580,6 +3581,12 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// assert_eq!(m.values_of("flag").unwrap().collect::>(), vec!["env1", "env2"]); /// ``` + /// [`ArgMatches::occurrences_of`]: ./struct.ArgMatches.html#method.occurrences_of + /// [`ArgMatches::value_of`]: ./struct.ArgMatches.html#method.value_of + /// [`ArgMatches::is_present`]: ./struct.ArgMatches.html#method.is_present + /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value + /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple + /// [`Arg::use_delimiter(true)`]: ./struct.Arg.html#method.use_delimiter pub fn env(self, name: &'a str) -> Self { self.env_os(OsStr::new(name)) } @@ -3746,7 +3753,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// **NOTE:** Setting this option will cause next-line-help output style to be used /// when long help (`--help`) is called. - /// + /// /// # Examples /// /// ```rust @@ -3781,9 +3788,9 @@ impl<'a, 'b> Arg<'a, 'b> { /// -h, --help Prints help information /// -V, --version Prints version information /// ``` - /// + /// /// However, when --help is called - /// + /// /// ```rust /// # use clap::{App, Arg}; /// let m = App::new("prog") @@ -3795,24 +3802,24 @@ impl<'a, 'b> Arg<'a, 'b> { /// "prog", "--help" /// ]); /// ``` - /// + /// /// Then the following would be displayed - /// + /// /// ```notrust /// helptest - /// + /// /// USAGE: /// helptest [FLAGS] - /// + /// /// FLAGS: /// --config Some help text describing the --config arg /// -h, --help Prints help information /// -V, --version Prints version information /// ``` pub fn hidden_short_help(self, hide: bool) -> Self { - if hide { + if hide { self.set(ArgSettings::HiddenShortHelp) - } else { + } else { self.unset(ArgSettings::HiddenShortHelp) } } @@ -3823,7 +3830,7 @@ impl<'a, 'b> Arg<'a, 'b> { /// /// **NOTE:** Setting this option will cause next-line-help output style to be used /// when long help (`--help`) is called. - /// + /// /// # Examples /// /// ```rust @@ -3858,9 +3865,9 @@ impl<'a, 'b> Arg<'a, 'b> { /// -h, --help Prints help information /// -V, --version Prints version information /// ``` - /// + /// /// However, when -h is called - /// + /// /// ```rust /// # use clap::{App, Arg}; /// let m = App::new("prog") @@ -3872,15 +3879,15 @@ impl<'a, 'b> Arg<'a, 'b> { /// "prog", "-h" /// ]); /// ``` - /// + /// /// Then the following would be displayed - /// + /// /// ```notrust /// helptest - /// + /// /// USAGE: /// helptest [FLAGS] - /// + /// /// FLAGS: /// --config Some help text describing the --config arg /// -h, --help Prints help information @@ -3894,20 +3901,23 @@ impl<'a, 'b> Arg<'a, 'b> { } } - /// Checks if one of the [`ArgSettings`] settings is set for the argument + /// Checks if one of the [`ArgSettings`] settings is set for the argument. + /// /// [`ArgSettings`]: ./enum.ArgSettings.html pub fn is_set(&self, s: ArgSettings) -> bool { self.b.is_set(s) } - /// Sets one of the [`ArgSettings`] settings for the argument + /// Sets one of the [`ArgSettings`] settings for the argument. + /// /// [`ArgSettings`]: ./enum.ArgSettings.html pub fn set(mut self, s: ArgSettings) -> Self { self.setb(s); self } - /// Unsets one of the [`ArgSettings`] settings for the argument + /// Unsets one of the [`ArgSettings`] settings for the argument. + /// /// [`ArgSettings`]: ./enum.ArgSettings.html pub fn unset(mut self, s: ArgSettings) -> Self { self.unsetb(s); diff --git a/vendor/clap/src/args/arg_matches.rs b/vendor/clap/src/args/arg_matches.rs index 7ac112877e..6cf70a49ae 100644 --- a/vendor/clap/src/args/arg_matches.rs +++ b/vendor/clap/src/args/arg_matches.rs @@ -786,8 +786,7 @@ impl<'a> ArgMatches<'a> { /// assert_eq!(values.next(), None); /// ``` /// [`ArgMatches::values_of`]: ./struct.ArgMatches.html#method.values_of -#[derive(Clone)] -#[allow(missing_debug_implementations)] +#[derive(Debug, Clone)] pub struct Values<'a> { iter: Map, fn(&'a OsString) -> &'a str>, } @@ -838,8 +837,7 @@ impl<'a> Default for Values<'a> { /// ``` /// [`ArgMatches::values_of_os`]: ./struct.ArgMatches.html#method.values_of_os /// [`Values`]: ./struct.Values.html -#[derive(Clone)] -#[allow(missing_debug_implementations)] +#[derive(Debug, Clone)] pub struct OsValues<'a> { iter: Map, fn(&'a OsString) -> &'a OsStr>, } @@ -890,8 +888,7 @@ impl<'a> Default for OsValues<'a> { /// assert_eq!(indices.next(), None); /// ``` /// [`ArgMatches::indices_of`]: ./struct.ArgMatches.html#method.indices_of -#[derive(Clone)] -#[allow(missing_debug_implementations)] +#[derive(Debug, Clone)] pub struct Indices<'a> { // would rather use '_, but: https://github.com/rust-lang/rust/issues/48469 iter: Map, fn(&'a usize) -> usize>, } diff --git a/vendor/clap/src/args/group.rs b/vendor/clap/src/args/group.rs index e082b69f4d..f8bfb7a086 100644 --- a/vendor/clap/src/args/group.rs +++ b/vendor/clap/src/args/group.rs @@ -45,7 +45,7 @@ use yaml_rust::Yaml; /// --minor 'auto increase minor' /// --patch 'auto increase patch'") /// .group(ArgGroup::with_name("vers") -/// .args(&["set-ver", "major", "minor","patch"]) +/// .args(&["set-ver", "major", "minor", "patch"]) /// .required(true)) /// .get_matches_from_safe(vec!["app", "--major", "--patch"]); /// // Because we used two args in the group it's an error diff --git a/vendor/clap/src/args/settings.rs b/vendor/clap/src/args/settings.rs index 864dd90303..7b0e0a26c7 100644 --- a/vendor/clap/src/args/settings.rs +++ b/vendor/clap/src/args/settings.rs @@ -77,7 +77,8 @@ pub enum ArgSettings { Multiple, /// The argument allows empty values such as `--option ""` EmptyValues, - /// The argument should be propagated down through all child [`SubCommands`] + /// The argument should be propagated down through all child [`SubCommand`]s + /// /// [`SubCommand`]: ./struct.SubCommand.html Global, /// The argument should **not** be shown in help text diff --git a/vendor/clap/src/completions/bash.rs b/vendor/clap/src/completions/bash.rs index d042e2ea1e..37dfa66983 100644 --- a/vendor/clap/src/completions/bash.rs +++ b/vendor/clap/src/completions/bash.rs @@ -20,19 +20,19 @@ impl<'a, 'b> BashGen<'a, 'b> { w!( buf, format!( - "_{name}() {{ + r#"_{name}() {{ local i cur prev opts cmds COMPREPLY=() - cur=\"${{COMP_WORDS[COMP_CWORD]}}\" - prev=\"${{COMP_WORDS[COMP_CWORD-1]}}\" - cmd=\"\" - opts=\"\" + cur="${{COMP_WORDS[COMP_CWORD]}}" + prev="${{COMP_WORDS[COMP_CWORD-1]}}" + cmd="" + opts="" for i in ${{COMP_WORDS[@]}} do - case \"${{i}}\" in + case "${{i}}" in {name}) - cmd=\"{name}\" + cmd="{name}" ;; {subcmds} *) @@ -40,20 +40,20 @@ impl<'a, 'b> BashGen<'a, 'b> { esac done - case \"${{cmd}}\" in + case "${{cmd}}" in {name}) - opts=\"{name_opts}\" + opts="{name_opts}" if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq 1 ]] ; then - COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) ) + COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") ) return 0 fi - case \"${{prev}}\" in + case "${{prev}}" in {name_opts_details} *) COMPREPLY=() ;; esac - COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) ) + COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") ) return 0 ;; {subcmd_details} @@ -61,7 +61,7 @@ impl<'a, 'b> BashGen<'a, 'b> { }} complete -F _{name} -o bashdefault -o default {name} -", +"#, name = self.p.meta.bin_name.as_ref().unwrap(), name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()), name_opts_details = @@ -79,10 +79,10 @@ complete -F _{name} -o bashdefault -o default {name} for sc in &scs { subcmds = format!( - "{} + r#"{} {name}) - cmd+=\"__{fn_name}\" - ;;", + cmd+="__{fn_name}" + ;;"#, subcmds, name = sc, fn_name = sc.replace("-", "__") @@ -101,22 +101,22 @@ complete -F _{name} -o bashdefault -o default {name} for sc in &scs { subcmd_dets = format!( - "{} + r#"{} {subcmd}) - opts=\"{sc_opts}\" + opts="{sc_opts}" if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then - COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) ) + COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") ) return 0 fi - case \"${{prev}}\" in + case "${{prev}}" in {opts_details} *) COMPREPLY=() ;; esac - COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) ) + COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") ) return 0 - ;;", + ;;"#, subcmd_dets, subcmd = sc.replace("-", "__"), sc_opts = self.all_options_for_path(&*sc), @@ -169,9 +169,9 @@ complete -F _{name} -o bashdefault -o default {name} debugln!("BashGen::vals_for: o={}", o.b.name); use args::AnyArg; if let Some(vals) = o.possible_vals() { - format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" ")) + format!(r#"$(compgen -W "{}" -- "${{cur}}")"#, vals.join(" ")) } else { - String::from("$(compgen -f ${cur})") + String::from(r#"$(compgen -f "${cur}")"#) } } diff --git a/vendor/clap/src/errors.rs b/vendor/clap/src/errors.rs index 35ac58bd09..c6087c00a2 100644 --- a/vendor/clap/src/errors.rs +++ b/vendor/clap/src/errors.rs @@ -196,7 +196,7 @@ pub enum ErrorKind { /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues); /// ``` - /// [`Arg::number_of_values`] + /// /// [`Arg::number_of_values`]: ./struct.Arg.html#method.number_of_values /// [`Arg::value_names`]: ./struct.Arg.html#method.value_names WrongNumberOfValues, @@ -365,6 +365,7 @@ pub enum ErrorKind { /// Represents a [Format error] (which is a part of [`Display`]). /// Typically caused by writing to `stderr` or `stdout`. + /// /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html /// [Format error]: https://doc.rust-lang.org/std/fmt/struct.Error.html Format, diff --git a/vendor/clap/src/fmt.rs b/vendor/clap/src/fmt.rs index 334c5b103a..108a6354b9 100644 --- a/vendor/clap/src/fmt.rs +++ b/vendor/clap/src/fmt.rs @@ -62,11 +62,11 @@ impl Colorizer { let is_a_tty = is_a_tty(option.use_stderr); let is_term_dumb = is_term_dumb(); Colorizer { - when: if is_a_tty && !is_term_dumb { - option.when - } else { - ColorWhen::Never - }, + when: match option.when { + ColorWhen::Auto if is_a_tty && !is_term_dumb => ColorWhen::Auto, + ColorWhen::Auto => ColorWhen::Never, + when => when, + } } } diff --git a/vendor/clap/src/lib.rs b/vendor/clap/src/lib.rs index 5a10fc4804..0a3e1bb676 100644 --- a/vendor/clap/src/lib.rs +++ b/vendor/clap/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright ⓒ 2015-2016 Kevin B. Knapp and [`clap-rs` contributors](https://github.com/kbknapp/clap-rs/blob/master/CONTRIBUTORS.md). +// Copyright ⓒ 2015-2016 Kevin B. Knapp and [`clap-rs` contributors](https://github.com/clap-rs/clap/blob/master/CONTRIBUTORS.md). // Licensed under the MIT license // (see LICENSE or ) All files in the project carrying such // notice may not be copied, modified, or distributed except according to those terms. @@ -29,8 +29,8 @@ //! //! The following examples show a quick example of some of the very basic functionality of `clap`. //! For more advanced usage, such as requirements, conflicts, groups, multiple values and -//! occurrences see the [documentation](https://docs.rs/clap/), [examples/](https://github.com/kbknapp/clap-rs/tree/master/examples) directory of -//! this repository or the [video tutorials](https://www.youtube.com/playlist?list=PLza5oFLQGTl2Z5T8g1pRkIynR3E0_pc7U). +//! occurrences see the [documentation](https://docs.rs/clap/), [examples/] directory of +//! this repository or the [video tutorials]. //! //! **NOTE:** All of these examples are functionally the same, but show different styles in which to //! use `clap` @@ -266,7 +266,7 @@ //! //! To try out the pre-built example, use the following steps: //! -//! * Clone the repository `$ git clone https://github.com/kbknapp/clap-rs && cd clap-rs/tests` +//! * Clone the repository `$ git clone https://github.com/clap-rs/clap && cd clap-rs/tests` //! * Compile the example `$ cargo build --release` //! * Run the help info `$ ./target/release/claptests --help` //! * Play with the arguments! @@ -313,13 +313,13 @@ //! //! ```toml //! [dependencies.clap] -//! git = "https://github.com/kbknapp/clap-rs.git" +//! git = "https://github.com/clap-rs/clap.git" //! ``` //! //! Add `extern crate clap;` to your crate root. //! //! Define a list of valid arguments for your program (see the -//! [documentation](https://docs.rs/clap/) or [examples/](examples) directory of this repo) +//! [documentation](https://docs.rs/clap/) or [examples/] directory of this repo) //! //! Then run `cargo build` or `cargo update && cargo build` for your project. //! @@ -366,17 +366,17 @@ //! * **Red** Color: **NOT** included by default (must use cargo `features` to enable) //! * **Blue** Color: Dev dependency, only used while developing. //! -//! ![clap dependencies](https://raw.githubusercontent.com/kbknapp/clap-rs/master/clap_dep_graph.png) +//! ![clap dependencies](https://raw.githubusercontent.com/clap-rs/clap/master/clap_dep_graph.png) //! //! ### More Information //! //! You can find complete documentation on the [docs.rs](https://docs.rs/clap/) for this project. //! -//! You can also find usage examples in the [examples/](https://github.com/kbknapp/clap-rs/tree/master/examples) directory of this repo. +//! You can also find usage examples in the [examples/] directory of this repo. //! //! #### Video Tutorials //! -//! There's also the video tutorial series [Argument Parsing with Rust v2](https://www.youtube.com/playlist?list=PLza5oFLQGTl2Z5T8g1pRkIynR3E0_pc7U). +//! There's also the video tutorial series [Argument Parsing with Rust v2][video tutorials]. //! //! These videos slowly trickle out as I finish them and currently a work in progress. //! @@ -388,10 +388,10 @@ //! appreciated! //! //! Another really great way to help is if you find an interesting, or helpful way in which to use -//! `clap`. You can either add it to the [examples/](examples) directory, or file an issue and tell +//! `clap`. You can either add it to the [examples/] directory, or file an issue and tell //! me. I'm all about giving credit where credit is due :) //! -//! Please read [CONTRIBUTING.md](https://raw.githubusercontent.com/kbknapp/clap-rs/master/.github/CONTRIBUTING.md) before you start contributing. +//! Please read [CONTRIBUTING.md](https://raw.githubusercontent.com/clap-rs/clap/master/.github/CONTRIBUTING.md) before you start contributing. //! //! //! ### Testing Code @@ -509,11 +509,15 @@ //! //! ## License //! -//! `clap` is licensed under the MIT license. Please read the [LICENSE-MIT](LICENSE-MIT) file in +//! `clap` is licensed under the MIT license. Please read the [LICENSE-MIT][license] file in //! this repository for more information. +//! +//! [examples/]: https://github.com/clap-rs/clap/tree/master/examples +//! [video tutorials]: https://www.youtube.com/playlist?list=PLza5oFLQGTl2Z5T8g1pRkIynR3E0_pc7U +//! [license]: https://raw.githubusercontent.com/clap-rs/clap/master/LICENSE-MIT #![crate_type = "lib"] -#![doc(html_root_url = "https://docs.rs/clap/2.32.0")] +#![doc(html_root_url = "https://docs.rs/clap/2.33.0")] #![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, unused_import_braces, unused_allocation)] // Lints we'd like to deny but are currently failing for upstream crates @@ -567,7 +571,7 @@ mod completions; mod map; const INTERNAL_ERROR_MSG: &'static str = "Fatal internal error. Please consider filing a bug \ - report at https://github.com/kbknapp/clap-rs/issues"; + report at https://github.com/clap-rs/clap/issues"; const INVALID_UTF8: &'static str = "unexpected invalid UTF-8 code point"; #[cfg(unstable)] diff --git a/vendor/clap/src/macros.rs b/vendor/clap/src/macros.rs index 384a3bf7ca..8198e19bad 100644 --- a/vendor/clap/src/macros.rs +++ b/vendor/clap/src/macros.rs @@ -254,7 +254,7 @@ macro_rules! values_t_or_exit { macro_rules! _clap_count_exprs { () => { 0 }; ($e:expr) => { 1 }; - ($e:expr, $($es:expr),+) => { 1 + _clap_count_exprs!($($es),*) }; + ($e:expr, $($es:expr),+) => { 1 + $crate::_clap_count_exprs!($($es),*) }; } /// Convenience macro to generate more complete enums with variants to be used as a type when @@ -267,7 +267,7 @@ macro_rules! _clap_count_exprs { /// /// **NOTE:** This macro automatically implements [`std::str::FromStr`] and [`std::fmt::Display`] /// -/// **NOTE:** These enums support pub (or not) and uses of the #[derive()] traits +/// **NOTE:** These enums support pub (or not) and uses of the `#[derive()]` traits /// /// # Examples /// @@ -324,7 +324,7 @@ macro_rules! arg_enum { $(stringify!($v),)+ ]; format!("valid values: {}", - v.join(" ,")) + v.join(", ")) }), } } @@ -338,7 +338,7 @@ macro_rules! arg_enum { } impl $e { #[allow(dead_code)] - pub fn variants() -> [&'static str; _clap_count_exprs!($(stringify!($v)),+)] { + pub fn variants() -> [&'static str; $crate::_clap_count_exprs!($(stringify!($v)),+)] { [ $(stringify!($v),)+ ] @@ -600,7 +600,8 @@ macro_rules! app_from_crate { /// (author: "Someone E. ") /// (@arg verbose: -v --verbose "Print test information verbosely") /// ) -/// ); +/// ) +/// .get_matches(); /// # } /// ``` /// # Shorthand Syntax for Args @@ -775,9 +776,13 @@ macro_rules! clap_app { (@arg ($arg:expr) $modes:tt $ident:ident[$($target:ident)*] $($tail:tt)*) => { clap_app!{ @arg ($arg $( .$ident(stringify!($target)) )*) $modes $($tail)* } }; -// Inherit builder's functions - (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr)*) $($tail:tt)*) => { - clap_app!{ @arg ($arg.$ident($($expr)*)) $modes $($tail)* } +// Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")` + (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr),*) $($tail:tt)*) => { + clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } + }; +// Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)` + (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr,)*) $($tail:tt)*) => { + clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } }; // Build a subcommand outside of an app. diff --git a/vendor/clap/src/suggestions.rs b/vendor/clap/src/suggestions.rs index 23832cb3a0..06071d216e 100644 --- a/vendor/clap/src/suggestions.rs +++ b/vendor/clap/src/suggestions.rs @@ -44,6 +44,7 @@ where #[cfg_attr(feature = "lints", allow(needless_lifetimes))] pub fn did_you_mean_flag_suffix<'z, T, I>( arg: &str, + args_rest: &'z [&str], longs: I, subcommands: &'z [App], ) -> (String, Option<&'z str>) @@ -51,16 +52,18 @@ where T: AsRef + 'z, I: IntoIterator, { - match did_you_mean(arg, longs) { - Some(candidate) => { - let suffix = format!( - "\n\tDid you mean {}{}?", - Format::Good("--"), - Format::Good(candidate) + if let Some(candidate) = did_you_mean(arg, longs) { + let suffix = format!( + "\n\tDid you mean {}{}?", + Format::Good("--"), + Format::Good(candidate) ); - return (suffix, Some(candidate)); - } - None => for subcommand in subcommands { + return (suffix, Some(candidate)); + } + + subcommands + .into_iter() + .filter_map(|subcommand| { let opts = subcommand .p .flags @@ -68,18 +71,27 @@ where .filter_map(|f| f.s.long) .chain(subcommand.p.opts.iter().filter_map(|o| o.s.long)); - if let Some(candidate) = did_you_mean(arg, opts) { - let suffix = format!( - "\n\tDid you mean to put '{}{}' after the subcommand '{}'?", - Format::Good("--"), - Format::Good(candidate), - Format::Good(subcommand.get_name()) - ); - return (suffix, Some(candidate)); - } - }, - } - (String::new(), None) + let candidate = match did_you_mean(arg, opts) { + Some(candidate) => candidate, + None => return None + }; + let score = match args_rest.iter().position(|x| *x == subcommand.get_name()) { + Some(score) => score, + None => return None + }; + + let suffix = format!( + "\n\tDid you mean to put '{}{}' after the subcommand '{}'?", + Format::Good("--"), + Format::Good(candidate), + Format::Good(subcommand.get_name()) + ); + + Some((score, (suffix, Some(candidate)))) + }) + .min_by_key(|&(score, _)| score) + .map(|(_, suggestion)| suggestion) + .unwrap_or_else(|| (String::new(), None)) } /// Returns a suffix that can be empty, or is the standard 'did you mean' phrase diff --git a/vendor/env_logger-0.5.13/.cargo-checksum.json b/vendor/env_logger-0.5.13/.cargo-checksum.json deleted file mode 100644 index 672fe1d888..0000000000 --- a/vendor/env_logger-0.5.13/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"c1b01561f3dd77e0fdec6312d7a94f2ecc24c6dc2fe2c01dae46304ed7bad6f7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"a7c09976a3d59a675c500c7518def593a9c1f0316bd237118f6063a92d792578","examples/custom_default_format.rs":"799c439f61cb711078f8aa584db537a5758c25b90d44767849dae2ad3822885c","examples/custom_format.rs":"b0321c84bad849626caf5e92ac154537ee894c7fcf220e426ed0a41b3935a0fc","examples/custom_logger.rs":"99fb3c9761ad4c5fe73f4ec2a2bd44b4acf6d1f7b7cfaa16bf0373665d3e2a4b","examples/default.rs":"a763144dca7d156579781a102551076acc42b5e8398c573f9a3484376bd05b2f","examples/direct_logger.rs":"549f6a10e0903d06aca2cc7ba82415b07a23392676101c9bc7aa72b4a9b0b9e2","src/filter/mod.rs":"d6b21d9baa4efee4fe54394e60479bd6958b96b86f5c1d33ef8d1ac472be3be8","src/filter/regex.rs":"5fff47d1d4d0aa3f2bab90636127d3e72aebf800c3b78faba99637220ffdf865","src/filter/string.rs":"52bbd047c31a1afdb3cd1c11629b956f21b3f47bf22e06421baf3d693a045e59","src/fmt.rs":"6e42be7bc75bb2df87be2492f0874efc740eff0d9e6c127ef8e973bff344362e","src/lib.rs":"f98ef584eb610273966d4d261fff7e0e8a7b7f1163fb858f2c0b420bf5581377","tests/log-in-log.rs":"41126910998adfbac771c2a1237fecbc5437344f8e4dfc2f93235bab764a087e","tests/regexp_filter.rs":"44aa6c39de894be090e37083601e501cfffb15e3c0cd36209c48abdf3e2cb120"},"package":"15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"} \ No newline at end of file diff --git a/vendor/env_logger-0.5.13/Cargo.toml b/vendor/env_logger-0.5.13/Cargo.toml deleted file mode 100644 index 3a19c6bca4..0000000000 --- a/vendor/env_logger-0.5.13/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "env_logger" -version = "0.5.13" -authors = ["The Rust Project Developers"] -description = "A logging implementation for `log` which is configured via an environment\nvariable.\n" -documentation = "https://docs.rs/env_logger" -readme = "README.md" -keywords = ["logging", "log", "logger"] -categories = ["development-tools::debugging"] -license = "MIT/Apache-2.0" -repository = "https://github.com/sebasmagri/env_logger/" - -[[test]] -name = "regexp_filter" -harness = false - -[[test]] -name = "log-in-log" -harness = false -[dependencies.atty] -version = "0.2.5" - -[dependencies.humantime] -version = "1.1" - -[dependencies.log] -version = "0.4" -features = ["std"] - -[dependencies.regex] -version = "1.0.3" -optional = true - -[dependencies.termcolor] -version = "1" - -[features] -default = ["regex"] diff --git a/vendor/env_logger-0.5.13/README.md b/vendor/env_logger-0.5.13/README.md deleted file mode 100644 index 332dee8032..0000000000 --- a/vendor/env_logger-0.5.13/README.md +++ /dev/null @@ -1,140 +0,0 @@ -env_logger [![Build Status](https://travis-ci.org/sebasmagri/env_logger.svg?branch=master)](https://travis-ci.org/sebasmagri/env_logger) [![Maintenance](https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg)](https://github.com/sebasmagri/env_logger) [![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger) [![Documentation](https://img.shields.io/badge/docs-current-blue.svg)](https://docs.rs/env_logger) -========== - -Implements a logger that can be configured via environment variables. - -## Usage - -### In libraries - -`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://doc.rust-lang.org/log) crate instead. - -### In executables - -It must be added along with `log` to the project dependencies: - -```toml -[dependencies] -log = "0.4.0" -env_logger = "0.5.13" -``` - -`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging. - -```rust -#[macro_use] -extern crate log; -extern crate env_logger; - -fn main() { - env_logger::init(); - - info!("starting up"); - - // ... -} -``` - -Then when running the executable, specify a value for the `RUST_LOG` -environment variable that corresponds with the log messages you want to show. - -```bash -$ RUST_LOG=info ./main -INFO: 2017-11-09T02:12:24Z: main: starting up -``` - -### In tests - -Tests can use the `env_logger` crate to see log messages generated during that test: - -```toml -[dependencies] -log = "0.4.0" - -[dev-dependencies] -env_logger = "0.5.13" -``` - -```rust -#[macro_use] -extern crate log; - -fn add_one(num: i32) -> i32 { - info!("add_one called with {}", num); - num + 1 -} - -#[cfg(test)] -mod tests { - use super::*; - extern crate env_logger; - - #[test] - fn it_adds_one() { - let _ = env_logger::try_init(); - info!("can log from the test too"); - assert_eq!(3, add_one(2)); - } - - #[test] - fn it_handles_negative_numbers() { - let _ = env_logger::try_init(); - info!("logging from another test"); - assert_eq!(-7, add_one(-8)); - } -} -``` - -Assuming the module under test is called `my_lib`, running the tests with the -`RUST_LOG` filtering to info messages from this module looks like: - -```bash -$ RUST_LOG=my_lib=info cargo test - Running target/debug/my_lib-... - -running 2 tests -INFO: 2017-11-09T02:12:24Z: my_lib::tests: logging from another test -INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with -8 -test tests::it_handles_negative_numbers ... ok -INFO: 2017-11-09T02:12:24Z: my_lib::tests: can log from the test too -INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with 2 -test tests::it_adds_one ... ok - -test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured -``` - -Note that `env_logger::try_init()` needs to be called in each test in which you -want to enable logging. Additionally, the default behavior of tests to -run in parallel means that logging output may be interleaved with test output. -Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by -running one test by specifying its name as an argument to the test binaries as -directed by the `cargo test` help docs: - -```bash -$ RUST_LOG=my_lib=info cargo test it_adds_one - Running target/debug/my_lib-... - -running 1 test -INFO: 2017-11-09T02:12:24Z: my_lib::tests: can log from the test too -INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with 2 -test tests::it_adds_one ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured -``` - -## Configuring log target - -By default, `env_logger` logs to stderr. If you want to log to stdout instead, -you can use the `Builder` to change the log target: - -```rust -use std::env; -use env_logger::{Builder, Target}; - -let mut builder = Builder::new(); -builder.target(Target::Stdout); -if env::var("RUST_LOG").is_ok() { - builder.parse(&env::var("RUST_LOG").unwrap()); -} -builder.init(); -``` diff --git a/vendor/env_logger-0.5.13/examples/custom_default_format.rs b/vendor/env_logger-0.5.13/examples/custom_default_format.rs deleted file mode 100644 index d1a45b6089..0000000000 --- a/vendor/env_logger-0.5.13/examples/custom_default_format.rs +++ /dev/null @@ -1,44 +0,0 @@ -/*! -Disabling parts of the default format. - -Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: - -```no_run,shell -$ export MY_LOG_LEVEL='info' -``` - -Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors -or `auto` to enable them: - -```no_run,shell -$ export MY_LOG_STYLE=never -``` - -If you want to control the logging output completely, see the `custom_logger` example. -*/ - -#[macro_use] -extern crate log; -extern crate env_logger; - -use env_logger::{Env, Builder}; - -fn init_logger() { - let env = Env::default() - .filter("MY_LOG_LEVEL") - .write_style("MY_LOG_STYLE"); - - let mut builder = Builder::from_env(env); - - builder - .default_format_level(false) - .default_format_timestamp_nanos(true); - - builder.init(); -} - -fn main() { - init_logger(); - - info!("a log from `MyLogger`"); -} diff --git a/vendor/env_logger-0.5.13/examples/custom_format.rs b/vendor/env_logger-0.5.13/examples/custom_format.rs deleted file mode 100644 index 68a064d48a..0000000000 --- a/vendor/env_logger-0.5.13/examples/custom_format.rs +++ /dev/null @@ -1,52 +0,0 @@ -/*! -Changing the default logging format. - -Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: - -```no_run,shell -$ export MY_LOG_LEVEL='info' -``` - -Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors -or `auto` to enable them: - -```no_run,shell -$ export MY_LOG_STYLE=never -``` - -If you want to control the logging output completely, see the `custom_logger` example. -*/ - -#[macro_use] -extern crate log; -extern crate env_logger; - -use std::io::Write; - -use env_logger::{Env, Builder, fmt}; - -fn init_logger() { - let env = Env::default() - .filter("MY_LOG_LEVEL") - .write_style("MY_LOG_STYLE"); - - let mut builder = Builder::from_env(env); - - // Use a different format for writing log records - builder.format(|buf, record| { - let mut style = buf.style(); - style.set_bg(fmt::Color::Yellow).set_bold(true); - - let timestamp = buf.timestamp(); - - writeln!(buf, "My formatted log ({}): {}", timestamp, style.value(record.args())) - }); - - builder.init(); -} - -fn main() { - init_logger(); - - info!("a log from `MyLogger`"); -} diff --git a/vendor/env_logger-0.5.13/examples/custom_logger.rs b/vendor/env_logger-0.5.13/examples/custom_logger.rs deleted file mode 100644 index 792c9c8e5e..0000000000 --- a/vendor/env_logger-0.5.13/examples/custom_logger.rs +++ /dev/null @@ -1,60 +0,0 @@ -/*! -Using `env_logger` to drive a custom logger. - -Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: - -```no_run,shell -$ export MY_LOG_LEVEL='info' -``` - -If you only want to change the way logs are formatted, look at the `custom_format` example. -*/ - -#[macro_use] -extern crate log; -extern crate env_logger; -use env_logger::filter::Filter; -use log::{Log, Metadata, Record, SetLoggerError}; - -struct MyLogger { - inner: Filter -} - -impl MyLogger { - fn new() -> MyLogger { - use env_logger::filter::Builder; - let mut builder = Builder::from_env("MY_LOG_LEVEL"); - - MyLogger { - inner: builder.build() - } - } - - fn init() -> Result<(), SetLoggerError> { - let logger = Self::new(); - - log::set_max_level(logger.inner.filter()); - log::set_boxed_logger(Box::new(logger)) - } -} - -impl Log for MyLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - self.inner.enabled(metadata) - } - - fn log(&self, record: &Record) { - // Check if the record is matched by the logger before logging - if self.inner.matches(record) { - println!("{} - {}", record.level(), record.args()); - } - } - - fn flush(&self) { } -} - -fn main() { - MyLogger::init().unwrap(); - - info!("a log from `MyLogger`"); -} diff --git a/vendor/env_logger-0.5.13/examples/default.rs b/vendor/env_logger-0.5.13/examples/default.rs deleted file mode 100644 index 5d799fe054..0000000000 --- a/vendor/env_logger-0.5.13/examples/default.rs +++ /dev/null @@ -1,36 +0,0 @@ -/*! -Using `env_logger`. - -Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: - -```no_run,shell -$ export MY_LOG_LEVEL='info' -``` - -Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors -or `auto` to enable them: - -```no_run,shell -$ export MY_LOG_STYLE=never -``` -*/ - -#[macro_use] -extern crate log; -extern crate env_logger; - -use env_logger::Env; - -fn main() { - let env = Env::default() - .filter_or("MY_LOG_LEVEL", "trace") - .write_style_or("MY_LOG_STYLE", "always"); - - env_logger::init_from_env(env); - - trace!("some trace log"); - debug!("some debug log"); - info!("some information log"); - warn!("some warning log"); - error!("some error log"); -} diff --git a/vendor/env_logger-0.5.13/examples/direct_logger.rs b/vendor/env_logger-0.5.13/examples/direct_logger.rs deleted file mode 100644 index 410230bcdc..0000000000 --- a/vendor/env_logger-0.5.13/examples/direct_logger.rs +++ /dev/null @@ -1,40 +0,0 @@ -/*! -Using `env_logger::Logger` and the `log::Log` trait directly. - -This example doesn't rely on environment variables, or having a static logger installed. -*/ - -extern crate log; -extern crate env_logger; - -fn record() -> log::Record<'static> { - let error_metadata = log::MetadataBuilder::new() - .target("myApp") - .level(log::Level::Error) - .build(); - - log::Record::builder() - .metadata(error_metadata) - .args(format_args!("Error!")) - .line(Some(433)) - .file(Some("app.rs")) - .module_path(Some("server")) - .build() -} - -fn main() { - use log::Log; - - let stylish_logger = env_logger::Builder::new() - .filter(None, log::LevelFilter::Error) - .write_style(env_logger::WriteStyle::Always) - .build(); - - let unstylish_logger = env_logger::Builder::new() - .filter(None, log::LevelFilter::Error) - .write_style(env_logger::WriteStyle::Never) - .build(); - - stylish_logger.log(&record()); - unstylish_logger.log(&record()); -} \ No newline at end of file diff --git a/vendor/env_logger-0.5.13/src/filter/mod.rs b/vendor/env_logger-0.5.13/src/filter/mod.rs deleted file mode 100644 index 80a3f30fa1..0000000000 --- a/vendor/env_logger-0.5.13/src/filter/mod.rs +++ /dev/null @@ -1,568 +0,0 @@ -//! Filtering for log records. -//! -//! This module contains the log filtering used by `env_logger` to match records. -//! You can use the `Filter` type in your own logger implementation to use the same -//! filter parsing and matching as `env_logger`. For more details about the format -//! for directive strings see [Enabling Logging]. -//! -//! ## Using `env_logger` in your own logger -//! -//! You can use `env_logger`'s filtering functionality with your own logger. -//! Call [`Builder::parse`] to parse directives from a string when constructing -//! your logger. Call [`Filter::matches`] to check whether a record should be -//! logged based on the parsed filters when log records are received. -//! -//! ``` -//! extern crate log; -//! extern crate env_logger; -//! use env_logger::filter::Filter; -//! use log::{Log, Metadata, Record}; -//! -//! struct MyLogger { -//! filter: Filter -//! } -//! -//! impl MyLogger { -//! fn new() -> MyLogger { -//! use env_logger::filter::Builder; -//! let mut builder = Builder::new(); -//! -//! // Parse a directives string from an environment variable -//! if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") { -//! builder.parse(filter); -//! } -//! -//! MyLogger { -//! filter: builder.build() -//! } -//! } -//! } -//! -//! impl Log for MyLogger { -//! fn enabled(&self, metadata: &Metadata) -> bool { -//! self.filter.enabled(metadata) -//! } -//! -//! fn log(&self, record: &Record) { -//! // Check if the record is matched by the filter -//! if self.filter.matches(record) { -//! println!("{:?}", record); -//! } -//! } -//! -//! fn flush(&self) {} -//! } -//! # fn main() {} -//! ``` -//! -//! [Enabling Logging]: ../index.html#enabling-logging -//! [`Builder::parse`]: struct.Builder.html#method.parse -//! [`Filter::matches`]: struct.Filter.html#method.matches - -use std::env; -use std::mem; -use std::fmt; -use log::{Level, LevelFilter, Record, Metadata}; - -#[cfg(feature = "regex")] -#[path = "regex.rs"] -mod inner; - -#[cfg(not(feature = "regex"))] -#[path = "string.rs"] -mod inner; - -/// A log filter. -/// -/// This struct can be used to determine whether or not a log record -/// should be written to the output. -/// Use the [`Builder`] type to parse and construct a `Filter`. -/// -/// [`Builder`]: struct.Builder.html -pub struct Filter { - directives: Vec, - filter: Option, -} - -/// A builder for a log filter. -/// -/// It can be used to parse a set of directives from a string before building -/// a [`Filter`] instance. -/// -/// ## Example -/// -/// ``` -/// #[macro_use] -/// extern crate log; -/// extern crate env_logger; -/// -/// use std::env; -/// use std::io; -/// use env_logger::filter::Builder; -/// -/// fn main() { -/// let mut builder = Builder::new(); -/// -/// // Parse a logging filter from an environment variable. -/// if let Ok(rust_log) = env::var("RUST_LOG") { -/// builder.parse(&rust_log); -/// } -/// -/// let filter = builder.build(); -/// } -/// ``` -/// -/// [`Filter`]: struct.Filter.html -pub struct Builder { - directives: Vec, - filter: Option, -} - -#[derive(Debug)] -struct Directive { - name: Option, - level: LevelFilter, -} - -impl Filter { - /// Returns the maximum `LevelFilter` that this filter instance is - /// configured to output. - /// - /// # Example - /// - /// ```rust - /// extern crate log; - /// extern crate env_logger; - /// - /// use log::LevelFilter; - /// use env_logger::filter::Builder; - /// - /// fn main() { - /// let mut builder = Builder::new(); - /// builder.filter(Some("module1"), LevelFilter::Info); - /// builder.filter(Some("module2"), LevelFilter::Error); - /// - /// let filter = builder.build(); - /// assert_eq!(filter.filter(), LevelFilter::Info); - /// } - /// ``` - pub fn filter(&self) -> LevelFilter { - self.directives.iter() - .map(|d| d.level) - .max() - .unwrap_or(LevelFilter::Off) - } - - /// Checks if this record matches the configured filter. - pub fn matches(&self, record: &Record) -> bool { - if !self.enabled(record.metadata()) { - return false; - } - - if let Some(filter) = self.filter.as_ref() { - if !filter.is_match(&*record.args().to_string()) { - return false; - } - } - - true - } - - /// Determines if a log message with the specified metadata would be logged. - pub fn enabled(&self, metadata: &Metadata) -> bool { - let level = metadata.level(); - let target = metadata.target(); - - enabled(&self.directives, level, target) - } -} - -impl Builder { - /// Initializes the filter builder with defaults. - pub fn new() -> Builder { - Builder { - directives: Vec::new(), - filter: None, - } - } - - /// Initializes the filter builder from an environment. - pub fn from_env(env: &str) -> Builder { - let mut builder = Builder::new(); - - if let Ok(s) = env::var(env) { - builder.parse(&s); - } - - builder - } - - /// Adds a directive to the filter for a specific module. - pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { - self.filter(Some(module), level) - } - - /// Adds a directive to the filter for all modules. - pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { - self.filter(None, level) - } - - /// Adds a directive to the filter. - /// - /// The given module (if any) will log at most the specified level provided. - /// If no module is provided then the filter will apply to all log messages. - pub fn filter(&mut self, - module: Option<&str>, - level: LevelFilter) -> &mut Self { - self.directives.push(Directive { - name: module.map(|s| s.to_string()), - level, - }); - self - } - - /// Parses the directives string. - /// - /// See the [Enabling Logging] section for more details. - /// - /// [Enabling Logging]: ../index.html#enabling-logging - pub fn parse(&mut self, filters: &str) -> &mut Self { - let (directives, filter) = parse_spec(filters); - - self.filter = filter; - - for directive in directives { - self.directives.push(directive); - } - self - } - - /// Build a log filter. - pub fn build(&mut self) -> Filter { - if self.directives.is_empty() { - // Adds the default filter if none exist - self.directives.push(Directive { - name: None, - level: LevelFilter::Error, - }); - } else { - // Sort the directives by length of their name, this allows a - // little more efficient lookup at runtime. - self.directives.sort_by(|a, b| { - let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0); - let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0); - alen.cmp(&blen) - }); - } - - Filter { - directives: mem::replace(&mut self.directives, Vec::new()), - filter: mem::replace(&mut self.filter, None), - } - } -} - -impl Default for Builder { - fn default() -> Self { - Builder::new() - } -} - -impl fmt::Debug for Filter { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Filter") - .field("filter", &self.filter) - .field("directives", &self.directives) - .finish() - } -} - -impl fmt::Debug for Builder { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Filter") - .field("filter", &self.filter) - .field("directives", &self.directives) - .finish() - } -} - -/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo") -/// and return a vector with log directives. -fn parse_spec(spec: &str) -> (Vec, Option) { - let mut dirs = Vec::new(); - - let mut parts = spec.split('/'); - let mods = parts.next(); - let filter = parts.next(); - if parts.next().is_some() { - println!("warning: invalid logging spec '{}', \ - ignoring it (too many '/'s)", spec); - return (dirs, None); - } - mods.map(|m| { for s in m.split(',') { - if s.len() == 0 { continue } - let mut parts = s.split('='); - let (log_level, name) = match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) { - (Some(part0), None, None) => { - // if the single argument is a log-level string or number, - // treat that as a global fallback - match part0.parse() { - Ok(num) => (num, None), - Err(_) => (LevelFilter::max(), Some(part0)), - } - } - (Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)), - (Some(part0), Some(part1), None) => { - match part1.parse() { - Ok(num) => (num, Some(part0)), - _ => { - println!("warning: invalid logging spec '{}', \ - ignoring it", part1); - continue - } - } - }, - _ => { - println!("warning: invalid logging spec '{}', \ - ignoring it", s); - continue - } - }; - dirs.push(Directive { - name: name.map(|s| s.to_string()), - level: log_level, - }); - }}); - - let filter = filter.map_or(None, |filter| { - match inner::Filter::new(filter) { - Ok(re) => Some(re), - Err(e) => { - println!("warning: invalid regex filter - {}", e); - None - } - } - }); - - return (dirs, filter); -} - - -// Check whether a level and target are enabled by the set of directives. -fn enabled(directives: &[Directive], level: Level, target: &str) -> bool { - // Search for the longest match, the vector is assumed to be pre-sorted. - for directive in directives.iter().rev() { - match directive.name { - Some(ref name) if !target.starts_with(&**name) => {}, - Some(..) | None => { - return level <= directive.level - } - } - } - false -} - -#[cfg(test)] -mod tests { - use log::{Level, LevelFilter}; - - use super::{Builder, Filter, Directive, parse_spec, enabled}; - - fn make_logger_filter(dirs: Vec) -> Filter { - let mut logger = Builder::new().build(); - logger.directives = dirs; - logger - } - - #[test] - fn filter_info() { - let logger = Builder::new().filter(None, LevelFilter::Info).build(); - assert!(enabled(&logger.directives, Level::Info, "crate1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate1")); - } - - #[test] - fn filter_beginning_longest_match() { - let logger = Builder::new() - .filter(Some("crate2"), LevelFilter::Info) - .filter(Some("crate2::mod"), LevelFilter::Debug) - .filter(Some("crate1::mod1"), LevelFilter::Warn) - .build(); - assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - #[test] - fn parse_default() { - let logger = Builder::new().parse("info,crate1::mod1=warn").build(); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn match_full_path() { - let logger = make_logger_filter(vec![ - Directive { - name: Some("crate2".to_string()), - level: LevelFilter::Info - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn - } - ]); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - #[test] - fn no_match() { - let logger = make_logger_filter(vec![ - Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, - Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } - ]); - assert!(!enabled(&logger.directives, Level::Warn, "crate3")); - } - - #[test] - fn match_beginning() { - let logger = make_logger_filter(vec![ - Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, - Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } - ]); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod1")); - } - - #[test] - fn match_beginning_longest_match() { - let logger = make_logger_filter(vec![ - Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, - Directive { name: Some("crate2::mod".to_string()), level: LevelFilter::Debug }, - Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } - ]); - assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - #[test] - fn match_default() { - let logger = make_logger_filter(vec![ - Directive { name: None, level: LevelFilter::Info }, - Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } - ]); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn zero_level() { - let logger = make_logger_filter(vec![ - Directive { name: None, level: LevelFilter::Info }, - Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Off } - ]); - assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn parse_spec_valid() { - let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug"); - assert_eq!(dirs.len(), 3); - assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Error); - - assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::max()); - - assert_eq!(dirs[2].name, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_invalid_crate() { - // test parse_spec with multiple = in specification - let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_invalid_level() { - // test parse_spec with 'noNumber' as log level - let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_string_level() { - // test parse_spec with 'warn' as log level - let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_empty_level() { - // test parse_spec with '' as log level - let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2="); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::max()); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_global() { - // test parse_spec with no crate - let (dirs, filter) = parse_spec("warn,crate2=debug"); - assert_eq!(dirs.len(), 2); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert_eq!(dirs[1].name, Some("crate2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_valid_filter() { - let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc"); - assert_eq!(dirs.len(), 3); - assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Error); - - assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::max()); - - assert_eq!(dirs[2].name, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::Debug); - assert!(filter.is_some() && filter.unwrap().to_string() == "abc"); - } - - #[test] - fn parse_spec_invalid_crate_filter() { - let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_some() && filter.unwrap().to_string() == "a.c"); - } - - #[test] - fn parse_spec_empty_with_filter() { - let (dirs, filter) = parse_spec("crate1/a*c"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::max()); - assert!(filter.is_some() && filter.unwrap().to_string() == "a*c"); - } -} diff --git a/vendor/env_logger-0.5.13/src/filter/regex.rs b/vendor/env_logger-0.5.13/src/filter/regex.rs deleted file mode 100644 index a042654135..0000000000 --- a/vendor/env_logger-0.5.13/src/filter/regex.rs +++ /dev/null @@ -1,29 +0,0 @@ -extern crate regex; - -use std::fmt; - -use self::regex::Regex; - -#[derive(Debug)] -pub struct Filter { - inner: Regex, -} - -impl Filter { - pub fn new(spec: &str) -> Result { - match Regex::new(spec){ - Ok(r) => Ok(Filter { inner: r }), - Err(e) => Err(e.to_string()), - } - } - - pub fn is_match(&self, s: &str) -> bool { - self.inner.is_match(s) - } -} - -impl fmt::Display for Filter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/vendor/env_logger-0.5.13/src/filter/string.rs b/vendor/env_logger-0.5.13/src/filter/string.rs deleted file mode 100644 index 96d7ecca12..0000000000 --- a/vendor/env_logger-0.5.13/src/filter/string.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::fmt; - -#[derive(Debug)] -pub struct Filter { - inner: String, -} - -impl Filter { - pub fn new(spec: &str) -> Result { - Ok(Filter { inner: spec.to_string() }) - } - - pub fn is_match(&self, s: &str) -> bool { - s.contains(&self.inner) - } -} - -impl fmt::Display for Filter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/vendor/env_logger-0.5.13/src/fmt.rs b/vendor/env_logger-0.5.13/src/fmt.rs deleted file mode 100644 index d90210fa3b..0000000000 --- a/vendor/env_logger-0.5.13/src/fmt.rs +++ /dev/null @@ -1,844 +0,0 @@ -//! Formatting for log records. -//! -//! This module contains a [`Formatter`] that can be used to format log records -//! into without needing temporary allocations. Usually you won't need to worry -//! about the contents of this module and can use the `Formatter` like an ordinary -//! [`Write`]. -//! -//! # Formatting log records -//! -//! The format used to print log records can be customised using the [`Builder::format`] -//! method. -//! Custom formats can apply different color and weight to printed values using -//! [`Style`] builders. -//! -//! ``` -//! use std::io::Write; -//! use env_logger::fmt::Color; -//! -//! let mut builder = env_logger::Builder::new(); -//! -//! builder.format(|buf, record| { -//! let mut level_style = buf.style(); -//! -//! level_style.set_color(Color::Red).set_bold(true); -//! -//! writeln!(buf, "{}: {}", -//! level_style.value(record.level()), -//! record.args()) -//! }); -//! ``` -//! -//! [`Formatter`]: struct.Formatter.html -//! [`Style`]: struct.Style.html -//! [`Builder::format`]: ../struct.Builder.html#method.format -//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html - -use std::io::prelude::*; -use std::{io, fmt}; -use std::rc::Rc; -use std::str::FromStr; -use std::error::Error; -use std::cell::RefCell; -use std::time::SystemTime; - -use log::Level; -use termcolor::{self, ColorSpec, ColorChoice, Buffer, BufferWriter, WriteColor}; -use atty; -use humantime::{format_rfc3339_seconds, format_rfc3339_nanos}; - -/// A formatter to write logs into. -/// -/// `Formatter` implements the standard [`Write`] trait for writing log records. -/// It also supports terminal colors, through the [`style`] method. -/// -/// # Examples -/// -/// Use the [`writeln`] macro to easily format a log record: -/// -/// ``` -/// use std::io::Write; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())); -/// ``` -/// -/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html -/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html -/// [`style`]: #method.style -pub struct Formatter { - buf: Rc>, - write_style: WriteStyle, -} - -/// A set of styles to apply to the terminal output. -/// -/// Call [`Formatter::style`] to get a `Style` and use the builder methods to -/// set styling properties, like [color] and [weight]. -/// To print a value using the style, wrap it in a call to [`value`] when the log -/// record is formatted. -/// -/// # Examples -/// -/// Create a bold, red colored style and use it to print the log level: -/// -/// ``` -/// use std::io::Write; -/// use env_logger::fmt::Color; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| { -/// let mut level_style = buf.style(); -/// -/// level_style.set_color(Color::Red).set_bold(true); -/// -/// writeln!(buf, "{}: {}", -/// level_style.value(record.level()), -/// record.args()) -/// }); -/// ``` -/// -/// Styles can be re-used to output multiple values: -/// -/// ``` -/// use std::io::Write; -/// use env_logger::fmt::Color; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| { -/// let mut bold = buf.style(); -/// -/// bold.set_bold(true); -/// -/// writeln!(buf, "{}: {} {}", -/// bold.value(record.level()), -/// bold.value("some bold text"), -/// record.args()) -/// }); -/// ``` -/// -/// [`Formatter::style`]: struct.Formatter.html#method.style -/// [color]: #method.set_color -/// [weight]: #method.set_bold -/// [`value`]: #method.value -#[derive(Clone)] -pub struct Style { - buf: Rc>, - spec: ColorSpec, -} - -/// A value that can be printed using the given styles. -/// -/// It is the result of calling [`Style::value`]. -/// -/// [`Style::value`]: struct.Style.html#method.value -pub struct StyledValue<'a, T> { - style: &'a Style, - value: T, -} - -/// An [RFC3339] formatted timestamp. -/// -/// The timestamp implements [`Display`] and can be written to a [`Formatter`]. -/// -/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt -/// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html -/// [`Formatter`]: struct.Formatter.html -pub struct Timestamp(SystemTime); - -/// An [RFC3339] formatted timestamp with nanos -#[derive(Debug)] -pub struct PreciseTimestamp(SystemTime); - -/// Log target, either `stdout` or `stderr`. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum Target { - /// Logs will be sent to standard output. - Stdout, - /// Logs will be sent to standard error. - Stderr, -} - -impl Default for Target { - fn default() -> Self { - Target::Stderr - } -} - -/// Whether or not to print styles to the target. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum WriteStyle { - /// Try to print styles, but don't force the issue. - Auto, - /// Try very hard to print styles. - Always, - /// Never print styles. - Never, -} - -impl Default for WriteStyle { - fn default() -> Self { - WriteStyle::Auto - } -} - -/// A terminal target with color awareness. -pub(crate) struct Writer { - inner: BufferWriter, - write_style: WriteStyle, -} - -impl Writer { - pub(crate) fn write_style(&self) -> WriteStyle { - self.write_style - } -} - -/// A builder for a terminal writer. -/// -/// The target and style choice can be configured before building. -pub(crate) struct Builder { - target: Target, - write_style: WriteStyle, -} - -impl Builder { - /// Initialize the writer builder with defaults. - pub fn new() -> Self { - Builder { - target: Default::default(), - write_style: Default::default(), - } - } - - /// Set the target to write to. - pub fn target(&mut self, target: Target) -> &mut Self { - self.target = target; - self - } - - /// Parses a style choice string. - /// - /// See the [Disabling colors] section for more details. - /// - /// [Disabling colors]: ../index.html#disabling-colors - pub fn parse(&mut self, write_style: &str) -> &mut Self { - self.write_style(parse_write_style(write_style)) - } - - /// Whether or not to print style characters when writing. - pub fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { - self.write_style = write_style; - self - } - - /// Build a terminal writer. - pub fn build(&mut self) -> Writer { - let color_choice = match self.write_style { - WriteStyle::Auto => { - if atty::is(match self.target { - Target::Stderr => atty::Stream::Stderr, - Target::Stdout => atty::Stream::Stdout, - }) { - ColorChoice::Auto - } else { - ColorChoice::Never - } - }, - WriteStyle::Always => ColorChoice::Always, - WriteStyle::Never => ColorChoice::Never, - }; - - let writer = match self.target { - Target::Stderr => BufferWriter::stderr(color_choice), - Target::Stdout => BufferWriter::stdout(color_choice), - }; - - Writer { - inner: writer, - write_style: self.write_style, - } - } -} - -impl Default for Builder { - fn default() -> Self { - Builder::new() - } -} - -impl Style { - /// Set the text color. - /// - /// # Examples - /// - /// Create a style with red text: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_color(Color::Red); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_color(&mut self, color: Color) -> &mut Style { - self.spec.set_fg(color.into_termcolor()); - self - } - - /// Set the text weight. - /// - /// If `yes` is true then text will be written in bold. - /// If `yes` is false then text will be written in the default weight. - /// - /// # Examples - /// - /// Create a style with bold text: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_bold(true); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_bold(&mut self, yes: bool) -> &mut Style { - self.spec.set_bold(yes); - self - } - - /// Set the text intensity. - /// - /// If `yes` is true then text will be written in a brighter color. - /// If `yes` is false then text will be written in the default color. - /// - /// # Examples - /// - /// Create a style with intense text: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_intense(true); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_intense(&mut self, yes: bool) -> &mut Style { - self.spec.set_intense(yes); - self - } - - /// Set the background color. - /// - /// # Examples - /// - /// Create a style with a yellow background: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_bg(Color::Yellow); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_bg(&mut self, color: Color) -> &mut Style { - self.spec.set_bg(color.into_termcolor()); - self - } - - /// Wrap a value in the style. - /// - /// The same `Style` can be used to print multiple different values. - /// - /// # Examples - /// - /// Create a bold, red colored style and use it to print the log level: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_color(Color::Red).set_bold(true); - /// - /// writeln!(buf, "{}: {}", - /// style.value(record.level()), - /// record.args()) - /// }); - /// ``` - pub fn value(&self, value: T) -> StyledValue { - StyledValue { - style: &self, - value - } - } -} - -impl Formatter { - pub(crate) fn new(writer: &Writer) -> Self { - Formatter { - buf: Rc::new(RefCell::new(writer.inner.buffer())), - write_style: writer.write_style(), - } - } - - pub(crate) fn write_style(&self) -> WriteStyle { - self.write_style - } - - /// Begin a new [`Style`]. - /// - /// # Examples - /// - /// Create a bold, red colored style and use it to print the log level: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut level_style = buf.style(); - /// - /// level_style.set_color(Color::Red).set_bold(true); - /// - /// writeln!(buf, "{}: {}", - /// level_style.value(record.level()), - /// record.args()) - /// }); - /// ``` - /// - /// [`Style`]: struct.Style.html - pub fn style(&self) -> Style { - Style { - buf: self.buf.clone(), - spec: ColorSpec::new(), - } - } - - /// Get the default [`Style`] for the given level. - pub fn default_level_style(&self, level: Level) -> Style { - let mut level_style = self.style(); - match level { - Level::Trace => level_style.set_color(Color::White), - Level::Debug => level_style.set_color(Color::Blue), - Level::Info => level_style.set_color(Color::Green), - Level::Warn => level_style.set_color(Color::Yellow), - Level::Error => level_style.set_color(Color::Red).set_bold(true), - }; - level_style - } - - /// Get a [`Timestamp`] for the current date and time in UTC. - /// - /// # Examples - /// - /// Include the current timestamp with the log record: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let ts = buf.timestamp(); - /// - /// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args()) - /// }); - /// ``` - /// - /// [`Timestamp`]: struct.Timestamp.html - pub fn timestamp(&self) -> Timestamp { - Timestamp(SystemTime::now()) - } - - /// Get a [`PreciseTimestamp`] for the current date and time in UTC with nanos. - pub fn precise_timestamp(&self) -> PreciseTimestamp { - PreciseTimestamp(SystemTime::now()) - } - - pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { - writer.inner.print(&self.buf.borrow()) - } - - pub(crate) fn clear(&mut self) { - self.buf.borrow_mut().clear() - } -} - -impl Write for Formatter { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.buf.borrow_mut().write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.buf.borrow_mut().flush() - } -} - -impl<'a, T> StyledValue<'a, T> { - fn write_fmt(&self, f: F) -> fmt::Result - where - F: FnOnce() -> fmt::Result, - { - self.style.buf.borrow_mut().set_color(&self.style.spec).map_err(|_| fmt::Error)?; - - // Always try to reset the terminal style, even if writing failed - let write = f(); - let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error); - - write.and(reset) - } -} - -impl fmt::Debug for Timestamp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation. - struct TimestampValue<'a>(&'a Timestamp); - - impl<'a> fmt::Debug for TimestampValue<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } - } - - f.debug_tuple("Timestamp") - .field(&TimestampValue(&self)) - .finish() - } -} - -impl fmt::Debug for Writer { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Writer").finish() - } -} - -impl fmt::Debug for Formatter { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Formatter").finish() - } -} - -impl fmt::Debug for Builder { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Logger") - .field("target", &self.target) - .field("write_style", &self.write_style) - .finish() - } -} - -impl fmt::Debug for Style { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Style").field("spec", &self.spec).finish() - } -} - -macro_rules! impl_styled_value_fmt { - ($($fmt_trait:path),*) => { - $( - impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - self.write_fmt(|| T::fmt(&self.value, f)) - } - } - )* - }; -} - -impl_styled_value_fmt!( - fmt::Debug, - fmt::Display, - fmt::Pointer, - fmt::Octal, - fmt::Binary, - fmt::UpperHex, - fmt::LowerHex, - fmt::UpperExp, - fmt::LowerExp); - -impl fmt::Display for Timestamp { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - format_rfc3339_seconds(self.0).fmt(f) - } -} - -impl fmt::Display for PreciseTimestamp { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - format_rfc3339_nanos(self.0).fmt(f) - } -} - -// The `Color` type is copied from https://github.com/BurntSushi/ripgrep/tree/master/termcolor - -/// The set of available colors for the terminal foreground/background. -/// -/// The `Ansi256` and `Rgb` colors will only output the correct codes when -/// paired with the `Ansi` `WriteColor` implementation. -/// -/// The `Ansi256` and `Rgb` color types are not supported when writing colors -/// on Windows using the console. If they are used on Windows, then they are -/// silently ignored and no colors will be emitted. -/// -/// This set may expand over time. -/// -/// This type has a `FromStr` impl that can parse colors from their human -/// readable form. The format is as follows: -/// -/// 1. Any of the explicitly listed colors in English. They are matched -/// case insensitively. -/// 2. A single 8-bit integer, in either decimal or hexadecimal format. -/// 3. A triple of 8-bit integers separated by a comma, where each integer is -/// in decimal or hexadecimal format. -/// -/// Hexadecimal numbers are written with a `0x` prefix. -#[allow(missing_docs)] -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum Color { - Black, - Blue, - Green, - Red, - Cyan, - Magenta, - Yellow, - White, - Ansi256(u8), - Rgb(u8, u8, u8), - #[doc(hidden)] - __Nonexhaustive, -} - -/// An error from parsing an invalid color specification. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ParseColorError(ParseColorErrorKind); - -#[derive(Clone, Debug, Eq, PartialEq)] -enum ParseColorErrorKind { - /// An error originating from `termcolor`. - TermColor(termcolor::ParseColorError), - /// An error converting the `termcolor` color to a `env_logger::Color`. - /// - /// This variant should only get reached if a user uses a new spec that's - /// valid for `termcolor`, but not recognised in `env_logger` yet. - Unrecognized { - given: String, - } -} - -impl ParseColorError { - fn termcolor(err: termcolor::ParseColorError) -> Self { - ParseColorError(ParseColorErrorKind::TermColor(err)) - } - - fn unrecognized(given: String) -> Self { - ParseColorError(ParseColorErrorKind::Unrecognized { given }) - } - - /// Return the string that couldn't be parsed as a valid color. - pub fn invalid(&self) -> &str { - match self.0 { - ParseColorErrorKind::TermColor(ref err) => err.invalid(), - ParseColorErrorKind::Unrecognized { ref given, .. } => given, - } - } -} - -impl Error for ParseColorError { - fn description(&self) -> &str { - match self.0 { - ParseColorErrorKind::TermColor(ref err) => err.description(), - ParseColorErrorKind::Unrecognized { .. } => "unrecognized color value", - } - } -} - -impl fmt::Display for ParseColorError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.0 { - ParseColorErrorKind::TermColor(ref err) => fmt::Display::fmt(err, f), - ParseColorErrorKind::Unrecognized { ref given, .. } => { - write!(f, "unrecognized color value '{}'", given) - } - } - } -} - -impl Color { - fn into_termcolor(self) -> Option { - match self { - Color::Black => Some(termcolor::Color::Black), - Color::Blue => Some(termcolor::Color::Blue), - Color::Green => Some(termcolor::Color::Green), - Color::Red => Some(termcolor::Color::Red), - Color::Cyan => Some(termcolor::Color::Cyan), - Color::Magenta => Some(termcolor::Color::Magenta), - Color::Yellow => Some(termcolor::Color::Yellow), - Color::White => Some(termcolor::Color::White), - Color::Ansi256(value) => Some(termcolor::Color::Ansi256(value)), - Color::Rgb(r, g, b) => Some(termcolor::Color::Rgb(r, g, b)), - _ => None, - } - } - - fn from_termcolor(color: termcolor::Color) -> Option { - match color { - termcolor::Color::Black => Some(Color::Black), - termcolor::Color::Blue => Some(Color::Blue), - termcolor::Color::Green => Some(Color::Green), - termcolor::Color::Red => Some(Color::Red), - termcolor::Color::Cyan => Some(Color::Cyan), - termcolor::Color::Magenta => Some(Color::Magenta), - termcolor::Color::Yellow => Some(Color::Yellow), - termcolor::Color::White => Some(Color::White), - termcolor::Color::Ansi256(value) => Some(Color::Ansi256(value)), - termcolor::Color::Rgb(r, g, b) => Some(Color::Rgb(r, g, b)), - _ => None, - } - } -} - -impl FromStr for Color { - type Err = ParseColorError; - - fn from_str(s: &str) -> Result { - let tc = termcolor::Color::from_str(s).map_err(ParseColorError::termcolor)?; - Color::from_termcolor(tc).ok_or_else(|| ParseColorError::unrecognized(s.into())) - } -} - -fn parse_write_style(spec: &str) -> WriteStyle { - match spec { - "auto" => WriteStyle::Auto, - "always" => WriteStyle::Always, - "never" => WriteStyle::Never, - _ => Default::default(), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_write_style_valid() { - let inputs = vec![ - ("auto", WriteStyle::Auto), - ("always", WriteStyle::Always), - ("never", WriteStyle::Never), - ]; - - for (input, expected) in inputs { - assert_eq!(expected, parse_write_style(input)); - } - } - - #[test] - fn parse_write_style_invalid() { - let inputs = vec![ - "", - "true", - "false", - "NEVER!!" - ]; - - for input in inputs { - assert_eq!(WriteStyle::Auto, parse_write_style(input)); - } - } - - #[test] - fn parse_color_name_valid() { - let inputs = vec![ - "black", - "blue", - "green", - "red", - "cyan", - "magenta", - "yellow", - "white", - ]; - - for input in inputs { - assert!(Color::from_str(input).is_ok()); - } - } - - #[test] - fn parse_color_ansi_valid() { - let inputs = vec![ - "7", - "32", - "0xFF", - ]; - - for input in inputs { - assert!(Color::from_str(input).is_ok()); - } - } - - #[test] - fn parse_color_rgb_valid() { - let inputs = vec![ - "0,0,0", - "0,128,255", - "0x0,0x0,0x0", - "0x33,0x66,0xFF", - ]; - - for input in inputs { - assert!(Color::from_str(input).is_ok()); - } - } - - #[test] - fn parse_color_invalid() { - let inputs = vec![ - "not_a_color", - "256", - "0,0", - "0,0,256", - ]; - - for input in inputs { - let err = Color::from_str(input).unwrap_err(); - assert_eq!(input, err.invalid()); - } - } -} diff --git a/vendor/env_logger-0.5.13/src/lib.rs b/vendor/env_logger-0.5.13/src/lib.rs deleted file mode 100644 index 90058ee77d..0000000000 --- a/vendor/env_logger-0.5.13/src/lib.rs +++ /dev/null @@ -1,1125 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A simple logger configured via environment variables which writes -//! to stdout or stderr, for use with the logging facade exposed by the -//! [`log` crate][log-crate-url]. -//! -//! ## Example -//! -//! ``` -//! #[macro_use] extern crate log; -//! extern crate env_logger; -//! -//! use log::Level; -//! -//! fn main() { -//! env_logger::init(); -//! -//! debug!("this is a debug {}", "message"); -//! error!("this is printed by default"); -//! -//! if log_enabled!(Level::Info) { -//! let x = 3 * 4; // expensive computation -//! info!("the answer was: {}", x); -//! } -//! } -//! ``` -//! -//! Assumes the binary is `main`: -//! -//! ```{.bash} -//! $ RUST_LOG=error ./main -//! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default -//! ``` -//! -//! ```{.bash} -//! $ RUST_LOG=info ./main -//! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default -//! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 -//! ``` -//! -//! ```{.bash} -//! $ RUST_LOG=debug ./main -//! DEBUG: 2017-11-09T02:12:24Z: main: this is a debug message -//! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default -//! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 -//! ``` -//! -//! You can also set the log level on a per module basis: -//! -//! ```{.bash} -//! $ RUST_LOG=main=info ./main -//! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default -//! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 -//! ``` -//! -//! And enable all logging: -//! -//! ```{.bash} -//! $ RUST_LOG=main ./main -//! DEBUG: 2017-11-09T02:12:24Z: main: this is a debug message -//! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default -//! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 -//! ``` -//! -//! If the binary name contains hyphens, you will need to replace -//! them with underscores: -//! -//! ```{.bash} -//! $ RUST_LOG=my_app ./my-app -//! DEBUG: 2017-11-09T02:12:24Z: my_app: this is a debug message -//! ERROR: 2017-11-09T02:12:24Z: my_app: this is printed by default -//! INFO: 2017-11-09T02:12:24Z: my_app: the answer was: 12 -//! ``` -//! -//! This is because Rust modules and crates cannot contain hyphens -//! in their name, although `cargo` continues to accept them. -//! -//! See the documentation for the [`log` crate][log-crate-url] for more -//! information about its API. -//! -//! ## Enabling logging -//! -//! Log levels are controlled on a per-module basis, and by default all logging -//! is disabled except for `error!`. Logging is controlled via the `RUST_LOG` -//! environment variable. The value of this environment variable is a -//! comma-separated list of logging directives. A logging directive is of the -//! form: -//! -//! ```text -//! path::to::module=level -//! ``` -//! -//! The path to the module is rooted in the name of the crate it was compiled -//! for, so if your program is contained in a file `hello.rs`, for example, to -//! turn on logging for this file you would use a value of `RUST_LOG=hello`. -//! Furthermore, this path is a prefix-search, so all modules nested in the -//! specified module will also have logging enabled. -//! -//! The actual `level` is optional to specify. If omitted, all logging will -//! be enabled. If specified, it must be one of the strings `debug`, `error`, -//! `info`, `warn`, or `trace`. -//! -//! As the log level for a module is optional, the module to enable logging for -//! is also optional. If only a `level` is provided, then the global log -//! level for all modules is set to this value. -//! -//! Some examples of valid values of `RUST_LOG` are: -//! -//! * `hello` turns on all logging for the 'hello' module -//! * `info` turns on all info logging -//! * `hello=debug` turns on debug logging for 'hello' -//! * `hello,std::option` turns on hello, and std's option logging -//! * `error,hello=warn` turn on global error logging and also warn for hello -//! -//! ## Filtering results -//! -//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` -//! followed by a regex. Each message is checked against the regex, and is only -//! logged if it matches. Note that the matching is done after formatting the -//! log string but before adding any logging meta-data. There is a single filter -//! for all modules. -//! -//! Some examples: -//! -//! * `hello/foo` turns on all logging for the 'hello' module where the log -//! message includes 'foo'. -//! * `info/f.o` turns on all info logging where the log message includes 'foo', -//! 'f1o', 'fao', etc. -//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log -//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. -//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also -//! warn for hello. In both cases the log message must include a single digit -//! number followed by 'scopes'. -//! -//! ## Disabling colors -//! -//! Colors and other styles can be configured with the `RUST_LOG_STYLE` -//! environment variable. It accepts the following values: -//! -//! * `auto` (default) will attempt to print style characters, but don't force the issue. -//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. -//! * `always` will always print style characters even if they aren't supported by the terminal. -//! This includes emitting ANSI colors on Windows if the console API is unavailable. -//! * `never` will never print style characters. -//! -//! ## Tweaking the default format -//! -//! Parts of the default format can be excluded from the log output using the [`Builder`]. -//! The following example excludes the timestamp from the log output: -//! -//! ``` -//! #[macro_use] extern crate log; -//! extern crate env_logger; -//! -//! use log::Level; -//! -//! fn main() { -//! env_logger::Builder::from_default_env() -//! .default_format_timestamp(false) -//! .init(); -//! -//! debug!("this is a debug {}", "message"); -//! error!("this is printed by default"); -//! -//! if log_enabled!(Level::Info) { -//! let x = 3 * 4; // expensive computation -//! info!("the answer was: {}", x); -//! } -//! } -//! ``` -//! -//! ## Specifying defaults for environment variables -//! -//! `env_logger` can read configuration from environment variables. -//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type. -//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable -//! isn't set: -//! -//! ``` -//! #[macro_use] extern crate log; -//! extern crate env_logger; -//! -//! use log::Level; -//! -//! fn main() { -//! let env = env_logger::Env::default() -//! .filter_or(env_logger::DEFAULT_FILTER_ENV, "warn"); -//! -//! env_logger::Builder::from_env(env).init(); -//! } -//! ``` -//! -//! [log-crate-url]: https://docs.rs/log/ -//! [`Builder`]: struct.Builder.html -//! [`Env`]: struct.Env.html - -#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/env_logger/0.5.13")] -#![cfg_attr(test, deny(warnings))] - -// When compiled for the rustc compiler itself we want to make sure that this is -// an unstable crate -#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] -#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] - -#![deny(missing_debug_implementations, missing_docs, warnings)] - -extern crate log; -extern crate termcolor; -extern crate humantime; -extern crate atty; - -use std::env; -use std::borrow::Cow; -use std::io::prelude::*; -use std::io; -use std::mem; -use std::cell::RefCell; - -use log::{Log, LevelFilter, Record, SetLoggerError, Metadata}; - -pub mod filter; -pub mod fmt; - -pub use self::fmt::{Target, WriteStyle, Color, Formatter}; - -/// The default name for the environment variable to read filters from. -pub const DEFAULT_FILTER_ENV: &'static str = "RUST_LOG"; - -/// The default name for the environment variable to read style preferences from. -pub const DEFAULT_WRITE_STYLE_ENV: &'static str = "RUST_LOG_STYLE"; - -/// Set of environment variables to configure from. -/// -/// # Default environment variables -/// -/// By default, the `Env` will read the following environment variables: -/// -/// - `RUST_LOG`: the level filter -/// - `RUST_LOG_STYLE`: whether or not to print styles with records. -/// -/// These sources can be configured using the builder methods on `Env`. -#[derive(Debug)] -pub struct Env<'a> { - filter: Var<'a>, - write_style: Var<'a>, -} - -#[derive(Debug)] -struct Var<'a> { - name: Cow<'a, str>, - default: Option>, -} - -/// The env logger. -/// -/// This struct implements the `Log` trait from the [`log` crate][log-crate-url], -/// which allows it to act as a logger. -/// -/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] -/// methods will each construct a `Logger` and immediately initialize it as the -/// default global logger. -/// -/// If you'd instead need access to the constructed `Logger`, you can use -/// the associated [`Builder`] and install it with the -/// [`log` crate][log-crate-url] directly. -/// -/// [log-crate-url]: https://docs.rs/log/ -/// [`init()`]: fn.init.html -/// [`try_init()`]: fn.try_init.html -/// [`Builder::init()`]: struct.Builder.html#method.init -/// [`Builder::try_init()`]: struct.Builder.html#method.try_init -/// [`Builder`]: struct.Builder.html -pub struct Logger { - writer: fmt::Writer, - filter: filter::Filter, - format: Box io::Result<()> + Sync + Send>, -} - -struct Format { - default_format_timestamp: bool, - default_format_module_path: bool, - default_format_level: bool, - default_format_timestamp_nanos: bool, - custom_format: Option io::Result<()> + Sync + Send>>, -} - -impl Default for Format { - fn default() -> Self { - Format { - default_format_timestamp: true, - default_format_module_path: true, - default_format_level: true, - default_format_timestamp_nanos: false, - custom_format: None, - } - } -} - -impl Format { - /// Convert the format into a callable function. - /// - /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. - /// If the `custom_format` is `None`, then a default format is returned. - /// Any `default_format` switches set to `false` won't be written by the format. - fn into_boxed_fn(self) -> Box io::Result<()> + Sync + Send> { - if let Some(fmt) = self.custom_format { - fmt - } - else { - Box::new(move |buf, record| { - let write_level = if self.default_format_level { - let level = record.level(); - let level_style = buf.default_level_style(level); - write!(buf, "{:>5} ", level_style.value(level)) - } else { - Ok(()) - }; - - let write_ts = if self.default_format_timestamp { - if self.default_format_timestamp_nanos { - let ts_nanos = buf.precise_timestamp(); - write!(buf, "{}: ", ts_nanos) - } else { - let ts = buf.timestamp(); - write!(buf, "{}: ", ts) - } - } else { - Ok(()) - }; - - let default_format_module_path = (self.default_format_module_path, record.module_path()); - let write_module_path = if let (true, Some(module_path)) = default_format_module_path { - write!(buf, "{}: ", module_path) - } else { - Ok(()) - }; - - let write_args = writeln!(buf, "{}", record.args()); - - write_level.and(write_ts).and(write_module_path).and(write_args) - }) - } - } -} - -/// `Builder` acts as builder for initializing a `Logger`. -/// -/// It can be used to customize the log format, change the environment variable used -/// to provide the logging directives and also set the default log level filter. -/// -/// # Examples -/// -/// ``` -/// #[macro_use] -/// extern crate log; -/// extern crate env_logger; -/// -/// use std::env; -/// use std::io::Write; -/// use log::LevelFilter; -/// use env_logger::Builder; -/// -/// fn main() { -/// let mut builder = Builder::from_default_env(); -/// -/// builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) -/// .filter(None, LevelFilter::Info) -/// .init(); -/// -/// error!("error message"); -/// info!("info message"); -/// } -/// ``` -#[derive(Default)] -pub struct Builder { - filter: filter::Builder, - writer: fmt::Builder, - format: Format, -} - -impl Builder { - /// Initializes the log builder with defaults. - /// - /// **NOTE:** This method won't read from any environment variables. - /// Use the [`filter`] and [`write_style`] methods to configure the builder - /// or use [`from_env`] or [`from_default_env`] instead. - /// - /// # Examples - /// - /// Create a new builder and configure filters and style: - /// - /// ``` - /// # extern crate log; - /// # extern crate env_logger; - /// # fn main() { - /// use log::LevelFilter; - /// use env_logger::{Builder, WriteStyle}; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter(None, LevelFilter::Info) - /// .write_style(WriteStyle::Always) - /// .init(); - /// # } - /// ``` - /// - /// [`filter`]: #method.filter - /// [`write_style`]: #method.write_style - /// [`from_env`]: #method.from_env - /// [`from_default_env`]: #method.from_default_env - pub fn new() -> Builder { - Default::default() - } - - /// Initializes the log builder from the environment. - /// - /// The variables used to read configuration from can be tweaked before - /// passing in. - /// - /// # Examples - /// - /// Initialise a logger reading the log filter from an environment variable - /// called `MY_LOG`: - /// - /// ``` - /// use env_logger::Builder; - /// - /// let mut builder = Builder::from_env("MY_LOG"); - /// builder.init(); - /// ``` - /// - /// Initialise a logger using the `MY_LOG` variable for filtering and - /// `MY_LOG_STYLE` for whether or not to write styles: - /// - /// ``` - /// use env_logger::{Builder, Env}; - /// - /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); - /// - /// let mut builder = Builder::from_env(env); - /// builder.init(); - /// ``` - pub fn from_env<'a, E>(env: E) -> Self - where - E: Into> - { - let mut builder = Builder::new(); - let env = env.into(); - - if let Some(s) = env.get_filter() { - builder.parse(&s); - } - - if let Some(s) = env.get_write_style() { - builder.parse_write_style(&s); - } - - builder - } - - /// Initializes the log builder from the environment using default variable names. - /// - /// This method is a convenient way to call `from_env(Env::default())` without - /// having to use the `Env` type explicitly. The builder will use the - /// [default environment variables]. - /// - /// # Examples - /// - /// Initialise a logger using the default environment variables: - /// - /// ``` - /// use env_logger::Builder; - /// - /// let mut builder = Builder::from_default_env(); - /// builder.init(); - /// ``` - /// - /// [default environment variables]: struct.Env.html#default-environment-variables - pub fn from_default_env() -> Self { - Self::from_env(Env::default()) - } - - /// Sets the format function for formatting the log output. - /// - /// This function is called on each record logged and should format the - /// log record and output it to the given [`Formatter`]. - /// - /// The format function is expected to output the string directly to the - /// `Formatter` so that implementations can use the [`std::fmt`] macros - /// to format and output without intermediate heap allocations. The default - /// `env_logger` formatter takes advantage of this. - /// - /// # Examples - /// - /// Use a custom format to write only the log message: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.format(|buf, record| write!(buf, "{}", record.args())); - /// ``` - /// - /// [`Formatter`]: fmt/struct.Formatter.html - /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html - /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html - pub fn format(&mut self, format: F) -> &mut Self - where F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send - { - self.format.custom_format = Some(Box::new(format)); - self - } - - /// Use the default format. - /// - /// This method will clear any custom format set on the builder. - pub fn default_format(&mut self) -> &mut Self { - self.format.custom_format = None; - self - } - - /// Whether or not to write the level in the default format. - pub fn default_format_level(&mut self, write: bool) -> &mut Self { - self.format.default_format_level = write; - self - } - - /// Whether or not to write the module path in the default format. - pub fn default_format_module_path(&mut self, write: bool) -> &mut Self { - self.format.default_format_module_path = write; - self - } - - /// Whether or not to write the timestamp in the default format. - pub fn default_format_timestamp(&mut self, write: bool) -> &mut Self { - self.format.default_format_timestamp = write; - self - } - - /// Whether or not to write the timestamp with nanos. - pub fn default_format_timestamp_nanos(&mut self, write: bool) -> &mut Self { - self.format.default_format_timestamp_nanos = write; - self - } - - /// Adds a directive to the filter for a specific module. - /// - /// # Examples - /// - /// Only include messages for warning and above for logs in `path::to::module`: - /// - /// ``` - /// # extern crate log; - /// # extern crate env_logger; - /// # fn main() { - /// use log::LevelFilter; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter_module("path::to::module", LevelFilter::Info); - /// # } - /// ``` - pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { - self.filter.filter_module(module, level); - self - } - - /// Adds a directive to the filter for all modules. - /// - /// # Examples - /// - /// Only include messages for warning and above for logs in `path::to::module`: - /// - /// ``` - /// # extern crate log; - /// # extern crate env_logger; - /// # fn main() { - /// use log::LevelFilter; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter_level(LevelFilter::Info); - /// # } - /// ``` - pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { - self.filter.filter_level(level); - self - } - - /// Adds filters to the logger. - /// - /// The given module (if any) will log at most the specified level provided. - /// If no module is provided then the filter will apply to all log messages. - /// - /// # Examples - /// - /// Only include messages for warning and above for logs in `path::to::module`: - /// - /// ``` - /// # extern crate log; - /// # extern crate env_logger; - /// # fn main() { - /// use log::LevelFilter; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter(Some("path::to::module"), LevelFilter::Info); - /// # } - /// ``` - pub fn filter(&mut self, - module: Option<&str>, - level: LevelFilter) -> &mut Self { - self.filter.filter(module, level); - self - } - - /// Parses the directives string in the same form as the `RUST_LOG` - /// environment variable. - /// - /// See the module documentation for more details. - pub fn parse(&mut self, filters: &str) -> &mut Self { - self.filter.parse(filters); - self - } - - /// Sets the target for the log output. - /// - /// Env logger can log to either stdout or stderr. The default is stderr. - /// - /// # Examples - /// - /// Write log message to `stdout`: - /// - /// ``` - /// use env_logger::{Builder, Target}; - /// - /// let mut builder = Builder::new(); - /// - /// builder.target(Target::Stdout); - /// ``` - pub fn target(&mut self, target: fmt::Target) -> &mut Self { - self.writer.target(target); - self - } - - /// Sets whether or not styles will be written. - /// - /// This can be useful in environments that don't support control characters - /// for setting colors. - /// - /// # Examples - /// - /// Never attempt to write styles: - /// - /// ``` - /// use env_logger::{Builder, WriteStyle}; - /// - /// let mut builder = Builder::new(); - /// - /// builder.write_style(WriteStyle::Never); - /// ``` - pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { - self.writer.write_style(write_style); - self - } - - /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` - /// environment variable. - /// - /// See the module documentation for more details. - pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { - self.writer.parse(write_style); - self - } - - /// Initializes the global logger with the built env logger. - /// - /// This should be called early in the execution of a Rust program. Any log - /// events that occur before initialization will be ignored. - /// - /// # Errors - /// - /// This function will fail if it is called more than once, or if another - /// library has already initialized a global logger. - pub fn try_init(&mut self) -> Result<(), SetLoggerError> { - let logger = self.build(); - - log::set_max_level(logger.filter()); - log::set_boxed_logger(Box::new(logger)) - } - - /// Initializes the global logger with the built env logger. - /// - /// This should be called early in the execution of a Rust program. Any log - /// events that occur before initialization will be ignored. - /// - /// # Panics - /// - /// This function will panic if it is called more than once, or if another - /// library has already initialized a global logger. - pub fn init(&mut self) { - self.try_init().expect("Builder::init should not be called after logger initialized"); - } - - /// Build an env logger. - /// - /// The returned logger implements the `Log` trait and can be installed manually - /// or nested within another logger. - pub fn build(&mut self) -> Logger { - Logger { - writer: self.writer.build(), - filter: self.filter.build(), - format: mem::replace(&mut self.format, Default::default()).into_boxed_fn(), - } - } -} - -impl Logger { - /// Creates the logger from the environment. - /// - /// The variables used to read configuration from can be tweaked before - /// passing in. - /// - /// # Examples - /// - /// Create a logger reading the log filter from an environment variable - /// called `MY_LOG`: - /// - /// ``` - /// use env_logger::Logger; - /// - /// let logger = Logger::from_env("MY_LOG"); - /// ``` - /// - /// Create a logger using the `MY_LOG` variable for filtering and - /// `MY_LOG_STYLE` for whether or not to write styles: - /// - /// ``` - /// use env_logger::{Logger, Env}; - /// - /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); - /// - /// let logger = Logger::from_env(env); - /// ``` - pub fn from_env<'a, E>(env: E) -> Self - where - E: Into> - { - Builder::from_env(env).build() - } - - /// Creates the logger from the environment using default variable names. - /// - /// This method is a convenient way to call `from_env(Env::default())` without - /// having to use the `Env` type explicitly. The logger will use the - /// [default environment variables]. - /// - /// # Examples - /// - /// Creates a logger using the default environment variables: - /// - /// ``` - /// use env_logger::Logger; - /// - /// let logger = Logger::from_default_env(); - /// ``` - /// - /// [default environment variables]: struct.Env.html#default-environment-variables - pub fn from_default_env() -> Self { - Builder::from_default_env().build() - } - - /// Returns the maximum `LevelFilter` that this env logger instance is - /// configured to output. - pub fn filter(&self) -> LevelFilter { - self.filter.filter() - } - - /// Checks if this record matches the configured filter. - pub fn matches(&self, record: &Record) -> bool { - self.filter.matches(record) - } -} - -impl Log for Logger { - fn enabled(&self, metadata: &Metadata) -> bool { - self.filter.enabled(metadata) - } - - fn log(&self, record: &Record) { - if self.matches(record) { - // Log records are written to a thread-local buffer before being printed - // to the terminal. We clear these buffers afterwards, but they aren't shrinked - // so will always at least have capacity for the largest log record formatted - // on that thread. - // - // If multiple `Logger`s are used by the same threads then the thread-local - // formatter might have different color support. If this is the case the - // formatter and its buffer are discarded and recreated. - - thread_local! { - static FORMATTER: RefCell> = RefCell::new(None); - } - - FORMATTER.with(|tl_buf| { - // It's possible for implementations to sometimes - // log-while-logging (e.g. a `std::fmt` implementation logs - // internally) but it's super rare. If this happens make sure we - // at least don't panic and ship some output to the screen. - let mut a; - let mut b = None; - let tl_buf = match tl_buf.try_borrow_mut() { - Ok(f) => { - a = f; - &mut *a - } - Err(_) => &mut b, - }; - - // Check the buffer style. If it's different from the logger's - // style then drop the buffer and recreate it. - match *tl_buf { - Some(ref mut formatter) => { - if formatter.write_style() != self.writer.write_style() { - *formatter = Formatter::new(&self.writer) - } - }, - ref mut tl_buf => *tl_buf = Some(Formatter::new(&self.writer)) - } - - // The format is guaranteed to be `Some` by this point - let mut formatter = tl_buf.as_mut().unwrap(); - - let _ = (self.format)(&mut formatter, record).and_then(|_| formatter.print(&self.writer)); - - // Always clear the buffer afterwards - formatter.clear(); - }); - } - } - - fn flush(&self) {} -} - -impl<'a> Env<'a> { - /// Get a default set of environment variables. - pub fn new() -> Self { - Self::default() - } - - /// Specify an environment variable to read the filter from. - pub fn filter(mut self, filter_env: E) -> Self - where - E: Into> - { - self.filter = Var::new(filter_env); - - self - } - - /// Specify an environment variable to read the filter from. - /// - /// If the variable is not set, the default value will be used. - pub fn filter_or(mut self, filter_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - self.filter = Var::new_with_default(filter_env, default); - - self - } - - fn get_filter(&self) -> Option { - self.filter.get() - } - - /// Specify an environment variable to read the style from. - pub fn write_style(mut self, write_style_env: E) -> Self - where - E: Into> - { - self.write_style = Var::new(write_style_env); - - self - } - - /// Specify an environment variable to read the style from. - /// - /// If the variable is not set, the default value will be used. - pub fn write_style_or(mut self, write_style_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - self.write_style = Var::new_with_default(write_style_env, default); - - self - } - - fn get_write_style(&self) -> Option { - self.write_style.get() - } -} - -impl<'a> Var<'a> { - fn new(name: E) -> Self - where - E: Into>, - { - Var { - name: name.into(), - default: None, - } - } - - fn new_with_default(name: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - Var { - name: name.into(), - default: Some(default.into()), - } - } - - fn get(&self) -> Option { - env::var(&*self.name) - .ok() - .or_else(|| self.default - .to_owned() - .map(|v| v.into_owned())) - } -} - -impl<'a, T> From for Env<'a> -where - T: Into> -{ - fn from(filter_env: T) -> Self { - Env::default().filter(filter_env.into()) - } -} - -impl<'a> Default for Env<'a> { - fn default() -> Self { - Env { - filter: Var::new(DEFAULT_FILTER_ENV), - write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), - } - } -} - -mod std_fmt_impls { - use std::fmt; - use super::*; - - impl fmt::Debug for Logger{ - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Logger") - .field("filter", &self.filter) - .finish() - } - } - - impl fmt::Debug for Builder{ - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - f.debug_struct("Logger") - .field("filter", &self.filter) - .field("writer", &self.writer) - .finish() - } - } -} - -/// Attempts to initialize the global logger with an env logger. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Errors -/// -/// This function will fail if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn try_init() -> Result<(), SetLoggerError> { - try_init_from_env(Env::default()) -} - -/// Initializes the global logger with an env logger. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Panics -/// -/// This function will panic if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn init() { - try_init().expect("env_logger::init should not be called after logger initialized"); -} - -/// Attempts to initialize the global logger with an env logger from the given -/// environment variables. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Examples -/// -/// Initialise a logger using the `MY_LOG` environment variable for filters -/// and `MY_LOG_STYLE` for writing colors: -/// -/// ``` -/// # extern crate env_logger; -/// use env_logger::{Builder, Env}; -/// -/// # fn run() -> Result<(), Box<::std::error::Error>> { -/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); -/// -/// env_logger::try_init_from_env(env)?; -/// -/// Ok(()) -/// # } -/// # fn main() { run().unwrap(); } -/// ``` -/// -/// # Errors -/// -/// This function will fail if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> -where - E: Into> -{ - let mut builder = Builder::from_env(env); - - builder.try_init() -} - -/// Initializes the global logger with an env logger from the given environment -/// variables. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Examples -/// -/// Initialise a logger using the `MY_LOG` environment variable for filters -/// and `MY_LOG_STYLE` for writing colors: -/// -/// ``` -/// use env_logger::{Builder, Env}; -/// -/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); -/// -/// env_logger::init_from_env(env); -/// ``` -/// -/// # Panics -/// -/// This function will panic if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn init_from_env<'a, E>(env: E) -where - E: Into> -{ - try_init_from_env(env).expect("env_logger::init_from_env should not be called after logger initialized"); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn env_get_filter_reads_from_var_if_set() { - env::set_var("env_get_filter_reads_from_var_if_set", "from var"); - - let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default"); - - assert_eq!(Some("from var".to_owned()), env.get_filter()); - } - - #[test] - fn env_get_filter_reads_from_default_if_var_not_set() { - env::remove_var("env_get_filter_reads_from_default_if_var_not_set"); - - let env = Env::new().filter_or("env_get_filter_reads_from_default_if_var_not_set", "from default"); - - assert_eq!(Some("from default".to_owned()), env.get_filter()); - } - - #[test] - fn env_get_write_style_reads_from_var_if_set() { - env::set_var("env_get_write_style_reads_from_var_if_set", "from var"); - - let env = Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default"); - - assert_eq!(Some("from var".to_owned()), env.get_write_style()); - } - - #[test] - fn env_get_write_style_reads_from_default_if_var_not_set() { - env::remove_var("env_get_write_style_reads_from_default_if_var_not_set"); - - let env = Env::new().write_style_or("env_get_write_style_reads_from_default_if_var_not_set", "from default"); - - assert_eq!(Some("from default".to_owned()), env.get_write_style()); - } -} diff --git a/vendor/env_logger-0.5.13/tests/log-in-log.rs b/vendor/env_logger-0.5.13/tests/log-in-log.rs deleted file mode 100644 index 6b2c47e7a6..0000000000 --- a/vendor/env_logger-0.5.13/tests/log-in-log.rs +++ /dev/null @@ -1,38 +0,0 @@ -#[macro_use] extern crate log; -extern crate env_logger; - -use std::process; -use std::fmt; -use std::env; -use std::str; - -struct Foo; - -impl fmt::Display for Foo { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - info!("test"); - f.write_str("bar") - } -} - -fn main() { - env_logger::init(); - if env::var("YOU_ARE_TESTING_NOW").is_ok() { - return info!("{}", Foo); - } - - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("YOU_ARE_TESTING_NOW", "1") - .env("RUST_LOG", "debug") - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - if out.status.success() { - return - } - - println!("test failed: {}", out.status); - println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); - println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); - process::exit(1); -} diff --git a/vendor/env_logger-0.5.13/tests/regexp_filter.rs b/vendor/env_logger-0.5.13/tests/regexp_filter.rs deleted file mode 100644 index d23e9223ea..0000000000 --- a/vendor/env_logger-0.5.13/tests/regexp_filter.rs +++ /dev/null @@ -1,51 +0,0 @@ -#[macro_use] extern crate log; -extern crate env_logger; - -use std::process; -use std::env; -use std::str; - -fn main() { - if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) { - child_main(); - } else { - parent_main() - } -} - -fn child_main() { - env_logger::init(); - info!("XYZ Message"); -} - -fn run_child(rust_log: String) -> bool { - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("LOG_REGEXP_TEST", "1") - .env("RUST_LOG", rust_log) - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - str::from_utf8(out.stderr.as_ref()).unwrap().contains("XYZ Message") -} - -fn assert_message_printed(rust_log: &str) { - if !run_child(rust_log.to_string()) { - panic!("RUST_LOG={} should allow the test log message", rust_log) - } -} - -fn assert_message_not_printed(rust_log: &str) { - if run_child(rust_log.to_string()) { - panic!("RUST_LOG={} should not allow the test log message", rust_log) - } -} - -fn parent_main() { - // test normal log severity levels - assert_message_printed("info"); - assert_message_not_printed("warn"); - - // test of regular expression filters - assert_message_printed("info/XYZ"); - assert_message_not_printed("info/XXX"); -} diff --git a/vendor/env_logger/.cargo-checksum.json b/vendor/env_logger/.cargo-checksum.json index 7e7a63ea33..e5514ae7e2 100644 --- a/vendor/env_logger/.cargo-checksum.json +++ b/vendor/env_logger/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"ad925703fa86b5b5154c23a0580d168a114e0caf940e0c468cede5629d8cd458","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"d6b17263e1ef268abe75e464d9168b6850b7a2533c646a8cd3fc495699081ac9","examples/custom_default_format.rs":"799c439f61cb711078f8aa584db537a5758c25b90d44767849dae2ad3822885c","examples/custom_format.rs":"ac8323e2febf8b8ff7238bd254fbbbfb3183da5af84f7f3a261fd9ad892c9ab6","examples/custom_logger.rs":"99fb3c9761ad4c5fe73f4ec2a2bd44b4acf6d1f7b7cfaa16bf0373665d3e2a4b","examples/default.rs":"a763144dca7d156579781a102551076acc42b5e8398c573f9a3484376bd05b2f","examples/direct_logger.rs":"549f6a10e0903d06aca2cc7ba82415b07a23392676101c9bc7aa72b4a9b0b9e2","src/filter/mod.rs":"fcac209d691b9f0a39e8113626f1e2e4b39b64a2670c603a7a0b339ec8c5201f","src/filter/regex.rs":"5fff47d1d4d0aa3f2bab90636127d3e72aebf800c3b78faba99637220ffdf865","src/filter/string.rs":"52bbd047c31a1afdb3cd1c11629b956f21b3f47bf22e06421baf3d693a045e59","src/fmt/humantime/extern_impl.rs":"cd2538e7a03fd3ad6c843af3c3d4016ca96cadaefee32cf9b37329c4787e6552","src/fmt/humantime/mod.rs":"408496eb21344c654b9e06da2a2df86de56e427147bb7f7b47851e0da976c003","src/fmt/humantime/shim_impl.rs":"7c2fdf4031f5568b716df14842b0d32bc03ff398763f4849960df7f9632a5bb2","src/fmt/mod.rs":"a36bbee3cd310f410b61496f1bef2364af2754c1beba0fdef55b9e25b9e10b9b","src/fmt/writer/atty.rs":"3e9fd61d291d0919f7aa7119a26dd15d920df8783b4ae57bcf2c3cb6f3ff06b5","src/fmt/writer/mod.rs":"a00ccbe121c04f80934cd13cc439ad2e7df91d8bd23c4b2d4148cfc65dee017b","src/fmt/writer/termcolor/extern_impl.rs":"de11703e0ffb954a774dcebe32610239204e9cdf547b2529bc1bb8087d5f5534","src/fmt/writer/termcolor/mod.rs":"a3cf956aec030e0f940e4eaefe58d7703857eb900022286e328e05e5f61de183","src/fmt/writer/termcolor/shim_impl.rs":"6587345b53a6ac2cec485e3b7a7090c0905dbb3a0ae2561c66afafa1072d7695","src/lib.rs":"84ea61e31ea715d527de0140d786d5cf47d2207a5460b7e562db765baa4204a2","tests/init-twice-retains-filter.rs":"ae412fef7eaa6564301e6bfa852697c6587b038280d6df81c674a3a00573c226","tests/log-in-log.rs":"41126910998adfbac771c2a1237fecbc5437344f8e4dfc2f93235bab764a087e","tests/regexp_filter.rs":"44aa6c39de894be090e37083601e501cfffb15e3c0cd36209c48abdf3e2cb120"},"package":"afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"} \ No newline at end of file +{"files":{"CHANGELOG.md":"7c044d74477515ab39287a4caff27eb96daebaed8b9f9b6a1d1c081a7b42d4a7","Cargo.lock":"132c1f881b80a79314567a6993141c6204495fec144cdcec1729f2a3e0fec18b","Cargo.toml":"b60137f1fd54001ca4d8be1d0bbec154225a44c8f4fa3576078bdad55216d357","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"0e231c1c4ad51ff0239062297bdaa69aeb34a8692e3f814188ce1e0ade8583d5","examples/custom_default_format.rs":"799c439f61cb711078f8aa584db537a5758c25b90d44767849dae2ad3822885c","examples/custom_format.rs":"ac8323e2febf8b8ff7238bd254fbbbfb3183da5af84f7f3a261fd9ad892c9ab6","examples/custom_logger.rs":"99fb3c9761ad4c5fe73f4ec2a2bd44b4acf6d1f7b7cfaa16bf0373665d3e2a4b","examples/default.rs":"ac96427611784d310704f738c7a29ebddd7930c8a70ad3c464c4d3eae4cf74a3","examples/direct_logger.rs":"549f6a10e0903d06aca2cc7ba82415b07a23392676101c9bc7aa72b4a9b0b9e2","examples/filters_from_code.rs":"84bd82803683d19ae96f85edcf4ee38cda028c2dbde923dddecc8563453b18e2","src/filter/mod.rs":"de471579c5db400c5ed11b9d7c9fc62686068b42798c58f7165806319ab7ec09","src/filter/regex.rs":"5fff47d1d4d0aa3f2bab90636127d3e72aebf800c3b78faba99637220ffdf865","src/filter/string.rs":"52bbd047c31a1afdb3cd1c11629b956f21b3f47bf22e06421baf3d693a045e59","src/fmt/humantime/extern_impl.rs":"cd2538e7a03fd3ad6c843af3c3d4016ca96cadaefee32cf9b37329c4787e6552","src/fmt/humantime/mod.rs":"408496eb21344c654b9e06da2a2df86de56e427147bb7f7b47851e0da976c003","src/fmt/humantime/shim_impl.rs":"7c2fdf4031f5568b716df14842b0d32bc03ff398763f4849960df7f9632a5bb2","src/fmt/mod.rs":"5104dad2fd14bc18ab6ab46e7c2bc5752b509d9fc934fb99f0ebc126728f8f04","src/fmt/writer/atty.rs":"3e9fd61d291d0919f7aa7119a26dd15d920df8783b4ae57bcf2c3cb6f3ff06b5","src/fmt/writer/mod.rs":"583f6616e0cf21955a530baa332fb7a99bf4fcd418a2367bbd1e733a06a22318","src/fmt/writer/termcolor/extern_impl.rs":"15e048be128568abcdd0ce99dafffe296df26131d4aa05921585761d31c11db5","src/fmt/writer/termcolor/mod.rs":"a3cf956aec030e0f940e4eaefe58d7703857eb900022286e328e05e5f61de183","src/fmt/writer/termcolor/shim_impl.rs":"bdd479c4e933b14ba02a3c1a9fe30eb51bcdf600e23cebd044d68683fdaad037","src/lib.rs":"2c5ab92ee141022f3e657b0f81e84e5ee4e7fad9fb648204e00ed4fb03d4166f","tests/init-twice-retains-filter.rs":"00524ce0f6779981b695bad1fdd244f87b76c126aeccd8b4ff77ef9e6325478b","tests/log-in-log.rs":"41126910998adfbac771c2a1237fecbc5437344f8e4dfc2f93235bab764a087e","tests/regexp_filter.rs":"44aa6c39de894be090e37083601e501cfffb15e3c0cd36209c48abdf3e2cb120"},"package":"aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"} \ No newline at end of file diff --git a/vendor/env_logger/CHANGELOG.md b/vendor/env_logger/CHANGELOG.md new file mode 100644 index 0000000000..f849eefff6 --- /dev/null +++ b/vendor/env_logger/CHANGELOG.md @@ -0,0 +1,3 @@ +Changes to this crate are tracked via [GitHub Releases][releases]. + +[releases]: https://github.com/sebasmagri/env_logger/releases diff --git a/vendor/env_logger/Cargo.lock b/vendor/env_logger/Cargo.lock new file mode 100644 index 0000000000..565fc3a876 --- /dev/null +++ b/vendor/env_logger/Cargo.lock @@ -0,0 +1,212 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "env_logger" +version = "0.6.2" +dependencies = [ + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_syscall" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/vendor/env_logger/Cargo.toml b/vendor/env_logger/Cargo.toml index 2e34be3358..1d028baaaa 100644 --- a/vendor/env_logger/Cargo.toml +++ b/vendor/env_logger/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "env_logger" -version = "0.6.0" +version = "0.6.2" authors = ["The Rust Project Developers"] description = "A logging implementation for `log` which is configured via an environment\nvariable.\n" documentation = "https://docs.rs/env_logger" diff --git a/vendor/env_logger/README.md b/vendor/env_logger/README.md index 496c549152..8dc92f12a8 100644 --- a/vendor/env_logger/README.md +++ b/vendor/env_logger/README.md @@ -16,7 +16,7 @@ It must be added along with `log` to the project dependencies: ```toml [dependencies] log = "0.4.0" -env_logger = "0.6.0" +env_logger = "0.6.2" ``` `env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging. @@ -43,6 +43,8 @@ $ RUST_LOG=info ./main [2018-11-03T06:09:06Z INFO default] starting up ``` +`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/sebasmagri/env_logger/tree/master/examples) for more approaches. + ### In tests Tests can use the `env_logger` crate to see log messages generated during that test: @@ -52,7 +54,7 @@ Tests can use the `env_logger` crate to see log messages generated during that t log = "0.4.0" [dev-dependencies] -env_logger = { version = "0.6.0", default-features = false } +env_logger = "0.6.2" ``` ```rust @@ -69,16 +71,22 @@ mod tests { use super::*; extern crate env_logger; + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } + #[test] fn it_adds_one() { - let _ = env_logger::try_init(); + init(); + info!("can log from the test too"); assert_eq!(3, add_one(2)); } #[test] fn it_handles_negative_numbers() { - let _ = env_logger::try_init(); + init(); + info!("logging from another test"); assert_eq!(-7, add_one(-8)); } @@ -141,4 +149,4 @@ builder.init(); The default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`. -If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format. \ No newline at end of file +If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format. diff --git a/vendor/env_logger/examples/default.rs b/vendor/env_logger/examples/default.rs index 5d799fe054..302e38a208 100644 --- a/vendor/env_logger/examples/default.rs +++ b/vendor/env_logger/examples/default.rs @@ -22,6 +22,9 @@ extern crate env_logger; use env_logger::Env; fn main() { + // The `Env` lets us tweak what the environment + // variables to read are and what the default + // value is if they're missing let env = Env::default() .filter_or("MY_LOG_LEVEL", "trace") .write_style_or("MY_LOG_STYLE", "always"); diff --git a/vendor/env_logger/examples/filters_from_code.rs b/vendor/env_logger/examples/filters_from_code.rs new file mode 100644 index 0000000000..ef5b96910d --- /dev/null +++ b/vendor/env_logger/examples/filters_from_code.rs @@ -0,0 +1,19 @@ +/*! +Specify logging filters in code instead of using an environment variable. +*/ + +#[macro_use] +extern crate log; +extern crate env_logger; + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Trace) + .init(); + + trace!("some trace log"); + debug!("some debug log"); + info!("some information log"); + warn!("some warning log"); + error!("some error log"); +} diff --git a/vendor/env_logger/src/filter/mod.rs b/vendor/env_logger/src/filter/mod.rs index 65f413dd6a..a0fe6a2506 100644 --- a/vendor/env_logger/src/filter/mod.rs +++ b/vendor/env_logger/src/filter/mod.rs @@ -306,8 +306,8 @@ fn parse_spec(spec: &str) -> (Vec, Option) { let mods = parts.next(); let filter = parts.next(); if parts.next().is_some() { - println!("warning: invalid logging spec '{}', \ - ignoring it (too many '/'s)", spec); + eprintln!("warning: invalid logging spec '{}', \ + ignoring it (too many '/'s)", spec); return (dirs, None); } mods.map(|m| { for s in m.split(',') { @@ -327,15 +327,15 @@ fn parse_spec(spec: &str) -> (Vec, Option) { match part1.parse() { Ok(num) => (num, Some(part0)), _ => { - println!("warning: invalid logging spec '{}', \ - ignoring it", part1); + eprintln!("warning: invalid logging spec '{}', \ + ignoring it", part1); continue } } }, _ => { - println!("warning: invalid logging spec '{}', \ - ignoring it", s); + eprintln!("warning: invalid logging spec '{}', \ + ignoring it", s); continue } }; @@ -349,7 +349,7 @@ fn parse_spec(spec: &str) -> (Vec, Option) { match inner::Filter::new(filter) { Ok(re) => Some(re), Err(e) => { - println!("warning: invalid regex filter - {}", e); + eprintln!("warning: invalid regex filter - {}", e); None } } diff --git a/vendor/env_logger/src/fmt/mod.rs b/vendor/env_logger/src/fmt/mod.rs index 635995e22d..3f3d497594 100644 --- a/vendor/env_logger/src/fmt/mod.rs +++ b/vendor/env_logger/src/fmt/mod.rs @@ -117,6 +117,7 @@ pub(crate) struct Builder { pub default_format_timestamp_nanos: bool, pub default_format_module_path: bool, pub default_format_level: bool, + #[allow(unknown_lints, bare_trait_objects)] pub custom_format: Option io::Result<()> + Sync + Send>>, built: bool, } @@ -140,6 +141,7 @@ impl Builder { /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. /// If the `custom_format` is `None`, then a default format is returned. /// Any `default_format` switches set to `false` won't be written by the format. + #[allow(unknown_lints, bare_trait_objects)] pub fn build(&mut self) -> Box io::Result<()> + Sync + Send> { assert!(!self.built, "attempt to re-use consumed builder"); @@ -353,4 +355,4 @@ mod tests { assert_eq!("log message\n", written); } -} \ No newline at end of file +} diff --git a/vendor/env_logger/src/fmt/writer/mod.rs b/vendor/env_logger/src/fmt/writer/mod.rs index d628187ec2..d84e414677 100644 --- a/vendor/env_logger/src/fmt/writer/mod.rs +++ b/vendor/env_logger/src/fmt/writer/mod.rs @@ -70,21 +70,23 @@ impl Writer { pub(crate) struct Builder { target: Target, write_style: WriteStyle, + is_test: bool, built: bool, } impl Builder { /// Initialize the writer builder with defaults. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Builder { target: Default::default(), write_style: Default::default(), + is_test: false, built: false, } } /// Set the target to write to. - pub fn target(&mut self, target: Target) -> &mut Self { + pub(crate) fn target(&mut self, target: Target) -> &mut Self { self.target = target; self } @@ -94,18 +96,24 @@ impl Builder { /// See the [Disabling colors] section for more details. /// /// [Disabling colors]: ../index.html#disabling-colors - pub fn parse(&mut self, write_style: &str) -> &mut Self { + pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self { self.write_style(parse_write_style(write_style)) } /// Whether or not to print style characters when writing. - pub fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { + pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { self.write_style = write_style; self } + /// Whether or not to capture logs for `cargo test`. + pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self { + self.is_test = is_test; + self + } + /// Build a terminal writer. - pub fn build(&mut self) -> Writer { + pub(crate) fn build(&mut self) -> Writer { assert!(!self.built, "attempt to re-use consumed builder"); self.built = true; @@ -124,8 +132,8 @@ impl Builder { }; let writer = match self.target { - Target::Stderr => BufferWriter::stderr(color_choice), - Target::Stdout => BufferWriter::stdout(color_choice), + Target::Stderr => BufferWriter::stderr(self.is_test, color_choice), + Target::Stdout => BufferWriter::stdout(self.is_test, color_choice), }; Writer { diff --git a/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs index 236e163b66..0c2d138792 100644 --- a/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs +++ b/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs @@ -8,7 +8,7 @@ use log::Level; use termcolor::{self, ColorChoice, ColorSpec, WriteColor}; use ::WriteStyle; -use ::fmt::Formatter; +use ::fmt::{Formatter, Target}; pub(in ::fmt::writer) mod glob { pub use super::*; @@ -69,51 +69,98 @@ impl Formatter { } } -pub(in ::fmt::writer) struct BufferWriter(termcolor::BufferWriter); -pub(in ::fmt) struct Buffer(termcolor::Buffer); +pub(in ::fmt::writer) struct BufferWriter { + inner: termcolor::BufferWriter, + test_target: Option, +} + +pub(in ::fmt) struct Buffer { + inner: termcolor::Buffer, + test_target: Option, +} impl BufferWriter { - pub(in ::fmt::writer) fn stderr(write_style: WriteStyle) -> Self { - BufferWriter(termcolor::BufferWriter::stderr(write_style.into_color_choice())) + pub(in ::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self { + BufferWriter { + inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()), + test_target: if is_test { + Some(Target::Stderr) + } else { + None + }, + } } - pub(in ::fmt::writer) fn stdout(write_style: WriteStyle) -> Self { - BufferWriter(termcolor::BufferWriter::stdout(write_style.into_color_choice())) + pub(in ::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self { + BufferWriter { + inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()), + test_target: if is_test { + Some(Target::Stdout) + } else { + None + }, + } } pub(in ::fmt::writer) fn buffer(&self) -> Buffer { - Buffer(self.0.buffer()) + Buffer { + inner: self.inner.buffer(), + test_target: self.test_target, + } } pub(in ::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> { - self.0.print(&buf.0) + if let Some(target) = self.test_target { + // This impl uses the `eprint` and `print` macros + // instead of `termcolor`'s buffer. + // This is so their output can be captured by `cargo test` + let log = String::from_utf8_lossy(buf.bytes()); + + match target { + Target::Stderr => eprint!("{}", log), + Target::Stdout => print!("{}", log), + } + + Ok(()) + } else { + self.inner.print(&buf.inner) + } } } impl Buffer { pub(in ::fmt) fn clear(&mut self) { - self.0.clear() + self.inner.clear() } pub(in ::fmt) fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) + self.inner.write(buf) } pub(in ::fmt) fn flush(&mut self) -> io::Result<()> { - self.0.flush() + self.inner.flush() } - #[cfg(test)] pub(in ::fmt) fn bytes(&self) -> &[u8] { - self.0.as_slice() + self.inner.as_slice() } fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - self.0.set_color(spec) + // Ignore styles for test captured logs because they can't be printed + if self.test_target.is_none() { + self.inner.set_color(spec) + } else { + Ok(()) + } } fn reset(&mut self) -> io::Result<()> { - self.0.reset() + // Ignore styles for test captured logs because they can't be printed + if self.test_target.is_none() { + self.inner.reset() + } else { + Ok(()) + } } } diff --git a/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs index b785dec048..fb4735902d 100644 --- a/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs +++ b/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs @@ -13,13 +13,13 @@ pub(in ::fmt::writer) struct BufferWriter { pub(in ::fmt) struct Buffer(Vec); impl BufferWriter { - pub(in ::fmt::writer) fn stderr(_: WriteStyle) -> Self { + pub(in ::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self { BufferWriter { target: Target::Stderr, } } - pub(in ::fmt::writer) fn stdout(_: WriteStyle) -> Self { + pub(in ::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self { BufferWriter { target: Target::Stdout, } diff --git a/vendor/env_logger/src/lib.rs b/vendor/env_logger/src/lib.rs index 355b687f2f..37c4322914 100644 --- a/vendor/env_logger/src/lib.rs +++ b/vendor/env_logger/src/lib.rs @@ -139,6 +139,35 @@ //! * `error,hello=warn/[0-9]scopes` turn on global error logging and also //! warn for hello. In both cases the log message must include a single digit //! number followed by 'scopes'. +//! +//! ## Capturing logs in tests +//! +//! Records logged during `cargo test` will not be captured by the test harness by default. +//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured: +//! +//! ``` +//! # #[macro_use] extern crate log; +//! # extern crate env_logger; +//! # fn main() {} +//! #[cfg(test)] +//! mod tests { +//! fn init() { +//! let _ = env_logger::builder().is_test(true).try_init(); +//! } +//! +//! #[test] +//! fn it_works() { +//! init(); +//! +//! info!("This record will be captured by `cargo test`"); +//! +//! assert_eq!(2, 1 + 1); +//! } +//! } +//! ``` +//! +//! Enabling test capturing comes at the expense of color and other style support +//! and may have performance implications. //! //! ## Disabling colors //! @@ -157,9 +186,7 @@ //! The following example excludes the timestamp from the log output: //! //! ``` -//! use env_logger::Builder; -//! -//! Builder::from_default_env() +//! env_logger::builder() //! .default_format_timestamp(false) //! .init(); //! ``` @@ -180,9 +207,8 @@ //! //! ``` //! use std::io::Write; -//! use env_logger::Builder; //! -//! Builder::from_default_env() +//! env_logger::builder() //! .format(|buf, record| { //! writeln!(buf, "{}: {}", record.level(), record.args()) //! }) @@ -199,19 +225,20 @@ //! isn't set: //! //! ``` -//! use env_logger::{Builder, Env}; +//! use env_logger::Env; //! -//! Builder::from_env(Env::default().default_filter_or("warn")).init(); +//! env_logger::from_env(Env::default().default_filter_or("warn")).init(); //! ``` //! //! [log-crate-url]: https://docs.rs/log/ //! [`Builder`]: struct.Builder.html +//! [`Builder::is_test`]: struct.Builder.html#method.is_test //! [`Env`]: struct.Env.html //! [`fmt`]: fmt/index.html -#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/env_logger/0.6.0")] +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico", + html_root_url = "https://docs.rs/env_logger/0.6.2")] #![cfg_attr(test, deny(warnings))] // When compiled for the rustc compiler itself we want to make sure that this is @@ -295,6 +322,7 @@ struct Var<'a> { pub struct Logger { writer: Writer, filter: Filter, + #[allow(unknown_lints, bare_trait_objects)] format: Box io::Result<()> + Sync + Send>, } @@ -404,7 +432,7 @@ impl Builder { let env = env.into(); if let Some(s) = env.get_filter() { - builder.parse(&s); + builder.parse_filters(&s); } if let Some(s) = env.get_write_style() { @@ -579,7 +607,16 @@ impl Builder { /// environment variable. /// /// See the module documentation for more details. + #[deprecated(since = "0.6.1", note = "use `parse_filters` instead.")] pub fn parse(&mut self, filters: &str) -> &mut Self { + self.parse_filters(filters) + } + + /// Parses the directives string in the same form as the `RUST_LOG` + /// environment variable. + /// + /// See the module documentation for more details. + pub fn parse_filters(&mut self, filters: &str) -> &mut Self { self.filter.parse(filters); self } @@ -630,7 +667,16 @@ impl Builder { /// /// See the module documentation for more details. pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { - self.writer.parse(write_style); + self.writer.parse_write_style(write_style); + self + } + + /// Sets whether or not the logger will be used in unit tests. + /// + /// If `is_test` is `true` then the logger will allow the testing framework to + /// capture log records rather than printing them to the terminal directly. + pub fn is_test(&mut self, is_test: bool) -> &mut Self { + self.writer.is_test(is_test); self } @@ -1068,6 +1114,23 @@ where try_init_from_env(env).expect("env_logger::init_from_env should not be called after logger initialized"); } +/// Create a new builder with the default environment variables. +/// +/// The builder can be configured before being initialized. +pub fn builder() -> Builder { + Builder::from_default_env() +} + +/// Create a builder from the given environment variables. +/// +/// The builder can be configured before being initialized. +pub fn from_env<'a, E>(env: E) -> Builder +where + E: Into> +{ + Builder::from_env(env) +} + #[cfg(test)] mod tests { use super::*; diff --git a/vendor/env_logger/tests/init-twice-retains-filter.rs b/vendor/env_logger/tests/init-twice-retains-filter.rs index 6ab08e99f9..c1256ef6d1 100644 --- a/vendor/env_logger/tests/init-twice-retains-filter.rs +++ b/vendor/env_logger/tests/init-twice-retains-filter.rs @@ -15,7 +15,7 @@ fn main() { // Init again using a different max level // This shouldn't clobber the level that was previously set env_logger::Builder::new() - .parse("info") + .parse_filters("info") .try_init() .unwrap_err(); diff --git a/vendor/getopts/.cargo-checksum.json b/vendor/getopts/.cargo-checksum.json index 80ba8c8cb7..26d98808bc 100644 --- a/vendor/getopts/.cargo-checksum.json +++ b/vendor/getopts/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"186195a052d7f209dc438ff394eee222afb4a011eb66a35431c90aa828fb546a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"8c884e55b3999f01f31a8b494e523e2144a72c8ee7847d690d8e154f677c6cff","appveyor.yml":"da991211b72fa6f231af7adb84c9fb72f5a9131d1c0a3d47b8ceffe5a82c8542","src/lib.rs":"54ea0d2f7530486c4ccf1ed310c27c8875f87370e7ad9bb2fba6b67b43d506b5","src/tests/mod.rs":"180832c410b6813be0def273491e480ad7ddae8fe0759d7e42f3a002f363c2e5","tests/smoke.rs":"26a95ac42e42b766ae752fe8531fb740fd147d5cdff352dec0763d175ce91806"},"package":"72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450"} \ No newline at end of file +{"files":{"Cargo.toml":"eb778be71513b195b13c40e7f04ebce631ec4af5858a49693a71270000288791","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"5632a44cbb0f3727207a5ba5df3e8ce5229fab6882402285e7c1f50585d2cc69","src/lib.rs":"2c482a91d2adba4cc3abf84b6be812d5ed35f86f8fe6247201bb1511724eb850","src/tests/mod.rs":"e7a92033e4bb5b31a60b3db01c0c6d8d5498fdeb2d612990d2c44eae87552257","tests/smoke.rs":"26a95ac42e42b766ae752fe8531fb740fd147d5cdff352dec0763d175ce91806"},"package":"14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"} \ No newline at end of file diff --git a/vendor/getopts/Cargo.toml b/vendor/getopts/Cargo.toml index a98152a872..db224fcf5a 100644 --- a/vendor/getopts/Cargo.toml +++ b/vendor/getopts/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "getopts" -version = "0.2.19" +version = "0.2.21" authors = ["The Rust Project Developers"] description = "getopts-like option parsing.\n" homepage = "https://github.com/rust-lang/getopts" @@ -21,7 +21,20 @@ readme = "README.md" categories = ["command-line-interface"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/getopts" +[dependencies.core] +version = "1.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.std] +version = "1.0" +optional = true +package = "rustc-std-workspace-std" + [dependencies.unicode-width] version = "0.1.5" [dev-dependencies.log] version = "0.4" + +[features] +rustc-dep-of-std = ["unicode-width/rustc-dep-of-std", "std", "core"] diff --git a/vendor/getopts/README.md b/vendor/getopts/README.md index f80db224ea..065a05638d 100644 --- a/vendor/getopts/README.md +++ b/vendor/getopts/README.md @@ -3,9 +3,7 @@ getopts A Rust library for option parsing for CLI utilities. -[![Build Status](https://travis-ci.org/rust-lang-nursery/getopts.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/getopts) - -[Documentation](https://doc.rust-lang.org/getopts) +[Documentation](https://docs.rs/getopts) ## Usage @@ -15,13 +13,3 @@ Add this to your `Cargo.toml`: [dependencies] getopts = "0.2" ``` - -and this to your crate root: - -```rust -extern crate getopts; -``` - -## Rust Version Support - -The minimum supported Rust version is 1.18. diff --git a/vendor/getopts/appveyor.yml b/vendor/getopts/appveyor.yml deleted file mode 100644 index 6a1b8dc19c..0000000000 --- a/vendor/getopts/appveyor.yml +++ /dev/null @@ -1,17 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - - TARGET: i686-pc-windows-msvc - - TARGET: i686-pc-windows-gnu -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - SET PATH=%PATH%;C:\MinGW\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --verbose diff --git a/vendor/getopts/src/lib.rs b/vendor/getopts/src/lib.rs index 9a9d5d20f8..fd45b9508a 100644 --- a/vendor/getopts/src/lib.rs +++ b/vendor/getopts/src/lib.rs @@ -95,19 +95,10 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/getopts/0.2.19" + html_root_url = "https://docs.rs/getopts/0.2.20" )] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] -#![cfg_attr(rust_build, feature(staged_api))] -#![cfg_attr(rust_build, staged_api)] -#![cfg_attr( - rust_build, - unstable( - feature = "rustc_private", - reason = "use the crates.io `getopts` library instead" - ) -)] #[cfg(test)] #[macro_use] @@ -363,7 +354,8 @@ impl Options { .to_str() .ok_or_else(|| Fail::UnrecognizedOption(format!("{:?}", i.as_ref()))) .map(|s| s.to_owned()) - }).collect::<::std::result::Result, _>>()?; + }) + .collect::<::std::result::Result, _>>()?; let mut args = args.into_iter().peekable(); let mut arg_pos = 0; while let Some(cur) = args.next() { @@ -514,7 +506,7 @@ impl Options { /// Derive a custom formatted message from a set of options. The formatted options provided to /// a closure as an iterator. - pub fn usage_with_format) -> String>( + pub fn usage_with_format) -> String>( &self, mut formatter: F, ) -> String { @@ -522,7 +514,7 @@ impl Options { } /// Derive usage items from a set of options. - fn usage_items<'a>(&'a self) -> Box + 'a> { + fn usage_items<'a>(&'a self) -> Box + 'a> { let desc_sep = format!("\n{}", repeat(" ").take(24).collect::()); let any_short = self.grps.iter().any(|optref| !optref.short_name.is_empty()); @@ -848,7 +840,8 @@ impl Matches { .filter_map(|nm| match self.opt_val(&nm) { Some(Val(s)) => Some(s), _ => None, - }).next() + }) + .next() } /// Returns a vector of the arguments provided to all matches of the given @@ -861,7 +854,8 @@ impl Matches { .filter_map(|(_, v)| match v { Val(s) => Some(s), _ => None, - }).collect() + }) + .collect() } /// Returns a vector of the arguments provided to all matches of the given @@ -874,7 +868,8 @@ impl Matches { .filter_map(|(p, v)| match v { Val(s) => Some((p, s)), _ => None, - }).collect() + }) + .collect() } /// Returns the string argument supplied to a matching option or `None`. @@ -1022,7 +1017,8 @@ fn each_split_within(desc: &str, lim: usize) -> Vec { else { (words, a, idx) } - }).0; + }) + .0; let mut row = String::new(); for word in words.iter() { diff --git a/vendor/getopts/src/tests/mod.rs b/vendor/getopts/src/tests/mod.rs index c61beaa551..f1fb390987 100644 --- a/vendor/getopts/src/tests/mod.rs +++ b/vendor/getopts/src/tests/mod.rs @@ -1232,9 +1232,23 @@ fn test_opt_strs_pos() { }; let a_pos = matches.opt_strs_pos("a"); - assert_eq!(a_pos, vec![(0, "1".to_string()), (1, "2".to_string()), (3, "4".to_string())]); + assert_eq!( + a_pos, + vec![ + (0, "1".to_string()), + (1, "2".to_string()), + (3, "4".to_string()) + ] + ); let e_pos = matches.opt_strs_pos("e"); assert_eq!(e_pos, vec![]); let r_pos = matches.opt_strs_pos("r"); - assert_eq!(r_pos, vec![(2, "3".to_string()), (4, "5".to_string()), (5, "6".to_string())]); + assert_eq!( + r_pos, + vec![ + (2, "3".to_string()), + (4, "5".to_string()), + (5, "6".to_string()) + ] + ); } diff --git a/vendor/getrandom/.cargo-checksum.json b/vendor/getrandom/.cargo-checksum.json index 799ea0420e..bdece4d2af 100644 --- a/vendor/getrandom/.cargo-checksum.json +++ b/vendor/getrandom/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"09edc8fa76ba8459363c78d2b3a4db2e587b8505116da5d8b131432c505617e9","Cargo.toml":"b63994b40101d79e0643901bc730611d5087ea1ffee0686d4dc17f9c900bca81","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"ce0f100908e39194b6a5e596503e3ed6427820c27cea3fce2ebfee74e507469e","benches/mod.rs":"eae05a2128105062d27090af25e5c35ac2cf422115e335582f13c5127c3507b4","src/cloudabi.rs":"cd493b696ab968113d46b3b38cff52ecd89e79228640802ba523452932183d2b","src/dummy.rs":"184e81035f38a5edd3e7f3ed9ea0d3e4dc462ca5d224fad11cb660412dcd9198","src/error.rs":"09c44963f28db88ea961f85ece69bf8f177510836e2c84ff0ee9e9c6d62fe516","src/error_impls.rs":"e8a33ce04a71c588d88776dcd895446da9526f3843ae72ed438c65ac386e87da","src/freebsd.rs":"c41e51c4549a075d6d5a87a1518f1ad742497570576d0e730814dba6b830c4c7","src/fuchsia.rs":"470d8509deb5b06fa6417f294c0a49e0e35a580249a5d8944c3be5aa746f64ea","src/ios.rs":"e88214b6077eb75e471b388d57f952a9af8f6f0e514df5c6e655d6c22384313d","src/lib.rs":"c85d12a55fc33209534797947104459a3b59c25c1ad5ada38f2a147d51d56021","src/linux_android.rs":"b7975157fa1b28f4eb3dabf3ca28e055f974fcc391163cf4c9e5c8123fabc1e1","src/macos.rs":"757ddafd8645ad382fb041f2db3735f4da4ea174f87892411de63a208b3db619","src/openbsd.rs":"c77acddffa3287dc7f82d13a4650a8ac8ef991ee882f71650ebbc76f9df431f6","src/rdrand.rs":"fb162ff041eede073e9558875c4053bf4406480e0baf64178229d13c00c99c3c","src/solaris_illumos.rs":"f0c34c6eab80b35309c3b47cf89ff1749400ea11dcb1de21c83f03c52fe983b2","src/use_file.rs":"355e508223a4bd53ba2eaf574f32ca87e8e25e2bbf455d2d46639be7c5fe38a6","src/util.rs":"f7d62cf0b8818eb70f3a4d8d01acb7d016653181f3c5ac5fdd7dece8df50d3db","src/util_libc.rs":"9a51eda80778d4c2e8b38b72a460d8832a4fe51621f0feb6c9ef9c757889dc87","src/wasi.rs":"9c6ba8305fdee701d65889ed49543f7443660180504ad7b180aca9d666f212c5","src/wasm32_bindgen.rs":"a1d38368593e67bb6941386a17c1f6e495f5f4a24738eed97f0acb993634c253","src/wasm32_stdweb.rs":"754a098319513447cb4594bdfbc1234aeeeaea72d3c4e86a0976b3ba16a7bb08","src/windows.rs":"f568b343e6bfbdc158ebc4728baa1c1c08d55417657b940540d9df279f9536d9","tests/mod.rs":"919327a90d370a9dca30f5dcb97a3c8dcf78558ee0b0cf9e59da0bc23c95ed2a"},"package":"34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49"} \ No newline at end of file +{"files":{"CHANGELOG.md":"98896a2bc5487f23fd5aee0da960aab5b7615f6a867516ff4a1fe16a43781924","Cargo.toml":"a6ba2222a4179323d821b1663b164be709ee0221ce9c65c4695abdd66bcec6f8","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"434a2c0978ade0a0c1d24b72a23952243358982b34ebb3a52f9ae41dac18a6ae","benches/mod.rs":"eae05a2128105062d27090af25e5c35ac2cf422115e335582f13c5127c3507b4","build.rs":"9000429ff834eb551f6e3800414cd8d339a6e45ea96c751aa465e204c673357d","src/cloudabi.rs":"cd493b696ab968113d46b3b38cff52ecd89e79228640802ba523452932183d2b","src/dummy.rs":"184e81035f38a5edd3e7f3ed9ea0d3e4dc462ca5d224fad11cb660412dcd9198","src/error.rs":"bc1f2dd348d3edd0c0fecbf5d49f54529f5d077cf529548f530315ae01e1e658","src/error_impls.rs":"e8a33ce04a71c588d88776dcd895446da9526f3843ae72ed438c65ac386e87da","src/freebsd.rs":"c41e51c4549a075d6d5a87a1518f1ad742497570576d0e730814dba6b830c4c7","src/fuchsia.rs":"470d8509deb5b06fa6417f294c0a49e0e35a580249a5d8944c3be5aa746f64ea","src/ios.rs":"e88214b6077eb75e471b388d57f952a9af8f6f0e514df5c6e655d6c22384313d","src/lib.rs":"fa9e2f97fb541994ea0c204d8cbbb821512fba82e7edd75984fe120402eff7a7","src/linux_android.rs":"b7975157fa1b28f4eb3dabf3ca28e055f974fcc391163cf4c9e5c8123fabc1e1","src/macos.rs":"757ddafd8645ad382fb041f2db3735f4da4ea174f87892411de63a208b3db619","src/openbsd.rs":"c77acddffa3287dc7f82d13a4650a8ac8ef991ee882f71650ebbc76f9df431f6","src/rdrand.rs":"fb162ff041eede073e9558875c4053bf4406480e0baf64178229d13c00c99c3c","src/solaris_illumos.rs":"f0c34c6eab80b35309c3b47cf89ff1749400ea11dcb1de21c83f03c52fe983b2","src/use_file.rs":"f265fc53be3186d028291a1305d079bbd3bf1dd3f7670d190cfbdc5f2140403e","src/util.rs":"f7d62cf0b8818eb70f3a4d8d01acb7d016653181f3c5ac5fdd7dece8df50d3db","src/util_libc.rs":"134a183f48fc07a0d0f08594a4b9b988b59a2f867e55df40123b7a92321af489","src/wasi.rs":"e820d8f9242d827bc178d0d8e71f783dd3974c30a2e3783420d02a125a11cbaf","src/wasm32_bindgen.rs":"ca908b95c67656d3397275f187eea82de0a06787e2f0ba9c881aa27ef7654678","src/wasm32_stdweb.rs":"274e1a6b12b4812008e1bac36b2468e8b6e02a9d7e95954b860a1a3c64f6f7a8","src/windows.rs":"f568b343e6bfbdc158ebc4728baa1c1c08d55417657b940540d9df279f9536d9","src/windows_uwp.rs":"e400b03f1b5ff9df493f1ad96993185072945b3ad528a4de24700f44c4836cc3","tests/mod.rs":"919327a90d370a9dca30f5dcb97a3c8dcf78558ee0b0cf9e59da0bc23c95ed2a"},"package":"473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"} \ No newline at end of file diff --git a/vendor/getrandom/CHANGELOG.md b/vendor/getrandom/CHANGELOG.md index 8e40bce602..6f43b26f36 100644 --- a/vendor/getrandom/CHANGELOG.md +++ b/vendor/getrandom/CHANGELOG.md @@ -4,6 +4,47 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.12] - 2019-08-18 +### Changed +- Update wasi dependency from v0.5 to v0.7. [#100] + +[#100]: https://github.com/rust-random/getrandom/pull/100 + +## [0.1.11] - 2019-08-25 +### Fixed +- Implement `std`-dependent traits for selected targets even if `std` +feature is disabled. (backward compatibility with v0.1.8) [#96] + +[#96]: https://github.com/rust-random/getrandom/pull/96 + +## [0.1.10] - 2019-08-18 [YANKED] +### Changed +- Use the dummy implementation on `wasm32-unknown-unknown` even with the +disabled `dummy` feature. [#90] + +### Fixed +- Fix CSP error for `wasm-bindgen`. [#92] + +[#90]: https://github.com/rust-random/getrandom/pull/90 +[#92]: https://github.com/rust-random/getrandom/pull/92 + +## [0.1.9] - 2019-08-14 [YANKED] +### Changed +- Remove `std` dependency for opening and reading files. [#58] +- Use `wasi` isntead of `libc` on WASI target. [#64] +- By default emit a compile-time error when built for an unsupported target. +This behaviour can be disabled by using the `dummy` feature. [#71] + +### Added +- Add support for UWP targets. [#69] +- Add unstable `rustc-dep-of-std` feature. [#78] + +[#58]: https://github.com/rust-random/getrandom/pull/58 +[#64]: https://github.com/rust-random/getrandom/pull/64 +[#69]: https://github.com/rust-random/getrandom/pull/69 +[#71]: https://github.com/rust-random/getrandom/pull/71 +[#78]: https://github.com/rust-random/getrandom/pull/78 + ## [0.1.8] - 2019-07-29 ### Changed - Explicitly specify types to arguments of 'libc::syscall'. [#74] diff --git a/vendor/getrandom/Cargo.toml b/vendor/getrandom/Cargo.toml index 8f1c0b0e5c..64d0ec5cfc 100644 --- a/vendor/getrandom/Cargo.toml +++ b/vendor/getrandom/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "getrandom" -version = "0.1.8" +version = "0.1.12" authors = ["The Rand Project Developers"] exclude = ["utils/*", ".*", "appveyor.yml"] description = "A small cross-platform library for retrieving random data from system source" @@ -24,14 +24,28 @@ repository = "https://github.com/rust-random/getrandom" [dependencies.cfg-if] version = "0.1" +[dependencies.compiler_builtins] +version = "0.1" +optional = true + +[dependencies.core] +version = "1.0" +optional = true +package = "rustc-std-workspace-core" + [dependencies.log] version = "0.4" optional = true [features] +dummy = [] +rustc-dep-of-std = ["compiler_builtins", "core"] std = [] -[target."cfg(any(unix, target_os = \"redox\", target_os = \"wasi\"))".dependencies.libc] -version = "0.2.60" +[target."cfg(any(unix, target_os = \"redox\"))".dependencies.libc] +version = "0.2.62" +default-features = false +[target."cfg(target_os = \"wasi\")".dependencies.wasi] +version = "0.7" [target.wasm32-unknown-unknown.dependencies.stdweb] version = "0.4.18" optional = true diff --git a/vendor/getrandom/README.md b/vendor/getrandom/README.md index 92d203410e..01bbfb5ef9 100644 --- a/vendor/getrandom/README.md +++ b/vendor/getrandom/README.md @@ -18,7 +18,6 @@ library like [`rand`]. [`rand`]: https://crates.io/crates/rand - ## Usage Add this to your `Cargo.toml`: @@ -40,22 +39,35 @@ fn get_random_buf() -> Result<[u8; 32], getrandom::Error> { ## Features -This library is `no_std` compatible, but uses `std` on most platforms. +This library is `no_std` for every supported target. However, getting randomness +usually requires calling some external system API. This means most platforms +will require linking against system libraries (i.e. `libc` for Unix, +`Advapi32.dll` for Windows, Security framework on iOS, etc...). The `log` library is supported as an optional dependency. If enabled, error reporting will be improved on some platforms. -For WebAssembly (`wasm32`), WASI and Emscripten targets are supported directly; otherwise -one of the following features must be enabled: +For the `wasm32-unknown-unknown` target, one of the following features should be +enabled: - [`wasm-bindgen`](https://crates.io/crates/wasm_bindgen) - [`stdweb`](https://crates.io/crates/stdweb) +By default, compiling `getrandom` for an unsupported target will result in +a compilation error. If you want to build an application which uses `getrandom` +for such target, you can either: +- Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml` +to switch to a custom implementation with a support of your target. +- Enable the `dummy` feature to have getrandom use an implementation that always +fails at run-time on unsupported targets. + +[replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section +[patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section + ## Minimum Supported Rust Version This crate requires Rust 1.32.0 or later. - # License The `getrandom` library is distributed under either of @@ -64,4 +76,3 @@ The `getrandom` library is distributed under either of * [MIT license](LICENSE-MIT) at your option. - diff --git a/vendor/getrandom/build.rs b/vendor/getrandom/build.rs new file mode 100644 index 0000000000..1beb4ed86b --- /dev/null +++ b/vendor/getrandom/build.rs @@ -0,0 +1,19 @@ +#![deny(warnings)] + +use std::env; + +fn main() { + let target = env::var("TARGET").expect("TARGET was not set"); + if target.contains("-uwp-windows-") { + // for BCryptGenRandom + println!("cargo:rustc-link-lib=bcrypt"); + // to work around unavailability of `target_vendor` on Rust 1.33 + println!("cargo:rustc-cfg=getrandom_uwp"); + } else if target.contains("windows") { + // for RtlGenRandom (aka SystemFunction036) + println!("cargo:rustc-link-lib=advapi32"); + } else if target.contains("apple-ios") { + // for SecRandomCopyBytes and kSecRandomDefault + println!("cargo:rustc-link-lib=framework=Security"); + } +} diff --git a/vendor/getrandom/src/error.rs b/vendor/getrandom/src/error.rs index a61f2e4dd1..a27a750eab 100644 --- a/vendor/getrandom/src/error.rs +++ b/vendor/getrandom/src/error.rs @@ -21,8 +21,10 @@ pub struct Error(NonZeroU32); impl Error { #[deprecated(since = "0.1.7")] + /// Unknown error. pub const UNKNOWN: Error = UNSUPPORTED; #[deprecated(since = "0.1.7")] + /// System entropy source is unavailable. pub const UNAVAILABLE: Error = UNSUPPORTED; /// Codes below this point represent OS Errors (i.e. positive i32 values). @@ -40,7 +42,7 @@ impl Error { /// that it works in `no_std` contexts. If this method returns `None`, the /// error value can still be formatted via the `Diplay` implementation. #[inline] - pub fn raw_os_error(&self) -> Option { + pub fn raw_os_error(self) -> Option { if self.0.get() < Self::INTERNAL_START { Some(self.0.get() as i32) } else { @@ -53,30 +55,38 @@ impl Error { /// This code can either come from the underlying OS, or be a custom error. /// Use [`Error::raw_os_error()`] to disambiguate. #[inline] - pub fn code(&self) -> NonZeroU32 { + pub fn code(self) -> NonZeroU32 { self.0 } } -#[cfg(any(unix, target_os = "redox"))] -fn os_err_desc(errno: i32, buf: &mut [u8]) -> Option<&str> { - let buf_ptr = buf.as_mut_ptr() as *mut libc::c_char; - if unsafe { libc::strerror_r(errno, buf_ptr, buf.len()) } != 0 { - return None; - } - - // Take up to trailing null byte - let idx = buf.iter().position(|&b| b == 0).unwrap_or(buf.len()); - core::str::from_utf8(&buf[..idx]).ok() -} +cfg_if! { + if #[cfg(unix)] { + fn os_err_desc(errno: i32, buf: &mut [u8]) -> Option<&str> { + let buf_ptr = buf.as_mut_ptr() as *mut libc::c_char; + if unsafe { libc::strerror_r(errno, buf_ptr, buf.len()) } != 0 { + return None; + } -#[cfg(not(any(unix, target_os = "redox")))] -fn os_err_desc(_errno: i32, _buf: &mut [u8]) -> Option<&str> { - None + // Take up to trailing null byte + let n = buf.len(); + let idx = buf.iter().position(|&b| b == 0).unwrap_or(n); + core::str::from_utf8(&buf[..idx]).ok() + } + } else if #[cfg(target_os = "wasi")] { + fn os_err_desc(errno: i32, _buf: &mut [u8]) -> Option<&str> { + core::num::NonZeroU16::new(errno as u16) + .and_then(wasi::wasi_unstable::error_str) + } + } else { + fn os_err_desc(_errno: i32, _buf: &mut [u8]) -> Option<&str> { + None + } + } } impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut dbg = f.debug_struct("Error"); if let Some(errno) = self.raw_os_error() { dbg.field("os_error", &errno); @@ -95,7 +105,7 @@ impl fmt::Debug for Error { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(errno) = self.raw_os_error() { let mut buf = [0u8; 128]; match os_err_desc(errno, &mut buf) { diff --git a/vendor/getrandom/src/lib.rs b/vendor/getrandom/src/lib.rs index 338e806ddb..023a623050 100644 --- a/vendor/getrandom/src/lib.rs +++ b/vendor/getrandom/src/lib.rs @@ -12,13 +12,13 @@ //! //! | OS | interface //! |------------------|--------------------------------------------------------- -//! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after reading from `/dev/random` once +//! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` //! | Windows | [`RtlGenRandom`][3] //! | macOS | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`) //! | iOS | [`SecRandomCopyBytes`][4] //! | FreeBSD | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5] //! | OpenBSD | [`getentropy`][6] -//! | NetBSD | [`/dev/urandom`][7] after reading from `/dev/random` once +//! | NetBSD | [`/dev/urandom`][7] after successfully polling `/dev/random` //! | Dragonfly BSD | [`/dev/random`][8] //! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10] //! | Fuchsia OS | [`cprng_draw`][11] @@ -36,21 +36,37 @@ //! systems are using the recommended interface and respect maximum buffer //! sizes. //! -//! ## Support for WebAssembly and ams.js +//! ## Unsupported targets //! -//! The three Emscripten targets `asmjs-unknown-emscripten`, -//! `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use -//! Emscripten's emulation of `/dev/random` on web browsers and Node.js. +//! By default, compiling `getrandom` for an unsupported target will result in +//! a compilation error. If you want to build an application which uses `getrandom` +//! for such target, you can either: +//! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml` +//! to switch to a custom implementation with a support of your target. +//! - Enable the `dummy` feature to have getrandom use an implementation that always +//! fails at run-time on unsupported targets. //! -//! The bare WASM target `wasm32-unknown-unknown` tries to call the javascript -//! methods directly, using either `stdweb` or `wasm-bindgen` depending on what -//! features are activated for this crate. Note that if both features are -//! enabled `wasm-bindgen` will be used. If neither feature is enabled, -//! `getrandom` will always fail. +//! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section +//! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section //! -//! The WASI target `wasm32-wasi` uses the `__wasi_random_get` function defined -//! by the WASI standard. +//! ## Support for WebAssembly and asm.js //! +//! Getrandom supports all of Rust's current `wasm32` targets, and it works with +//! both Node.js and web browsers. The three Emscripten targets +//! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and +//! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation. +//! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function +//! defined by the WASI standard. +//! +//! Getrandom also supports `wasm32-unknown-unknown` by directly calling +//! JavaScript methods. Rust currently has two ways to do this: [bindgen] and +//! [stdweb]. Getrandom supports using either one by enabling the +//! `wasm-bindgen` or `stdweb` crate features. Note that if both features are +//! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls +//! to `getrandom` will always fail at runtime. +//! +//! [bindgen]: https://github.com/rust-lang/rust-bindgen +//! [stdweb]: https://github.com/koute/stdweb //! //! ## Early boot //! @@ -92,7 +108,7 @@ //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4 //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html -//! [11]: https://fuchsia.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/cprng_draw.md +//! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw //! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs //! [13]: https://github.com/nuxinl/cloudabi#random_get //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues @@ -112,6 +128,7 @@ )] #![no_std] #![cfg_attr(feature = "stdweb", recursion_limit = "128")] +#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)] #[macro_use] extern crate cfg_if; @@ -126,6 +143,14 @@ cfg_if! { macro_rules! error { ($($x:tt)*) => {}; } + #[allow(unused)] + macro_rules! warn { + ($($x:tt)*) => {}; + } + #[allow(unused)] + macro_rules! info { + ($($x:tt)*) => {}; + } } } @@ -134,41 +159,21 @@ pub use crate::error::Error; #[allow(dead_code)] mod util; -// Unlike the other Unix, Fuchsia and iOS don't use the libc to make any calls. -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "haiku", - target_os = "illumos", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox", - target_os = "solaris", -))] -#[allow(dead_code)] -mod util_libc; -// std-only trait definitions (also need for use_file) -#[cfg(any( - feature = "std", - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "haiku", - target_os = "illumos", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox", - target_os = "solaris", -))] -mod error_impls; +cfg_if! { + // Unlike the other Unix, Fuchsia and iOS don't use the libc to make any calls. + if #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "emscripten", + target_os = "freebsd", target_os = "haiku", target_os = "illumos", + target_os = "linux", target_os = "macos", target_os = "netbsd", + target_os = "openbsd", target_os = "redox", target_os = "solaris"))] { + #[allow(dead_code)] + mod util_libc; + // Keep std-only trait definitions for backwards compatiblity + mod error_impls; + } else if #[cfg(feature = "std")] { + mod error_impls; + } +} // These targets read from a file as a fallback method. #[cfg(any( @@ -216,6 +221,8 @@ cfg_if! { #[path = "solaris_illumos.rs"] mod imp; } else if #[cfg(target_os = "wasi")] { #[path = "wasi.rs"] mod imp; + } else if #[cfg(all(windows, getrandom_uwp))] { + #[path = "windows_uwp.rs"] mod imp; } else if #[cfg(windows)] { #[path = "windows.rs"] mod imp; } else if #[cfg(all(target_arch = "x86_64", any( @@ -225,18 +232,25 @@ cfg_if! { target_env = "sgx", )))] { #[path = "rdrand.rs"] mod imp; - } else if #[cfg(target_arch = "wasm32")] { + } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] { cfg_if! { if #[cfg(feature = "wasm-bindgen")] { #[path = "wasm32_bindgen.rs"] mod imp; } else if #[cfg(feature = "stdweb")] { #[path = "wasm32_stdweb.rs"] mod imp; } else { + // Always have an implementation for wasm32-unknown-unknown. + // See https://github.com/rust-random/getrandom/issues/87 #[path = "dummy.rs"] mod imp; } } - } else { + } else if #[cfg(feature = "dummy")] { #[path = "dummy.rs"] mod imp; + } else { + compile_error!("\ + target is not supported, for more information see: \ + https://docs.rs/getrandom/#unsupported-targets\ + "); } } diff --git a/vendor/getrandom/src/use_file.rs b/vendor/getrandom/src/use_file.rs index 74a12ef7fe..21e35343a8 100644 --- a/vendor/getrandom/src/use_file.rs +++ b/vendor/getrandom/src/use_file.rs @@ -7,18 +7,11 @@ // except according to those terms. //! Implementations that just need to read from a file -extern crate std; - -use crate::util_libc::{last_os_error, LazyFd}; +use crate::util_libc::{last_os_error, open_readonly, sys_fill_exact, LazyFd}; use crate::Error; -use core::mem::ManuallyDrop; -use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; -use std::{fs::File, io::Read}; #[cfg(target_os = "redox")] -const FILE_PATH: &str = "rand:"; -#[cfg(any(target_os = "android", target_os = "linux", target_os = "netbsd"))] -const FILE_PATH: &str = "/dev/urandom"; +const FILE_PATH: &str = "rand:\0"; #[cfg(any( target_os = "dragonfly", target_os = "emscripten", @@ -27,32 +20,54 @@ const FILE_PATH: &str = "/dev/urandom"; target_os = "solaris", target_os = "illumos" ))] -const FILE_PATH: &str = "/dev/random"; +const FILE_PATH: &str = "/dev/random\0"; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { static FD: LazyFd = LazyFd::new(); - let fd = FD.init(init_file).ok_or(last_os_error())?; - let file = ManuallyDrop::new(unsafe { File::from_raw_fd(fd) }); - let mut file_ref: &File = &file; + let fd = FD.init(init_file).ok_or_else(last_os_error)?; + let read = |buf: &mut [u8]| unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) }; if cfg!(target_os = "emscripten") { // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes. for chunk in dest.chunks_mut(65536) { - file_ref.read_exact(chunk)?; + sys_fill_exact(chunk, read)?; } } else { - file_ref.read_exact(dest)?; + sys_fill_exact(dest, read)?; } Ok(()) } -fn init_file() -> Option { - if FILE_PATH == "/dev/urandom" { - // read one byte from "/dev/random" to ensure that OS RNG has initialized - File::open("/dev/random") - .ok()? - .read_exact(&mut [0u8; 1]) - .ok()?; +cfg_if! { + if #[cfg(any(target_os = "android", target_os = "linux", target_os = "netbsd"))] { + fn init_file() -> Option { + // Poll /dev/random to make sure it is ok to read from /dev/urandom. + let mut pfd = libc::pollfd { + fd: unsafe { open_readonly("/dev/random\0")? }, + events: libc::POLLIN, + revents: 0, + }; + + let ret = loop { + // A negative timeout means an infinite timeout. + let res = unsafe { libc::poll(&mut pfd, 1, -1) }; + if res == 1 { + break unsafe { open_readonly("/dev/urandom\0") }; + } else if res < 0 { + let e = last_os_error().raw_os_error(); + if e == Some(libc::EINTR) || e == Some(libc::EAGAIN) { + continue; + } + } + // We either hard failed, or poll() returned the wrong pfd. + break None; + }; + unsafe { libc::close(pfd.fd) }; + ret + } + } else { + fn init_file() -> Option { + unsafe { open_readonly(FILE_PATH) } + } } - Some(File::open(FILE_PATH).ok()?.into_raw_fd()) } diff --git a/vendor/getrandom/src/util_libc.rs b/vendor/getrandom/src/util_libc.rs index 015d1a0483..d662fc6204 100644 --- a/vendor/getrandom/src/util_libc.rs +++ b/vendor/getrandom/src/util_libc.rs @@ -116,3 +116,25 @@ impl LazyFd { } } } + +cfg_if! { + if #[cfg(any(target_os = "linux", target_os = "emscripten"))] { + use libc::open64 as open; + } else { + use libc::open; + } +} + +// SAFETY: path must be null terminated, FD must be manually closed. +pub unsafe fn open_readonly(path: &str) -> Option { + debug_assert!(path.as_bytes().last() == Some(&0)); + let fd = open(path.as_ptr() as *mut _, libc::O_RDONLY | libc::O_CLOEXEC); + if fd < 0 { + return None; + } + // O_CLOEXEC works on all Unix targets except for older Linux kernels (pre + // 2.6.23), so we also use an ioctl to make sure FD_CLOEXEC is set. + #[cfg(target_os = "linux")] + libc::ioctl(fd, libc::FIOCLEX); + Some(fd) +} diff --git a/vendor/getrandom/src/wasi.rs b/vendor/getrandom/src/wasi.rs index 0920752f90..713c1ab90b 100644 --- a/vendor/getrandom/src/wasi.rs +++ b/vendor/getrandom/src/wasi.rs @@ -8,15 +8,12 @@ //! Implementation for WASI use crate::Error; -use core::num::NonZeroU32; +use core::num; +use wasi::wasi_unstable::random_get; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - let ret = - unsafe { libc::__wasi_random_get(dest.as_mut_ptr() as *mut libc::c_void, dest.len()) }; - if let Some(code) = NonZeroU32::new(ret as u32) { - error!("WASI: __wasi_random_get: failed with {}", ret); - Err(Error::from(code)) - } else { - Ok(()) // Zero means success for WASI - } + random_get(dest).map_err(|e: num::NonZeroU16| { + // convert wasi's NonZeroU16 error into getrandom's NonZeroU32 error + num::NonZeroU32::new(e.get() as u32).unwrap().into() + }) } diff --git a/vendor/getrandom/src/wasm32_bindgen.rs b/vendor/getrandom/src/wasm32_bindgen.rs index c6eef5fdff..86839a098a 100644 --- a/vendor/getrandom/src/wasm32_bindgen.rs +++ b/vendor/getrandom/src/wasm32_bindgen.rs @@ -58,54 +58,38 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { } fn getrandom_init() -> Result { - // First up we need to detect if we're running in node.js or a - // browser. To do this we get ahold of the `this` object (in a bit - // of a roundabout fashion). - // - // Once we have `this` we look at its `self` property, which is - // only defined on the web (either a main window or web worker). - let this = Function::new("return this").call(&JsValue::undefined()); - assert!(this != JsValue::undefined()); - let this = This::from(this); - let is_browser = this.self_() != JsValue::undefined(); - - if !is_browser { - return Ok(RngSource::Node(node_require("crypto"))); - } + if let Ok(self_) = Global::get_self() { + // If `self` is defined then we're in a browser somehow (main window + // or web worker). Here we want to try to use + // `crypto.getRandomValues`, but if `crypto` isn't defined we assume + // we're in an older web browser and the OS RNG isn't available. + + let crypto = self_.crypto(); + if crypto.is_undefined() { + return Err(BINDGEN_CRYPTO_UNDEF); + } - // If `self` is defined then we're in a browser somehow (main window - // or web worker). Here we want to try to use - // `crypto.getRandomValues`, but if `crypto` isn't defined we assume - // we're in an older web browser and the OS RNG isn't available. - let crypto = this.crypto(); - if crypto.is_undefined() { - return Err(BINDGEN_CRYPTO_UNDEF); - } + // Test if `crypto.getRandomValues` is undefined as well + let crypto: BrowserCrypto = crypto.into(); + if crypto.get_random_values_fn().is_undefined() { + return Err(BINDGEN_GRV_UNDEF); + } - // Test if `crypto.getRandomValues` is undefined as well - let crypto: BrowserCrypto = crypto.into(); - if crypto.get_random_values_fn().is_undefined() { - return Err(BINDGEN_GRV_UNDEF); + return Ok(RngSource::Browser(crypto)); } - // Ok! `self.crypto.getRandomValues` is a defined value, so let's - // assume we can do browser crypto. - Ok(RngSource::Browser(crypto)) + return Ok(RngSource::Node(node_require("crypto"))); } #[wasm_bindgen] extern "C" { - type Function; - #[wasm_bindgen(constructor)] - fn new(s: &str) -> Function; - #[wasm_bindgen(method)] - fn call(this: &Function, self_: &JsValue) -> JsValue; - - type This; - #[wasm_bindgen(method, getter, structural, js_name = self)] - fn self_(me: &This) -> JsValue; + type Global; + #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = self, js_name = self)] + fn get_self() -> Result; + + type Self_; #[wasm_bindgen(method, getter, structural)] - fn crypto(me: &This) -> JsValue; + fn crypto(me: &Self_) -> JsValue; #[derive(Clone, Debug)] type BrowserCrypto; diff --git a/vendor/getrandom/src/wasm32_stdweb.rs b/vendor/getrandom/src/wasm32_stdweb.rs index d8380c1368..6e5e78a4a6 100644 --- a/vendor/getrandom/src/wasm32_stdweb.rs +++ b/vendor/getrandom/src/wasm32_stdweb.rs @@ -11,9 +11,9 @@ extern crate std; use core::mem; +use stdweb::js; use stdweb::unstable::TryInto; use stdweb::web::error::Error as WebError; -use stdweb::{_js_impl, js}; use crate::error::{STDWEB_NO_RNG, STDWEB_RNG_FAILED}; use crate::Error; @@ -69,8 +69,8 @@ fn getrandom_init() -> Result { unreachable!() } } else { - let err: WebError = js! { return @{ result }.error }.try_into().unwrap(); - error!("getrandom unavailable: {}", err); + let _err: WebError = js! { return @{ result }.error }.try_into().unwrap(); + error!("getrandom unavailable: {}", _err); Err(STDWEB_NO_RNG) } } @@ -105,8 +105,8 @@ fn getrandom_fill(source: RngSource, dest: &mut [u8]) -> Result<(), Error> { }; if js! { return @{ result.as_ref() }.success } != true { - let err: WebError = js! { return @{ result }.error }.try_into().unwrap(); - error!("getrandom failed: {}", err); + let _err: WebError = js! { return @{ result }.error }.try_into().unwrap(); + error!("getrandom failed: {}", _err); return Err(STDWEB_RNG_FAILED); } } diff --git a/vendor/getrandom/src/windows_uwp.rs b/vendor/getrandom/src/windows_uwp.rs new file mode 100644 index 0000000000..bf15d1a2f6 --- /dev/null +++ b/vendor/getrandom/src/windows_uwp.rs @@ -0,0 +1,59 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Implementation for Windows UWP targets. After deprecation of Windows XP +//! and Vista, this can superseed the `RtlGenRandom`-based implementation. +use crate::Error; +use core::{ffi::c_void, num::NonZeroU32, ptr}; + +const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002; + +extern "system" { + fn BCryptGenRandom( + hAlgorithm: *mut c_void, + pBuffer: *mut u8, + cbBuffer: u32, + dwFlags: u32, + ) -> u32; +} + +pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + // Prevent overflow of u32 + for chunk in dest.chunks_mut(u32::max_value() as usize) { + let ret = unsafe { + BCryptGenRandom( + ptr::null_mut(), + chunk.as_mut_ptr(), + chunk.len() as u32, + BCRYPT_USE_SYSTEM_PREFERRED_RNG, + ) + }; + // NTSTATUS codes use two highest bits for severity status + match ret >> 30 { + 0b01 => { + info!("BCryptGenRandom: information code 0x{:08X}", ret); + } + 0b10 => { + warn!("BCryptGenRandom: warning code 0x{:08X}", ret); + } + 0b11 => { + error!("BCryptGenRandom: failed with 0x{:08X}", ret); + // We zeroize the highest bit, so the error code will reside + // inside the range of designated for OS codes. + let code = ret ^ (1 << 31); + // SAFETY: the second highest bit is always equal to one, + // so it's impossible to get zero. Unfortunately compiler + // is not smart enough to figure out it yet. + let code = unsafe { NonZeroU32::new_unchecked(code) }; + return Err(Error::from(code)); + } + _ => (), + } + } + Ok(()) +} diff --git a/vendor/hashbrown-0.4.0/.cargo-checksum.json b/vendor/hashbrown-0.4.0/.cargo-checksum.json deleted file mode 100644 index 9c60224696..0000000000 --- a/vendor/hashbrown-0.4.0/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"1c9928d8fe02aa9ab2e073590224f21439270a80dc68df7f9132510d30961076","Cargo.toml":"91a8be0fd778b61a96e285974431b34dbeba7fec800895e1d6f98143e96547bc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"0735fe14e65cda39df259e58c10aff5cffb897ccce9efa9c49fab14b9afe55ea","benches/bench.rs":"b8df8a3e1e7ea9f0a9ed6867ac178bb233b1da80b602c6e3574d592943c07ee7","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"d4fbca4db924925548f8dab8eb94cf4a3955a53c5e1ff15f59c460546c394034","src/external_trait_impls/rayon/map.rs":"fb0c2c1cafee4d5b65ede372fe5bfce86181d87ac71dcc2e7fd5b882fb920ecc","src/external_trait_impls/rayon/mod.rs":"b48139960a89ee84ed3b5e10ee5abb0259b40f2bb0ef867d0dd65784252a47c0","src/external_trait_impls/rayon/raw.rs":"1bf4f9fddaec0c6270cfc3dc3f3096027aeccdf73c259af3c7bfd61d6c672b9f","src/external_trait_impls/rayon/set.rs":"40dbd669a60f13d5fe4697837cacbcc1109b36c84a964dd74a02d8754eb058a3","src/external_trait_impls/serde.rs":"c429ec8fb922706df2bb3b774284c7951d0e2101a18a8bfd4a44323b50a33709","src/fx.rs":"4756873e73ad698109de6d2d8fd0711a047ac994200827fc3e6cfa9b18bff32a","src/lib.rs":"6455a8d9271d9adecaf12748ae6d0421b3f928324028eae9c1af6f4f4f34381a","src/macros.rs":"c53829e64b434b3b89e88f3dd5ec974cd812b7fb8ed981074c666852667651d4","src/map.rs":"4aef0e549c13101683689153aeb8fe2a419374573c9f3f29d84793a52cdb1926","src/raw/bitmask.rs":"3c1f33b09b212d3828a89c11a86ab1bb18dedc20e45ff0032787ca49de2833c5","src/raw/generic.rs":"9df50cf88e80acde6a13aa9e083a8512090d25ab4daeac5eed43c3602560e844","src/raw/mod.rs":"c6127504e1bdab56b55bcb8e8c933710e7e3b0f1bf1eeb3169756b3f6332d3e9","src/raw/sse2.rs":"8a564c91c9af1e824d0400a562e23bf2b6e3398744c39e32d1c22afff75612a1","src/rustc_entry.rs":"96f78e34cc41bc4a3866445b144070cdb325be14d54c9935605e9f23b8a06f31","src/scopeguard.rs":"808655b3e98512fdcee5a4597e7763a6be99582ba8d77e5ba5ca130d85a97211","src/set.rs":"517ea92827194679f2087f03e55d0635735c91a630dac771e045018a4d47f660","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"2286707a87b139f41902c82488c355b9fb402a3e734f392f3a73e87b9b932795","tests/serde.rs":"1260f576d3fb1c0979dd12718cb46e96a1989f95ca928014deccd279ec33b4a3","tests/set.rs":"fe75951f508db10055d2f4a9cde30d4418e941ff28c3b068fc5b0d57c71cab6c"},"package":"9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"} \ No newline at end of file diff --git a/vendor/hashbrown-0.4.0/CHANGELOG.md b/vendor/hashbrown-0.4.0/CHANGELOG.md deleted file mode 100644 index 34796e09a9..0000000000 --- a/vendor/hashbrown-0.4.0/CHANGELOG.md +++ /dev/null @@ -1,128 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [Unreleased] - -## [v0.4.0] - 2019-05-30 - -### Fixed -- Fixed `Send` trait bounds on `IterMut` not matching the libstd one. (#82) - -## [v0.3.1] - 2019-05-30 - -### Fixed -- Fixed incorrect use of slice in unsafe code. (#80) - -## [v0.3.0] - 2019-04-23 - -### Changed -- Changed shrink_to to not panic if min_capacity < capacity. (#67) - -### Fixed -- Worked around emscripten bug emscripten-core/emscripten-fastcomp#258. (#66) - -## [v0.2.2] - 2019-04-16 - -### Fixed -- Inlined non-nightly lowest_set_bit_nonzero. (#64) -- Fixed build on latest nightly. (#65) - -## [v0.2.1] - 2019-04-14 - -### Changed -- Use for_each in map Extend and FromIterator. (#58) -- Improved worst-case performance of HashSet.is_subset. (#61) - -### Fixed -- Removed incorrect debug_assert. (#60) - -## [v0.2.0] - 2019-03-31 - -### Changed -- The code has been updated to Rust 2018 edition. This means that the minimum - Rust version has been bumped to 1.31 (2018 edition). - -### Added -- Added `insert_with_hasher` to the raw_entry API to allow `K: !(Hash + Eq)`. (#54) -- Added support for using hashbrown as the hash table implementation in libstd. (#46) - -### Fixed -- Fixed cargo build with minimal-versions. (#45) -- Fixed `#[may_dangle]` attributes to match the libstd `HashMap`. (#46) -- ZST keys and values are now handled properly. (#46) - -## [v0.1.8] - 2019-01-14 - -### Added -- Rayon parallel iterator support (#37) -- `raw_entry` support (#31) -- `#[may_dangle]` on nightly (#31) -- `try_reserve` support (#31) - -### Fixed -- Fixed variance on `IterMut`. (#31) - -## [v0.1.7] - 2018-12-05 - -### Fixed -- Fixed non-SSE version of convert_special_to_empty_and_full_to_deleted. (#32) -- Fixed overflow in rehash_in_place. (#33) - -## [v0.1.6] - 2018-11-17 - -### Fixed -- Fixed compile error on nightly. (#29) - -## [v0.1.5] - 2018-11-08 - -### Fixed -- Fixed subtraction overflow in generic::Group::match_byte. (#28) - -## [v0.1.4] - 2018-11-04 - -### Fixed -- Fixed a bug in the `erase_no_drop` implementation. (#26) - -## [v0.1.3] - 2018-11-01 - -### Added -- Serde support. (#14) - -### Fixed -- Make the compiler inline functions more aggressively. (#20) - -## [v0.1.2] - 2018-10-31 - -### Fixed -- `clear` segfaults when called on an empty table. (#13) - -## [v0.1.1] - 2018-10-30 - -### Fixed -- `erase_no_drop` optimization not triggering in the SSE2 implementation. (#3) -- Missing `Send` and `Sync` for hash map and iterator types. (#7) -- Bug when inserting into a table smaller than the group width. (#5) - -## v0.1.0 - 2018-10-29 - -- Initial release - -[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.4.0...HEAD -[v0.4.0]: https://github.com/rust-lang/hashbrown/compare/v0.3.1...v0.4.0 -[v0.3.1]: https://github.com/rust-lang/hashbrown/compare/v0.3.0...v0.3.1 -[v0.3.0]: https://github.com/rust-lang/hashbrown/compare/v0.2.2...v0.3.0 -[v0.2.2]: https://github.com/rust-lang/hashbrown/compare/v0.2.1...v0.2.2 -[v0.2.1]: https://github.com/rust-lang/hashbrown/compare/v0.2.0...v0.2.1 -[v0.2.0]: https://github.com/rust-lang/hashbrown/compare/v0.1.8...v0.2.0 -[v0.1.8]: https://github.com/rust-lang/hashbrown/compare/v0.1.7...v0.1.8 -[v0.1.7]: https://github.com/rust-lang/hashbrown/compare/v0.1.6...v0.1.7 -[v0.1.6]: https://github.com/rust-lang/hashbrown/compare/v0.1.5...v0.1.6 -[v0.1.5]: https://github.com/rust-lang/hashbrown/compare/v0.1.4...v0.1.5 -[v0.1.4]: https://github.com/rust-lang/hashbrown/compare/v0.1.3...v0.1.4 -[v0.1.3]: https://github.com/rust-lang/hashbrown/compare/v0.1.2...v0.1.3 -[v0.1.2]: https://github.com/rust-lang/hashbrown/compare/v0.1.1...v0.1.2 -[v0.1.1]: https://github.com/rust-lang/hashbrown/compare/v0.1.0...v0.1.1 diff --git a/vendor/hashbrown-0.4.0/Cargo.toml b/vendor/hashbrown-0.4.0/Cargo.toml deleted file mode 100644 index 0cf03ca18f..0000000000 --- a/vendor/hashbrown-0.4.0/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "hashbrown" -version = "0.4.0" -authors = ["Amanieu d'Antras "] -exclude = [".travis.yml", "bors.toml", "/ci/*"] -description = "A Rust port of Google's SwissTable hash map" -readme = "README.md" -keywords = ["hash", "no_std", "hashmap", "swisstable"] -categories = ["data-structures", "no-std"] -license = "Apache-2.0/MIT" -repository = "https://github.com/rust-lang/hashbrown" -[dependencies.alloc] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-alloc" - -[dependencies.compiler_builtins] -version = "0.1.2" -optional = true - -[dependencies.core] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-core" - -[dependencies.rayon] -version = "1.0" -optional = true - -[dependencies.serde] -version = "1.0.25" -optional = true -default-features = false -[dev-dependencies.lazy_static] -version = "~1.2" - -[dev-dependencies.rand] -version = "0.5.1" - -[dev-dependencies.rayon] -version = "1.0" - -[dev-dependencies.rustc-hash] -version = "1.0" - -[dev-dependencies.serde_test] -version = "1.0" - -[features] -default = [] -nightly = [] -rustc-dep-of-std = ["nightly", "core", "compiler_builtins", "alloc"] diff --git a/vendor/hashbrown-0.4.0/README.md b/vendor/hashbrown-0.4.0/README.md deleted file mode 100644 index 123e18bcd9..0000000000 --- a/vendor/hashbrown-0.4.0/README.md +++ /dev/null @@ -1,87 +0,0 @@ -hashbrown -========= - -[![Build Status](https://travis-ci.com/rust-lang/hashbrown.svg?branch=master)](https://travis-ci.com/rust-lang/hashbrown) -[![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown) -[![Documentation](https://docs.rs/hashbrown/badge.svg)](https://docs.rs/hashbrown) - -This crate is a Rust port of Google's high-performance [SwissTable] hash -map, adapted to make it a drop-in replacement for Rust's standard `HashMap` -and `HashSet` types. - -The original C++ version of SwissTable can be found [here], and this -[CppCon talk] gives an overview of how the algorithm works. - -[SwissTable]: https://abseil.io/blog/20180927-swisstables -[here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h -[CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4 - -## [Change log](CHANGELOG.md) - -## Features - -- Drop-in replacement for the standard library `HashMap` and `HashSet` types. -- Uses `FxHash` as the default hasher, which is much faster than SipHash. -- Around 2x faster than `FxHashMap` and 8x faster than the standard `HashMap`. -- Lower memory usage: only 1 byte of overhead per entry instead of 8. -- Compatible with `#[no_std]` (currently requires nightly for the `alloc` crate). -- Empty hash maps do not allocate any memory. -- SIMD lookups to scan multiple hash entries in parallel. - -## Performance - -Compared to `std::collections::HashMap`: - -``` - name stdhash ns/iter hashbrown ns/iter diff ns/iter diff % speedup - find_existing 23,831 2,935 -20,896 -87.68% x 8.12 - find_nonexisting 25,326 2,283 -23,043 -90.99% x 11.09 - get_remove_insert 124 25 -99 -79.84% x 4.96 - grow_by_insertion 197 177 -20 -10.15% x 1.11 - hashmap_as_queue 72 18 -54 -75.00% x 4.00 - new_drop 14 0 -14 -100.00% x inf - new_insert_drop 78 55 -23 -29.49% x 1.42 -``` - -Compared to `rustc_hash::FxHashMap` (standard `HashMap` using `FxHash` instead of `SipHash`): - -``` - name fxhash ns/iter hashbrown ns/iter diff ns/iter diff % speedup - find_existing 5,951 2,935 -3,016 -50.68% x 2.03 - find_nonexisting 4,637 2,283 -2,354 -50.77% x 2.03 - get_remove_insert 29 25 -4 -13.79% x 1.16 - grow_by_insertion 160 177 17 10.62% x 0.90 - hashmap_as_queue 22 18 -4 -18.18% x 1.22 - new_drop 9 0 -9 -100.00% x inf - new_insert_drop 64 55 -9 -14.06% x 1.16 -``` - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -hashbrown = "0.4" -``` - -This crate has the following Cargo features: - -- `nightly`: Enables nightly-only features: `no_std` support and `#[may_dangle]`. -- `serde`: Enables serde serialization support. -- `rayon`: Enables rayon parallel iterator support. - -## License - -Licensed under either of: - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any -additional terms or conditions. diff --git a/vendor/hashbrown-0.4.0/benches/bench.rs b/vendor/hashbrown-0.4.0/benches/bench.rs deleted file mode 100644 index 9c1542a40b..0000000000 --- a/vendor/hashbrown-0.4.0/benches/bench.rs +++ /dev/null @@ -1,150 +0,0 @@ -#![feature(test)] - -extern crate test; - -use std::hash::Hash; -use test::{black_box, Bencher}; - -use hashbrown::HashMap; -//use rustc_hash::FxHashMap as HashMap; -//use std::collections::HashMap; - -fn new_map() -> HashMap { - HashMap::default() -} - -#[bench] -fn insert_i32(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - black_box(m); - }) -} - -#[bench] -fn insert_i64(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - black_box(m); - }) -} - -#[bench] -fn insert_erase_i32(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - black_box(&mut m); - for i in 1..1001 { - m.remove(&i); - } - black_box(m); - }) -} - -#[bench] -fn insert_erase_i64(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - black_box(&mut m); - for i in 1..1001 { - m.remove(&i); - } - black_box(m); - }) -} - -#[bench] -fn lookup_i32(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in 1..1001 { - black_box(m.get(&i)); - } - }) -} - -#[bench] -fn lookup_i64(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in 1..1001 { - black_box(m.get(&i)); - } - }) -} - -#[bench] -fn lookup_fail_i32(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in 1001..2001 { - black_box(m.get(&i)); - } - }) -} - -#[bench] -fn lookup_fail_i64(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in 1001..2001 { - black_box(m.get(&i)); - } - }) -} - -#[bench] -fn iter_i32(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in &m { - black_box(i); - } - }) -} - -#[bench] -fn iter_i64(b: &mut Bencher) { - let mut m: HashMap = new_map(); - for i in 1..1001 { - m.insert(i, i); - } - - b.iter(|| { - for i in &m { - black_box(i); - } - }) -} diff --git a/vendor/hashbrown-0.4.0/clippy.toml b/vendor/hashbrown-0.4.0/clippy.toml deleted file mode 100644 index d98bf2c09b..0000000000 --- a/vendor/hashbrown-0.4.0/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -doc-valid-idents = [ "CppCon", "SwissTable", "SipHash", "HashDoS" ] diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/mod.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/mod.rs deleted file mode 100644 index ef497836cb..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg(feature = "rayon")] -pub(crate) mod rayon; -#[cfg(feature = "serde")] -mod serde; diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/helpers.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/helpers.rs deleted file mode 100644 index 9382007ea2..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/helpers.rs +++ /dev/null @@ -1,26 +0,0 @@ -use alloc::collections::LinkedList; -use alloc::vec::Vec; - -use rayon::iter::{IntoParallelIterator, ParallelIterator}; - -/// Helper for collecting parallel iterators to an intermediary -pub(super) fn collect(iter: I) -> (LinkedList>, usize) { - let list = iter - .into_par_iter() - .fold(Vec::new, |mut vec, elem| { - vec.push(elem); - vec - }) - .map(|vec| { - let mut list = LinkedList::new(); - list.push_back(vec); - list - }) - .reduce(LinkedList::new, |mut list1, mut list2| { - list1.append(&mut list2); - list1 - }); - - let len = list.iter().map(Vec::len).sum(); - (list, len) -} diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/map.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/map.rs deleted file mode 100644 index 6f869ae0a0..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/map.rs +++ /dev/null @@ -1,676 +0,0 @@ -//! Rayon extensions for `HashMap`. - -use crate::hash_map::HashMap; -use core::fmt; -use core::hash::{BuildHasher, Hash}; -use rayon::iter::plumbing::UnindexedConsumer; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; - -/// Parallel iterator over shared references to entries in a map. -/// -/// This iterator is created by the [`par_iter`] method on [`HashMap`] -/// (provided by the [`IntoParallelRefIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html -pub struct ParIter<'a, K, V, S> { - map: &'a HashMap, -} - -impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParIter<'a, K, V, S> { - type Item = (&'a K, &'a V); - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map - .table - .par_iter() - .map(|x| unsafe { - let r = x.as_ref(); - (&r.0, &r.1) - }) - .drive_unindexed(consumer) - } -} - -impl Clone for ParIter<'_, K, V, S> { - #[inline] - fn clone(&self) -> Self { - ParIter { map: self.map } - } -} - -impl fmt::Debug for ParIter<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.iter().fmt(f) - } -} - -/// Parallel iterator over shared references to keys in a map. -/// -/// This iterator is created by the [`par_keys`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParKeys<'a, K, V, S> { - map: &'a HashMap, -} - -impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParKeys<'a, K, V, S> { - type Item = &'a K; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map - .table - .par_iter() - .map(|x| unsafe { &x.as_ref().0 }) - .drive_unindexed(consumer) - } -} - -impl Clone for ParKeys<'_, K, V, S> { - #[inline] - fn clone(&self) -> Self { - ParKeys { map: self.map } - } -} - -impl fmt::Debug for ParKeys<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.keys().fmt(f) - } -} - -/// Parallel iterator over shared references to values in a map. -/// -/// This iterator is created by the [`par_values`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParValues<'a, K, V, S> { - map: &'a HashMap, -} - -impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParValues<'a, K, V, S> { - type Item = &'a V; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map - .table - .par_iter() - .map(|x| unsafe { &x.as_ref().1 }) - .drive_unindexed(consumer) - } -} - -impl Clone for ParValues<'_, K, V, S> { - #[inline] - fn clone(&self) -> Self { - ParValues { map: self.map } - } -} - -impl fmt::Debug for ParValues<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.values().fmt(f) - } -} - -/// Parallel iterator over mutable references to entries in a map. -/// -/// This iterator is created by the [`par_iter_mut`] method on [`HashMap`] -/// (provided by the [`IntoParallelRefMutIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html -pub struct ParIterMut<'a, K, V, S> { - map: &'a mut HashMap, -} - -impl<'a, K: Send + Sync, V: Send, S: Send> ParallelIterator for ParIterMut<'a, K, V, S> { - type Item = (&'a K, &'a mut V); - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map - .table - .par_iter() - .map(|x| unsafe { - let r = x.as_mut(); - (&r.0, &mut r.1) - }) - .drive_unindexed(consumer) - } -} - -impl fmt::Debug - for ParIterMut<'_, K, V, S> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.iter().fmt(f) - } -} - -/// Parallel iterator over mutable references to values in a map. -/// -/// This iterator is created by the [`par_values_mut`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParValuesMut<'a, K, V, S> { - map: &'a mut HashMap, -} - -impl<'a, K: Send, V: Send, S: Send> ParallelIterator for ParValuesMut<'a, K, V, S> { - type Item = &'a mut V; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map - .table - .par_iter() - .map(|x| unsafe { &mut x.as_mut().1 }) - .drive_unindexed(consumer) - } -} - -impl fmt::Debug for ParValuesMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.values().fmt(f) - } -} - -/// Parallel iterator over entries of a consumed map. -/// -/// This iterator is created by the [`into_par_iter`] method on [`HashMap`] -/// (provided by the [`IntoParallelIterator`] trait). -/// See its documentation for more. -/// -/// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html -pub struct IntoParIter { - map: HashMap, -} - -impl ParallelIterator for IntoParIter { - type Item = (K, V); - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map.table.into_par_iter().drive_unindexed(consumer) - } -} - -impl fmt::Debug for IntoParIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.iter().fmt(f) - } -} - -/// Parallel draining iterator over entries of a map. -/// -/// This iterator is created by the [`par_drain`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParDrain<'a, K, V, S> { - map: &'a mut HashMap, -} - -impl ParallelIterator for ParDrain<'_, K, V, S> { - type Item = (K, V); - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.map.table.par_drain().drive_unindexed(consumer) - } -} - -impl fmt::Debug - for ParDrain<'_, K, V, S> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.map.iter().fmt(f) - } -} - -impl HashMap { - /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order. - #[inline] - pub fn par_keys(&self) -> ParKeys<'_, K, V, S> { - ParKeys { map: self } - } - - /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order. - #[inline] - pub fn par_values(&self) -> ParValues<'_, K, V, S> { - ParValues { map: self } - } -} - -impl HashMap { - /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order. - #[inline] - pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V, S> { - ParValuesMut { map: self } - } - - /// Consumes (potentially in parallel) all values in an arbitrary order, - /// while preserving the map's allocated memory for reuse. - #[inline] - pub fn par_drain(&mut self) -> ParDrain<'_, K, V, S> { - ParDrain { map: self } - } -} - -impl HashMap -where - K: Eq + Hash + Sync, - V: PartialEq + Sync, - S: BuildHasher + Sync, -{ - /// Returns `true` if the map is equal to another, - /// i.e. both maps contain the same keys mapped to the same values. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_eq(&self, other: &Self) -> bool { - self.len() == other.len() - && self - .into_par_iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) - } -} - -impl IntoParallelIterator for HashMap { - type Item = (K, V); - type Iter = IntoParIter; - - #[inline] - fn into_par_iter(self) -> Self::Iter { - IntoParIter { map: self } - } -} - -impl<'a, K: Sync, V: Sync, S: Sync> IntoParallelIterator for &'a HashMap { - type Item = (&'a K, &'a V); - type Iter = ParIter<'a, K, V, S>; - - #[inline] - fn into_par_iter(self) -> Self::Iter { - ParIter { map: self } - } -} - -impl<'a, K: Send + Sync, V: Send, S: Send> IntoParallelIterator for &'a mut HashMap { - type Item = (&'a K, &'a mut V); - type Iter = ParIterMut<'a, K, V, S>; - - #[inline] - fn into_par_iter(self) -> Self::Iter { - ParIterMut { map: self } - } -} - -/// Collect (key, value) pairs from a parallel iterator into a -/// hashmap. If multiple pairs correspond to the same key, then the -/// ones produced earlier in the parallel iterator will be -/// overwritten, just as with a sequential iterator. -impl FromParallelIterator<(K, V)> for HashMap -where - K: Eq + Hash + Send, - V: Send, - S: BuildHasher + Default, -{ - fn from_par_iter

(par_iter: P) -> Self - where - P: IntoParallelIterator, - { - let mut map = HashMap::default(); - map.par_extend(par_iter); - map - } -} - -/// Extend a hash map with items from a parallel iterator. -impl ParallelExtend<(K, V)> for HashMap -where - K: Eq + Hash + Send, - V: Send, - S: BuildHasher, -{ - fn par_extend(&mut self, par_iter: I) - where - I: IntoParallelIterator, - { - extend(self, par_iter); - } -} - -/// Extend a hash map with copied items from a parallel iterator. -impl<'a, K, V, S> ParallelExtend<(&'a K, &'a V)> for HashMap -where - K: Copy + Eq + Hash + Sync, - V: Copy + Sync, - S: BuildHasher, -{ - fn par_extend(&mut self, par_iter: I) - where - I: IntoParallelIterator, - { - extend(self, par_iter); - } -} - -// This is equal to the normal `HashMap` -- no custom advantage. -fn extend(map: &mut HashMap, par_iter: I) -where - K: Eq + Hash, - S: BuildHasher, - I: IntoParallelIterator, - HashMap: Extend, -{ - let (list, len) = super::helpers::collect(par_iter); - - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire length if the map is empty. - // Otherwise reserve half the length (rounded up), so the map - // will only resize twice in the worst case. - let reserve = if map.is_empty() { len } else { (len + 1) / 2 }; - map.reserve(reserve); - for vec in list { - map.extend(vec); - } -} - -#[cfg(test)] -mod test_par_map { - use alloc::vec::Vec; - use core::hash::{Hash, Hasher}; - use core::sync::atomic::{AtomicUsize, Ordering}; - - use rayon::prelude::*; - - use crate::hash_map::HashMap; - - struct Dropable<'a> { - k: usize, - counter: &'a AtomicUsize, - } - - impl Dropable<'_> { - fn new(k: usize, counter: &AtomicUsize) -> Dropable<'_> { - counter.fetch_add(1, Ordering::Relaxed); - - Dropable { k, counter } - } - } - - impl Drop for Dropable<'_> { - fn drop(&mut self) { - self.counter.fetch_sub(1, Ordering::Relaxed); - } - } - - impl Clone for Dropable<'_> { - fn clone(&self) -> Self { - Dropable::new(self.k, self.counter) - } - } - - impl Hash for Dropable<'_> { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.k.hash(state) - } - } - - impl PartialEq for Dropable<'_> { - fn eq(&self, other: &Self) -> bool { - self.k == other.k - } - } - - impl Eq for Dropable<'_> {} - - #[test] - fn test_into_iter_drops() { - let key = AtomicUsize::new(0); - let value = AtomicUsize::new(0); - - let hm = { - let mut hm = HashMap::new(); - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - - for i in 0..100 { - let d1 = Dropable::new(i, &key); - let d2 = Dropable::new(i + 100, &value); - hm.insert(d1, d2); - } - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // Ensure that dropping the iterator does not leak anything. - drop(hm.clone().into_par_iter()); - - { - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // retain only half - let _v: Vec<_> = hm - .into_par_iter() - .filter(|&(ref key, _)| key.k < 50) - .collect(); - - assert_eq!(key.load(Ordering::Relaxed), 50); - assert_eq!(value.load(Ordering::Relaxed), 50); - }; - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - } - - #[test] - fn test_drain_drops() { - let key = AtomicUsize::new(0); - let value = AtomicUsize::new(0); - - let mut hm = { - let mut hm = HashMap::new(); - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - - for i in 0..100 { - let d1 = Dropable::new(i, &key); - let d2 = Dropable::new(i + 100, &value); - hm.insert(d1, d2); - } - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // Ensure that dropping the drain iterator does not leak anything. - drop(hm.clone().par_drain()); - - { - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // retain only half - let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect(); - assert!(hm.is_empty()); - - assert_eq!(key.load(Ordering::Relaxed), 50); - assert_eq!(value.load(Ordering::Relaxed), 50); - }; - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - } - - #[test] - fn test_empty_iter() { - let mut m: HashMap = HashMap::new(); - assert_eq!(m.par_drain().count(), 0); - assert_eq!(m.par_keys().count(), 0); - assert_eq!(m.par_values().count(), 0); - assert_eq!(m.par_values_mut().count(), 0); - assert_eq!(m.par_iter().count(), 0); - assert_eq!(m.par_iter_mut().count(), 0); - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - assert_eq!(m.into_par_iter().count(), 0); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in 0..32 { - assert!(m.insert(i, i * 2).is_none()); - } - assert_eq!(m.len(), 32); - - let observed = AtomicUsize::new(0); - - m.par_iter().for_each(|(k, v)| { - assert_eq!(*v, *k * 2); - observed.fetch_or(1 << *k, Ordering::Relaxed); - }); - assert_eq!(observed.into_inner(), 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_par_iter().collect(); - let keys: Vec<_> = map.par_keys().cloned().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_par_iter().collect(); - let values: Vec<_> = map.par_values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_values_mut() { - let vec = vec![(1, 1), (2, 2), (3, 3)]; - let mut map: HashMap<_, _> = vec.into_par_iter().collect(); - map.par_values_mut().for_each(|value| *value = (*value) * 2); - let values: Vec<_> = map.par_values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&2)); - assert!(values.contains(&4)); - assert!(values.contains(&6)); - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); - - let mut m2 = HashMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); - - assert!(!m1.par_eq(&m2)); - - m2.insert(3, 4); - - assert!(m1.par_eq(&m2)); - } - - #[test] - fn test_from_iter() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.par_iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_extend_ref() { - let mut a = HashMap::new(); - a.insert(1, "one"); - let mut b = HashMap::new(); - b.insert(2, "two"); - b.insert(3, "three"); - - a.par_extend(&b); - - assert_eq!(a.len(), 3); - assert_eq!(a[&1], "one"); - assert_eq!(a[&2], "two"); - assert_eq!(a[&3], "three"); - } -} diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/mod.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/mod.rs deleted file mode 100644 index 6765299c74..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod helpers; -mod raw; - -pub(crate) mod map; -pub(crate) mod set; diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/raw.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/raw.rs deleted file mode 100644 index 6834705cfd..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/raw.rs +++ /dev/null @@ -1,193 +0,0 @@ -use crate::raw::Bucket; -use crate::raw::{RawIterRange, RawTable}; -use crate::scopeguard::guard; -use alloc::alloc::dealloc; -use core::marker::PhantomData; -use core::mem; -use core::ptr::NonNull; -use rayon::iter::{ - plumbing::{self, Folder, UnindexedConsumer, UnindexedProducer}, - ParallelIterator, -}; - -/// Parallel iterator which returns a raw pointer to every full bucket in the table. -pub struct RawParIter { - iter: RawIterRange, -} - -impl ParallelIterator for RawParIter { - type Item = Bucket; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - let producer = ParIterProducer { iter: self.iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -/// Producer which returns a `Bucket` for every element. -struct ParIterProducer { - iter: RawIterRange, -} - -impl UnindexedProducer for ParIterProducer { - type Item = Bucket; - - #[inline] - fn split(self) -> (Self, Option) { - let (left, right) = self.iter.split(); - let left = ParIterProducer { iter: left }; - let right = right.map(|right| ParIterProducer { iter: right }); - (left, right) - } - - #[inline] - fn fold_with(self, folder: F) -> F - where - F: Folder, - { - folder.consume_iter(self.iter) - } -} - -/// Parallel iterator which consumes a table and returns elements. -pub struct RawIntoParIter { - table: RawTable, -} - -impl ParallelIterator for RawIntoParIter { - type Item = T; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - let iter = unsafe { self.table.iter().iter }; - let _guard = guard(self.table.into_alloc(), |alloc| { - if let Some((ptr, layout)) = *alloc { - unsafe { - dealloc(ptr.as_ptr(), layout); - } - } - }); - let producer = ParDrainProducer { iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -/// Parallel iterator which consumes elements without freeing the table storage. -pub struct RawParDrain<'a, T> { - // We don't use a &'a mut RawTable because we want RawParDrain to be - // covariant over T. - table: NonNull>, - marker: PhantomData<&'a RawTable>, -} - -unsafe impl Send for RawParDrain<'_, T> {} - -impl ParallelIterator for RawParDrain<'_, T> { - type Item = T; - - #[inline] - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - let _guard = guard(self.table, |table| unsafe { - table.as_mut().clear_no_drop() - }); - let iter = unsafe { self.table.as_ref().iter().iter }; - mem::forget(self); - let producer = ParDrainProducer { iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -impl Drop for RawParDrain<'_, T> { - fn drop(&mut self) { - // If drive_unindexed is not called then simply clear the table. - unsafe { self.table.as_mut().clear() } - } -} - -/// Producer which will consume all elements in the range, even if it is dropped -/// halfway through. -struct ParDrainProducer { - iter: RawIterRange, -} - -impl UnindexedProducer for ParDrainProducer { - type Item = T; - - #[inline] - fn split(self) -> (Self, Option) { - let (left, right) = self.iter.clone().split(); - mem::forget(self); - let left = ParDrainProducer { iter: left }; - let right = right.map(|right| ParDrainProducer { iter: right }); - (left, right) - } - - #[inline] - fn fold_with(mut self, mut folder: F) -> F - where - F: Folder, - { - // Make sure to modify the iterator in-place so that any remaining - // elements are processed in our Drop impl. - while let Some(item) = self.iter.next() { - folder = folder.consume(unsafe { item.read() }); - if folder.full() { - return folder; - } - } - - // If we processed all elements then we don't need to run the drop. - mem::forget(self); - folder - } -} - -impl Drop for ParDrainProducer { - #[inline] - fn drop(&mut self) { - // Drop all remaining elements - if mem::needs_drop::() { - while let Some(item) = self.iter.next() { - unsafe { - item.drop(); - } - } - } - } -} - -impl RawTable { - /// Returns a parallel iterator over the elements in a `RawTable`. - #[inline] - pub fn par_iter(&self) -> RawParIter { - RawParIter { - iter: unsafe { self.iter().iter }, - } - } - - /// Returns a parallel iterator over the elements in a `RawTable`. - #[inline] - pub fn into_par_iter(self) -> RawIntoParIter { - RawIntoParIter { table: self } - } - - /// Returns a parallel iterator which consumes all elements of a `RawTable` - /// without freeing its memory allocation. - #[inline] - pub fn par_drain(&mut self) -> RawParDrain<'_, T> { - RawParDrain { - table: NonNull::from(self), - marker: PhantomData, - } - } -} diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/set.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/set.rs deleted file mode 100644 index 896be75b0a..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/rayon/set.rs +++ /dev/null @@ -1,646 +0,0 @@ -//! Rayon extensions for `HashSet`. - -use crate::hash_set::HashSet; -use core::hash::{BuildHasher, Hash}; -use rayon::iter::plumbing::UnindexedConsumer; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; - -/// Parallel iterator over elements of a consumed set. -/// -/// This iterator is created by the [`into_par_iter`] method on [`HashSet`] -/// (provided by the [`IntoParallelIterator`] trait). -/// See its documentation for more. -/// -/// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter -/// [`HashSet`]: /hashbrown/struct.HashSet.html -/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html -pub struct IntoParIter { - set: HashSet, -} - -impl ParallelIterator for IntoParIter { - type Item = T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.set - .map - .into_par_iter() - .map(|(k, _)| k) - .drive_unindexed(consumer) - } -} - -/// Parallel draining iterator over entries of a set. -/// -/// This iterator is created by the [`par_drain`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParDrain<'a, T, S> { - set: &'a mut HashSet, -} - -impl ParallelIterator for ParDrain<'_, T, S> { - type Item = T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.set - .map - .par_drain() - .map(|(k, _)| k) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in a set. -/// -/// This iterator is created by the [`par_iter`] method on [`HashSet`] -/// (provided by the [`IntoParallelRefIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter`]: /hashbrown/struct.HashSet.html#method.par_iter -/// [`HashSet`]: /hashbrown/struct.HashSet.html -/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html -pub struct ParIter<'a, T, S> { - set: &'a HashSet, -} - -impl<'a, T: Sync, S: Sync> ParallelIterator for ParIter<'a, T, S> { - type Item = &'a T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.set.map.par_keys().drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the difference of -/// sets. -/// -/// This iterator is created by the [`par_difference`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParDifference<'a, T, S> { - a: &'a HashSet, - b: &'a HashSet, -} - -impl<'a, T, S> ParallelIterator for ParDifference<'a, T, S> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, -{ - type Item = &'a T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.a - .into_par_iter() - .filter(|&x| !self.b.contains(x)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the symmetric -/// difference of sets. -/// -/// This iterator is created by the [`par_symmetric_difference`] method on -/// [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParSymmetricDifference<'a, T, S> { - a: &'a HashSet, - b: &'a HashSet, -} - -impl<'a, T, S> ParallelIterator for ParSymmetricDifference<'a, T, S> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, -{ - type Item = &'a T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.a - .par_difference(self.b) - .chain(self.b.par_difference(self.a)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the intersection of -/// sets. -/// -/// This iterator is created by the [`par_intersection`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParIntersection<'a, T, S> { - a: &'a HashSet, - b: &'a HashSet, -} - -impl<'a, T, S> ParallelIterator for ParIntersection<'a, T, S> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, -{ - type Item = &'a T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.a - .into_par_iter() - .filter(|&x| self.b.contains(x)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the union of sets. -/// -/// This iterator is created by the [`par_union`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParUnion<'a, T, S> { - a: &'a HashSet, - b: &'a HashSet, -} - -impl<'a, T, S> ParallelIterator for ParUnion<'a, T, S> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, -{ - type Item = &'a T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.a - .into_par_iter() - .chain(self.b.par_difference(self.a)) - .drive_unindexed(consumer) - } -} - -impl HashSet -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, -{ - /// Visits (potentially in parallel) the values representing the difference, - /// i.e. the values that are in `self` but not in `other`. - #[inline] - pub fn par_difference<'a>(&'a self, other: &'a Self) -> ParDifference<'a, T, S> { - ParDifference { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the symmetric - /// difference, i.e. the values that are in `self` or in `other` but not in both. - #[inline] - pub fn par_symmetric_difference<'a>( - &'a self, - other: &'a Self, - ) -> ParSymmetricDifference<'a, T, S> { - ParSymmetricDifference { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the - /// intersection, i.e. the values that are both in `self` and `other`. - #[inline] - pub fn par_intersection<'a>(&'a self, other: &'a Self) -> ParIntersection<'a, T, S> { - ParIntersection { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the union, - /// i.e. all the values in `self` or `other`, without duplicates. - #[inline] - pub fn par_union<'a>(&'a self, other: &'a Self) -> ParUnion<'a, T, S> { - ParUnion { a: self, b: other } - } - - /// Returns `true` if `self` has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_disjoint(&self, other: &Self) -> bool { - self.into_par_iter().all(|x| !other.contains(x)) - } - - /// Returns `true` if the set is a subset of another, - /// i.e. `other` contains at least all the values in `self`. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_subset(&self, other: &Self) -> bool { - if self.len() <= other.len() { - self.into_par_iter().all(|x| other.contains(x)) - } else { - false - } - } - - /// Returns `true` if the set is a superset of another, - /// i.e. `self` contains at least all the values in `other`. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_superset(&self, other: &Self) -> bool { - other.par_is_subset(self) - } - - /// Returns `true` if the set is equal to another, - /// i.e. both sets contain the same values. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.par_is_subset(other) - } -} - -impl HashSet -where - T: Eq + Hash + Send, - S: BuildHasher + Send, -{ - /// Consumes (potentially in parallel) all values in an arbitrary order, - /// while preserving the set's allocated memory for reuse. - #[inline] - pub fn par_drain(&mut self) -> ParDrain<'_, T, S> { - ParDrain { set: self } - } -} - -impl IntoParallelIterator for HashSet { - type Item = T; - type Iter = IntoParIter; - - #[inline] - fn into_par_iter(self) -> Self::Iter { - IntoParIter { set: self } - } -} - -impl<'a, T: Sync, S: Sync> IntoParallelIterator for &'a HashSet { - type Item = &'a T; - type Iter = ParIter<'a, T, S>; - - #[inline] - fn into_par_iter(self) -> Self::Iter { - ParIter { set: self } - } -} - -/// Collect values from a parallel iterator into a hashset. -impl FromParallelIterator for HashSet -where - T: Eq + Hash + Send, - S: BuildHasher + Default, -{ - fn from_par_iter

(par_iter: P) -> Self - where - P: IntoParallelIterator, - { - let mut set = HashSet::default(); - set.par_extend(par_iter); - set - } -} - -/// Extend a hash set with items from a parallel iterator. -impl ParallelExtend for HashSet -where - T: Eq + Hash + Send, - S: BuildHasher, -{ - fn par_extend(&mut self, par_iter: I) - where - I: IntoParallelIterator, - { - extend(self, par_iter); - } -} - -/// Extend a hash set with copied items from a parallel iterator. -impl<'a, T, S> ParallelExtend<&'a T> for HashSet -where - T: 'a + Copy + Eq + Hash + Sync, - S: BuildHasher, -{ - fn par_extend(&mut self, par_iter: I) - where - I: IntoParallelIterator, - { - extend(self, par_iter); - } -} - -// This is equal to the normal `HashSet` -- no custom advantage. -fn extend(set: &mut HashSet, par_iter: I) -where - T: Eq + Hash, - S: BuildHasher, - I: IntoParallelIterator, - HashSet: Extend, -{ - let (list, len) = super::helpers::collect(par_iter); - - // Values may be already present or show multiple times in the iterator. - // Reserve the entire length if the set is empty. - // Otherwise reserve half the length (rounded up), so the set - // will only resize twice in the worst case. - let reserve = if set.is_empty() { len } else { (len + 1) / 2 }; - set.reserve(reserve); - for vec in list { - set.extend(vec); - } -} - -#[cfg(test)] -mod test_par_set { - use alloc::vec::Vec; - use core::sync::atomic::{AtomicUsize, Ordering}; - - use rayon::prelude::*; - - use crate::hash_set::HashSet; - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.par_is_disjoint(&ys)); - assert!(!ys.par_is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.par_is_subset(&b)); - assert!(!a.par_is_superset(&b)); - assert!(!b.par_is_subset(&a)); - assert!(!b.par_is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.par_is_subset(&b)); - assert!(!a.par_is_superset(&b)); - assert!(!b.par_is_subset(&a)); - assert!(b.par_is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in 0..32 { - assert!(a.insert(i)); - } - let observed = AtomicUsize::new(0); - a.par_iter().for_each(|k| { - observed.fetch_or(1 << *k, Ordering::Relaxed); - }); - assert_eq!(observed.into_inner(), 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let i = a - .par_intersection(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let expected = [1, 5, 11]; - let i = a - .par_difference(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let expected = [-2, 1, 5, 11, 14, 22]; - let i = a - .par_symmetric_difference(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - let i = a - .par_union(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet<_> = xs.par_iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_par_iter().collect::>(); - assert!(v == ['a', 'b'] || v == ['b', 'a']); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1); - s2.insert(2); - - assert!(!s1.par_eq(&s2)); - - s2.insert(3); - - assert!(s1.par_eq(&s2)); - } - - #[test] - fn test_extend_ref() { - let mut a = HashSet::new(); - a.insert(1); - - a.par_extend(&[2, 3, 4][..]); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - - let mut b = HashSet::new(); - b.insert(5); - b.insert(6); - - a.par_extend(&b); - - assert_eq!(a.len(), 6); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - assert!(a.contains(&5)); - assert!(a.contains(&6)); - } -} diff --git a/vendor/hashbrown-0.4.0/src/external_trait_impls/serde.rs b/vendor/hashbrown-0.4.0/src/external_trait_impls/serde.rs deleted file mode 100644 index 5adac8cd43..0000000000 --- a/vendor/hashbrown-0.4.0/src/external_trait_impls/serde.rs +++ /dev/null @@ -1,200 +0,0 @@ -mod size_hint { - use core::cmp; - - /// This presumably exists to prevent denial of service attacks. - /// - /// Original discussion: https://github.com/serde-rs/serde/issues/1114. - #[inline] - pub(super) fn cautious(hint: Option) -> usize { - cmp::min(hint.unwrap_or(0), 4096) - } -} - -mod map { - use core::fmt; - use core::hash::{BuildHasher, Hash}; - use core::marker::PhantomData; - use serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; - use serde::ser::{Serialize, Serializer}; - - use crate::hash_map::HashMap; - - use super::size_hint; - - impl Serialize for HashMap - where - K: Serialize + Eq + Hash, - V: Serialize, - H: BuildHasher, - { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.collect_map(self) - } - } - - impl<'de, K, V, S> Deserialize<'de> for HashMap - where - K: Deserialize<'de> + Eq + Hash, - V: Deserialize<'de>, - S: BuildHasher + Default, - { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct MapVisitor { - marker: PhantomData>, - } - - impl<'de, K, V, S> Visitor<'de> for MapVisitor - where - K: Deserialize<'de> + Eq + Hash, - V: Deserialize<'de>, - S: BuildHasher + Default, - { - type Value = HashMap; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a map") - } - - #[inline] - fn visit_map(self, mut map: A) -> Result - where - A: MapAccess<'de>, - { - let mut values = HashMap::with_capacity_and_hasher( - size_hint::cautious(map.size_hint()), - S::default(), - ); - - while let Some((key, value)) = map.next_entry()? { - values.insert(key, value); - } - - Ok(values) - } - } - - let visitor = MapVisitor { - marker: PhantomData, - }; - deserializer.deserialize_map(visitor) - } - } -} - -mod set { - use core::fmt; - use core::hash::{BuildHasher, Hash}; - use core::marker::PhantomData; - use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; - use serde::ser::{Serialize, Serializer}; - - use crate::hash_set::HashSet; - - use super::size_hint; - - impl Serialize for HashSet - where - T: Serialize + Eq + Hash, - H: BuildHasher, - { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.collect_seq(self) - } - } - - impl<'de, T, S> Deserialize<'de> for HashSet - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct SeqVisitor { - marker: PhantomData>, - } - - impl<'de, T, S> Visitor<'de> for SeqVisitor - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - type Value = HashSet; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - #[inline] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - let mut values = HashSet::with_capacity_and_hasher( - size_hint::cautious(seq.size_hint()), - S::default(), - ); - - while let Some(value) = seq.next_element()? { - values.insert(value); - } - - Ok(values) - } - } - - let visitor = SeqVisitor { - marker: PhantomData, - }; - deserializer.deserialize_seq(visitor) - } - - fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - struct SeqInPlaceVisitor<'a, T, S>(&'a mut HashSet); - - impl<'a, 'de, T, S> Visitor<'de> for SeqInPlaceVisitor<'a, T, S> - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - #[inline] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - self.0.clear(); - self.0.reserve(size_hint::cautious(seq.size_hint())); - - while let Some(value) = seq.next_element()? { - self.0.insert(value); - } - - Ok(()) - } - } - - deserializer.deserialize_seq(SeqInPlaceVisitor(place)) - } - } -} diff --git a/vendor/hashbrown-0.4.0/src/fx.rs b/vendor/hashbrown-0.4.0/src/fx.rs deleted file mode 100644 index c7eb37624b..0000000000 --- a/vendor/hashbrown-0.4.0/src/fx.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! Fast, non-cryptographic hash used by rustc and Firefox. - -use core::default::Default; -use core::hash::{BuildHasherDefault, Hasher}; -use core::mem::size_of; -use core::ops::BitXor; - -/// Type alias for a `HashBuilder` using the `fx` hash algorithm. -pub type FxHashBuilder = BuildHasherDefault; - -/// A speedy hash algorithm for use within rustc. The hashmap in liballoc -/// by default uses SipHash which isn't quite as speedy as we want. In the -/// compiler we're not really worried about DOS attempts, so we use a fast -/// non-cryptographic hash. -/// -/// This is the same as the algorithm used by Firefox -- which is a homespun -/// one not based on any widely-known algorithm -- though modified to produce -/// 64-bit hash values instead of 32-bit hash values. It consistently -/// out-performs an FNV-based hash within rustc itself -- the collision rate is -/// similar or slightly worse than FNV, but the speed of the hash function -/// itself is much higher because it works on up to 8 bytes at a time. -pub struct FxHasher { - hash: usize, -} - -#[cfg(target_pointer_width = "32")] -const K: usize = 0x9e37_79b9; -#[cfg(target_pointer_width = "64")] -const K: usize = 0x517c_c1b7_2722_0a95; - -impl Default for FxHasher { - #[inline] - fn default() -> Self { - Self { hash: 0 } - } -} - -impl FxHasher { - #[inline] - fn add_to_hash(&mut self, i: usize) { - self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K); - } -} - -impl Hasher for FxHasher { - #[inline] - fn write(&mut self, mut bytes: &[u8]) { - macro_rules! read_bytes { - ($ty:ty, $src:expr) => {{ - assert!(size_of::<$ty>() <= $src.len()); - let mut data: $ty = 0; - unsafe { - $src.as_ptr() - .copy_to_nonoverlapping(&mut data as *mut $ty as *mut u8, size_of::<$ty>()); - } - data - }}; - } - - let mut hash = Self { hash: self.hash }; - assert!(size_of::() <= 8); - while bytes.len() >= size_of::() { - hash.add_to_hash(read_bytes!(usize, bytes) as usize); - bytes = &bytes[size_of::()..]; - } - if (size_of::() > 4) && (bytes.len() >= 4) { - hash.add_to_hash(read_bytes!(u32, bytes) as usize); - bytes = &bytes[4..]; - } - if (size_of::() > 2) && bytes.len() >= 2 { - hash.add_to_hash(read_bytes!(u16, bytes) as usize); - bytes = &bytes[2..]; - } - if (size_of::() > 1) && !bytes.is_empty() { - hash.add_to_hash(bytes[0] as usize); - } - self.hash = hash.hash; - } - - #[inline] - fn write_u8(&mut self, i: u8) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_u16(&mut self, i: u16) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_u32(&mut self, i: u32) { - self.add_to_hash(i as usize); - } - - #[cfg(target_pointer_width = "32")] - #[inline] - #[allow(clippy::cast_possible_truncation)] - fn write_u64(&mut self, i: u64) { - self.add_to_hash(i as usize); - self.add_to_hash((i >> 32) as usize); - } - - #[cfg(target_pointer_width = "64")] - #[inline] - #[allow(clippy::cast_possible_truncation)] - fn write_u64(&mut self, i: u64) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_usize(&mut self, i: usize) { - self.add_to_hash(i); - } - - #[inline] - fn finish(&self) -> u64 { - self.hash as u64 - } -} diff --git a/vendor/hashbrown-0.4.0/src/lib.rs b/vendor/hashbrown-0.4.0/src/lib.rs deleted file mode 100644 index 1fe78e6448..0000000000 --- a/vendor/hashbrown-0.4.0/src/lib.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! This crate is a Rust port of Google's high-performance [SwissTable] hash -//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap` -//! and `HashSet` types. -//! -//! The original C++ version of [SwissTable] can be found [here], and this -//! [CppCon talk] gives an overview of how the algorithm works. -//! -//! [SwissTable]: https://abseil.io/blog/20180927-swisstables -//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h -//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4 - -#![no_std] -#![cfg_attr( - feature = "nightly", - feature( - alloc_layout_extra, - allocator_api, - ptr_offset_from, - test, - core_intrinsics, - dropck_eyepatch - ) -)] -#![warn(missing_docs)] -#![allow(clippy::module_name_repetitions)] -#![warn(rust_2018_idioms)] - -#[cfg(test)] -#[macro_use] -extern crate std; - -#[cfg(feature = "nightly")] -#[cfg_attr(test, macro_use)] -extern crate alloc; -#[cfg(not(feature = "nightly"))] -extern crate std as alloc; - -#[macro_use] -mod macros; - -mod external_trait_impls; -mod fx; -mod map; -mod raw; -#[cfg(feature = "rustc-dep-of-std")] -mod rustc_entry; -mod scopeguard; -mod set; - -pub mod hash_map { - //! A hash map implemented with quadratic probing and SIMD lookup. - pub use crate::map::*; - - #[cfg(feature = "rustc-dep-of-std")] - pub use crate::rustc_entry::*; - - #[cfg(feature = "rayon")] - /// [rayon]-based parallel iterator types for hash maps. - /// You will rarely need to interact with it directly unless you have need - /// to name one of the iterator types. - /// - /// [rayon]: https://docs.rs/rayon/1.0/rayon - pub mod rayon { - pub use crate::external_trait_impls::rayon::map::*; - } -} -pub mod hash_set { - //! A hash set implemented as a `HashMap` where the value is `()`. - pub use crate::set::*; - - #[cfg(feature = "rayon")] - /// [rayon]-based parallel iterator types for hash sets. - /// You will rarely need to interact with it directly unless you have need - /// to name one of the iterator types. - /// - /// [rayon]: https://docs.rs/rayon/1.0/rayon - pub mod rayon { - pub use crate::external_trait_impls::rayon::set::*; - } -} - -pub use crate::map::HashMap; -pub use crate::set::HashSet; - -/// Augments `AllocErr` with a `CapacityOverflow` variant. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum CollectionAllocErr { - /// Error due to the computed capacity exceeding the collection's maximum - /// (usually `isize::MAX` bytes). - CapacityOverflow, - /// Error due to the allocator (see the `AllocErr` type's docs). - AllocErr, -} diff --git a/vendor/hashbrown-0.4.0/src/macros.rs b/vendor/hashbrown-0.4.0/src/macros.rs deleted file mode 100644 index e743094768..0000000000 --- a/vendor/hashbrown-0.4.0/src/macros.rs +++ /dev/null @@ -1,54 +0,0 @@ -// See the cfg-if crate. -macro_rules! cfg_if { - // match if/else chains with a final `else` - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - cfg_if! { - @__items - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } - }; - - // match if/else chains lacking a final `else` - ( - if #[cfg($($i_met:meta),*)] { $($i_it:item)* } - $( - else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } - )* - ) => { - cfg_if! { - @__items - () ; - ( ($($i_met),*) ($($i_it)*) ), - $( ( ($($e_met),*) ($($e_it)*) ), )* - ( () () ), - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the negated cfgs in a list at the beginning and after the - // semicolon is all the remaining items - (@__items ($($not:meta,)*) ; ) => {}; - (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - // Emit all items within one block, applying an approprate #[cfg]. The - // #[cfg] will require all `$m` matchers specified and must also negate - // all previous matchers. - cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$m` matchers to the list of `$not` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } - }; - - // Internal macro to Apply a cfg attribute to a list of items - (@__apply $m:meta, $($it:item)*) => { - $(#[$m] $it)* - }; -} diff --git a/vendor/hashbrown-0.4.0/src/map.rs b/vendor/hashbrown-0.4.0/src/map.rs deleted file mode 100644 index ad5602a997..0000000000 --- a/vendor/hashbrown-0.4.0/src/map.rs +++ /dev/null @@ -1,3566 +0,0 @@ -use crate::raw::{Bucket, RawDrain, RawIntoIter, RawIter, RawTable}; -use crate::CollectionAllocErr; -use core::borrow::Borrow; -use core::fmt::{self, Debug}; -use core::hash::{BuildHasher, Hash, Hasher}; -use core::iter::{FromIterator, FusedIterator}; -use core::marker::PhantomData; -use core::mem; -use core::ops::Index; - -pub use crate::fx::FxHashBuilder as DefaultHashBuilder; - -/// A hash map implemented with quadratic probing and SIMD lookup. -/// -/// The default hashing algorithm is currently `fx`, though this is -/// subject to change at any point in the future. This hash function is very -/// fast for all types of keys, but this algorithm will typically *not* protect -/// against attacks such as HashDoS. -/// -/// The hashing algorithm can be replaced on a per-`HashMap` basis using the -/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many -/// alternative algorithms are available on crates.io, such as the [`fnv`] crate. -/// -/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although -/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`. -/// If you implement these yourself, it is important that the following -/// property holds: -/// -/// ```text -/// k1 == k2 -> hash(k1) == hash(k2) -/// ``` -/// -/// In other words, if two keys are equal, their hashes must be equal. -/// -/// It is a logic error for a key to be modified in such a way that the key's -/// hash, as determined by the [`Hash`] trait, or its equality, as determined by -/// the [`Eq`] trait, changes while it is in the map. This is normally only -/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// -/// It is also a logic error for the [`Hash`] implementation of a key to panic. -/// This is generally only possible if the trait is implemented manually. If a -/// panic does occur then the contents of the `HashMap` may become corrupted and -/// some items may be dropped from the table. -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashMap` in this example). -/// let mut book_reviews = HashMap::new(); -/// -/// // Review some books. -/// book_reviews.insert( -/// "Adventures of Huckleberry Finn".to_string(), -/// "My favorite book.".to_string(), -/// ); -/// book_reviews.insert( -/// "Grimms' Fairy Tales".to_string(), -/// "Masterpiece.".to_string(), -/// ); -/// book_reviews.insert( -/// "Pride and Prejudice".to_string(), -/// "Very enjoyable.".to_string(), -/// ); -/// book_reviews.insert( -/// "The Adventures of Sherlock Holmes".to_string(), -/// "Eye lyked it alot.".to_string(), -/// ); -/// -/// // Check for a specific one. -/// // When collections store owned values (String), they can still be -/// // queried using references (&str). -/// if !book_reviews.contains_key("Les Misérables") { -/// println!("We've got {} reviews, but Les Misérables ain't one.", -/// book_reviews.len()); -/// } -/// -/// // oops, this review has a lot of spelling mistakes, let's delete it. -/// book_reviews.remove("The Adventures of Sherlock Holmes"); -/// -/// // Look up the values associated with some keys. -/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; -/// for &book in &to_find { -/// match book_reviews.get(book) { -/// Some(review) => println!("{}: {}", book, review), -/// None => println!("{} is unreviewed.", book) -/// } -/// } -/// -/// // Look up the value for a key (will panic if the key is not found). -/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]); -/// -/// // Iterate over everything. -/// for (book, review) in &book_reviews { -/// println!("{}: \"{}\"", book, review); -/// } -/// ``` -/// -/// `HashMap` also implements an [`Entry API`](#method.entry), which allows -/// for more complex methods of getting, setting, updating and removing keys and -/// their values: -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// // type inference lets us omit an explicit type signature (which -/// // would be `HashMap<&str, u8>` in this example). -/// let mut player_stats = HashMap::new(); -/// -/// fn random_stat_buff() -> u8 { -/// // could actually return some random value here - let's just return -/// // some fixed value for now -/// 42 -/// } -/// -/// // insert a key only if it doesn't already exist -/// player_stats.entry("health").or_insert(100); -/// -/// // insert a key using a function that provides a new value only if it -/// // doesn't already exist -/// player_stats.entry("defence").or_insert_with(random_stat_buff); -/// -/// // update a key, guarding against the key possibly not being set -/// let stat = player_stats.entry("attack").or_insert(100); -/// *stat += random_stat_buff(); -/// ``` -/// -/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. -/// We must also derive [`PartialEq`]. -/// -/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html -/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html -/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html -/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html -/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html -/// [`default`]: #method.default -/// [`with_hasher`]: #method.with_hasher -/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher -/// [`fnv`]: https://crates.io/crates/fnv -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking { -/// name: String, -/// country: String, -/// } -/// -/// impl Viking { -/// /// Creates a new Viking. -/// fn new(name: &str, country: &str) -> Viking { -/// Viking { name: name.to_string(), country: country.to_string() } -/// } -/// } -/// -/// // Use a HashMap to store the vikings' health points. -/// let mut vikings = HashMap::new(); -/// -/// vikings.insert(Viking::new("Einar", "Norway"), 25); -/// vikings.insert(Viking::new("Olaf", "Denmark"), 24); -/// vikings.insert(Viking::new("Harald", "Iceland"), 12); -/// -/// // Use derived implementation to print the status of the vikings. -/// for (viking, health) in &vikings { -/// println!("{:?} has {} hp", viking, health); -/// } -/// ``` -/// -/// A `HashMap` with fixed list of elements can be initialized from an array: -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// fn main() { -/// let timber_resources: HashMap<&str, i32> = -/// [("Norway", 100), -/// ("Denmark", 50), -/// ("Iceland", 10)] -/// .iter().cloned().collect(); -/// // use the values stored in map -/// } -/// ``` - -#[derive(Clone)] -pub struct HashMap { - pub(crate) hash_builder: S, - pub(crate) table: RawTable<(K, V)>, -} - -#[inline] -pub(crate) fn make_hash(hash_builder: &impl BuildHasher, val: &K) -> u64 { - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() -} - -impl HashMap { - /// Creates an empty `HashMap`. - /// - /// The hash map is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// ``` - #[inline] - pub fn new() -> Self { - Self::default() - } - - /// Creates an empty `HashMap` with the specified capacity. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10); - /// ``` - #[inline] - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default()) - } -} - -impl HashMap { - /// Creates an empty `HashMap` which will use the given hash builder to hash - /// keys. - /// - /// The created map has the default initial capacity. - /// - /// Warning: `hash_builder` is normally randomly generated, and - /// is designed to allow HashMaps to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_hasher(s); - /// map.insert(1, 2); - /// ``` - #[inline] - pub fn with_hasher(hash_builder: S) -> Self { - Self { - hash_builder, - table: RawTable::new(), - } - } - - /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` - /// to hash the keys. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// Warning: `hash_builder` is normally randomly generated, and - /// is designed to allow HashMaps to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_capacity_and_hasher(10, s); - /// map.insert(1, 2); - /// ``` - #[inline] - pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { - Self { - hash_builder, - table: RawTable::with_capacity(capacity), - } - } - - /// Returns a reference to the map's [`BuildHasher`]. - /// - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let hasher = DefaultHashBuilder::default(); - /// let map: HashMap = HashMap::with_hasher(hasher); - /// let hasher: &DefaultHashBuilder = map.hasher(); - /// ``` - #[inline] - pub fn hasher(&self) -> &S { - &self.hash_builder - } - - /// Returns the number of elements the map can hold without reallocating. - /// - /// This number is a lower bound; the `HashMap` might be able to hold - /// more, but is guaranteed to be able to hold at least this many. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let map: HashMap = HashMap::with_capacity(100); - /// assert!(map.capacity() >= 100); - /// ``` - #[inline] - pub fn capacity(&self) -> usize { - self.table.capacity() - } - - /// An iterator visiting all keys in arbitrary order. - /// The iterator element type is `&'a K`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for key in map.keys() { - /// println!("{}", key); - /// } - /// ``` - #[inline] - pub fn keys(&self) -> Keys<'_, K, V> { - Keys { inner: self.iter() } - } - - /// An iterator visiting all values in arbitrary order. - /// The iterator element type is `&'a V`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values() { - /// println!("{}", val); - /// } - /// ``` - #[inline] - pub fn values(&self) -> Values<'_, K, V> { - Values { inner: self.iter() } - } - - /// An iterator visiting all values mutably in arbitrary order. - /// The iterator element type is `&'a mut V`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values_mut() { - /// *val = *val + 10; - /// } - /// - /// for val in map.values() { - /// println!("{}", val); - /// } - /// ``` - #[inline] - pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { - ValuesMut { - inner: self.iter_mut(), - } - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// The iterator element type is `(&'a K, &'a V)`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - #[inline] - pub fn iter(&self) -> Iter<'_, K, V> { - // Here we tie the lifetime of self to the iter. - unsafe { - Iter { - inner: self.table.iter(), - marker: PhantomData, - } - } - } - - /// An iterator visiting all key-value pairs in arbitrary order, - /// with mutable references to the values. - /// The iterator element type is `(&'a K, &'a mut V)`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Update all values - /// for (_, val) in map.iter_mut() { - /// *val *= 2; - /// } - /// - /// for (key, val) in &map { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - #[inline] - pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { - // Here we tie the lifetime of self to the iter. - unsafe { - IterMut { - inner: self.table.iter(), - marker: PhantomData, - } - } - } - - #[cfg(test)] - #[inline] - fn raw_capacity(&self) -> usize { - self.table.buckets() - } - - /// Returns the number of elements in the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> usize { - self.table.len() - } - - /// Returns `true` if the map contains no elements. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Clears the map, returning all key-value pairs as an iterator. Keeps the - /// allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// - /// for (k, v) in a.drain().take(1) { - /// assert!(k == 1 || k == 2); - /// assert!(v == "a" || v == "b"); - /// } - /// - /// assert!(a.is_empty()); - /// ``` - #[inline] - pub fn drain(&mut self) -> Drain<'_, K, V> { - // Here we tie the lifetime of self to the iter. - unsafe { - Drain { - inner: self.table.drain(), - } - } - } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { - self.table.clear(); - } -} - -impl HashMap -where - K: Eq + Hash, - S: BuildHasher, -{ - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new allocation size overflows [`usize`]. - /// - /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// map.reserve(10); - /// ``` - #[inline] - pub fn reserve(&mut self, additional: usize) { - let hash_builder = &self.hash_builder; - self.table - .reserve(additional, |x| make_hash(hash_builder, &x.0)); - } - - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, isize> = HashMap::new(); - /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); - /// ``` - #[inline] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - let hash_builder = &self.hash_builder; - self.table - .try_reserve(additional, |x| make_hash(hash_builder, &x.0)) - } - - /// Shrinks the capacity of the map as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap = HashMap::with_capacity(100); - /// map.insert(1, 2); - /// map.insert(3, 4); - /// assert!(map.capacity() >= 100); - /// map.shrink_to_fit(); - /// assert!(map.capacity() >= 2); - /// ``` - #[inline] - pub fn shrink_to_fit(&mut self) { - let hash_builder = &self.hash_builder; - self.table.shrink_to(0, |x| make_hash(hash_builder, &x.0)); - } - - /// Shrinks the capacity of the map with a lower limit. It will drop - /// down no lower than the supplied limit while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// This function does nothing if the current capacity is smaller than the - /// supplied minimum capacity. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap = HashMap::with_capacity(100); - /// map.insert(1, 2); - /// map.insert(3, 4); - /// assert!(map.capacity() >= 100); - /// map.shrink_to(10); - /// assert!(map.capacity() >= 10); - /// map.shrink_to(0); - /// assert!(map.capacity() >= 2); - /// map.shrink_to(10); - /// assert!(map.capacity() >= 2); - /// ``` - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - let hash_builder = &self.hash_builder; - self.table - .shrink_to(min_capacity, |x| make_hash(hash_builder, &x.0)); - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut letters = HashMap::new(); - /// - /// for ch in "a short treatise on fungi".chars() { - /// let counter = letters.entry(ch).or_insert(0); - /// *counter += 1; - /// } - /// - /// assert_eq!(letters[&'s'], 2); - /// assert_eq!(letters[&'t'], 3); - /// assert_eq!(letters[&'u'], 1); - /// assert_eq!(letters.get(&'y'), None); - /// ``` - #[inline] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { - let hash = make_hash(&self.hash_builder, &key); - if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { - Entry::Occupied(OccupiedEntry { - key: Some(key), - elem, - table: self, - }) - } else { - Entry::Vacant(VacantEntry { - hash, - key, - table: self, - }) - } - } - - /// Returns a reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.get(&1), Some(&"a")); - /// assert_eq!(map.get(&2), None); - /// ``` - #[inline] - pub fn get(&self, k: &Q) -> Option<&V> - where - K: Borrow, - Q: Hash + Eq, - { - self.get_key_value(k).map(|(_, v)| v) - } - - /// Returns the key-value pair corresponding to the supplied key. - /// - /// The supplied key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); - /// assert_eq!(map.get_key_value(&2), None); - /// ``` - #[inline] - pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> - where - K: Borrow, - Q: Hash + Eq, - { - let hash = make_hash(&self.hash_builder, k); - self.table - .find(hash, |x| k.eq(x.0.borrow())) - .map(|item| unsafe { - let &(ref key, ref value) = item.as_ref(); - (key, value) - }) - } - - /// Returns `true` if the map contains a value for the specified key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[inline] - pub fn contains_key(&self, k: &Q) -> bool - where - K: Borrow, - Q: Hash + Eq, - { - self.get(k).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// if let Some(x) = map.get_mut(&1) { - /// *x = "b"; - /// } - /// assert_eq!(map[&1], "b"); - /// ``` - #[inline] - pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> - where - K: Borrow, - Q: Hash + Eq, - { - let hash = make_hash(&self.hash_builder, k); - self.table - .find(hash, |x| k.eq(x.0.borrow())) - .map(|item| unsafe { &mut item.as_mut().1 }) - } - - /// Inserts a key-value pair into the map. - /// - /// If the map did not have this key present, [`None`] is returned. - /// - /// If the map did have this key present, the value is updated, and the old - /// value is returned. The key is not updated, though; this matters for - /// types that can be `==` without being identical. See the [module-level - /// documentation] for more. - /// - /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - /// [module-level documentation]: index.html#insert-and-complex-keys - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.insert(37, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.insert(37, "c"), Some("b")); - /// assert_eq!(map[&37], "c"); - /// ``` - #[inline] - pub fn insert(&mut self, k: K, v: V) -> Option { - unsafe { - let hash = make_hash(&self.hash_builder, &k); - if let Some(item) = self.table.find(hash, |x| k.eq(&x.0)) { - Some(mem::replace(&mut item.as_mut().1, v)) - } else { - let hash_builder = &self.hash_builder; - self.table - .insert(hash, (k, v), |x| make_hash(hash_builder, &x.0)); - None - } - } - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), Some("a")); - /// assert_eq!(map.remove(&1), None); - /// ``` - #[inline] - pub fn remove(&mut self, k: &Q) -> Option - where - K: Borrow, - Q: Hash + Eq, - { - self.remove_entry(k).map(|(_, v)| v) - } - - /// Removes a key from the map, returning the stored key and value if the - /// key was previously in the map. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// # fn main() { - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); - /// assert_eq!(map.remove(&1), None); - /// # } - /// ``` - #[inline] - pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> - where - K: Borrow, - Q: Hash + Eq, - { - unsafe { - let hash = make_hash(&self.hash_builder, &k); - if let Some(item) = self.table.find(hash, |x| k.eq(x.0.borrow())) { - self.table.erase_no_drop(&item); - Some(item.read()) - } else { - None - } - } - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap = (0..8).map(|x|(x, x*10)).collect(); - /// map.retain(|&k, _| k % 2 == 0); - /// assert_eq!(map.len(), 4); - /// ``` - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&K, &mut V) -> bool, - { - // Here we only use `iter` as a temporary, preventing use-after-free - unsafe { - for item in self.table.iter() { - let &mut (ref key, ref mut value) = item.as_mut(); - if !f(key, value) { - // Erase the element from the table first since drop might panic. - self.table.erase_no_drop(&item); - item.drop(); - } - } - } - } -} - -impl HashMap -where - S: BuildHasher, -{ - /// Creates a raw entry builder for the HashMap. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. After this, insertions into a vacant entry - /// still require an owned key to be provided. - /// - /// Raw entries are useful for such exotic situations as: - /// - /// * Hash memoization - /// * Deferring the creation of an owned key until it is known to be required - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Because raw entries provide much more low-level control, it's much easier - /// to put the HashMap into an inconsistent state which, while memory-safe, - /// will cause the map to produce seemingly random results. Higher-level and - /// more foolproof APIs like `entry` should be preferred when possible. - /// - /// In particular, the hash used to initialized the raw entry must still be - /// consistent with the hash of the key that is ultimately stored in the entry. - /// This is because implementations of HashMap may need to recompute hashes - /// when resizing, at which point only the keys are available. - /// - /// Raw entries give mutable access to the keys. This must not be used - /// to modify how the key would compare or hash, as the map will not re-evaluate - /// where the key should go, meaning the keys may become "lost" if their - /// location does not reflect their state. For instance, if you change a key - /// so that the map now contains keys which compare equal, search may start - /// acting erratically, with two keys randomly masking each other. Implementations - /// are free to assume this doesn't happen (within the limits of memory-safety). - #[inline] - pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { - RawEntryBuilderMut { map: self } - } - - /// Creates a raw immutable entry builder for the HashMap. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. - /// - /// This is useful for - /// * Hash memoization - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Unless you are in such a situation, higher-level and more foolproof APIs like - /// `get` should be preferred. - /// - /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - #[inline] - pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { - RawEntryBuilder { map: self } - } -} - -impl PartialEq for HashMap -where - K: Eq + Hash, - V: PartialEq, - S: BuildHasher, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - self.iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) - } -} - -impl Eq for HashMap -where - K: Eq + Hash, - V: Eq, - S: BuildHasher, -{ -} - -impl Debug for HashMap -where - K: Debug, - V: Debug, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_map().entries(self.iter()).finish() - } -} - -impl Default for HashMap -where - S: BuildHasher + Default, -{ - /// Creates an empty `HashMap`, with the `Default` value for the hasher. - #[inline] - fn default() -> Self { - Self::with_hasher(Default::default()) - } -} - -impl Index<&Q> for HashMap -where - K: Eq + Hash + Borrow, - Q: Eq + Hash, - S: BuildHasher, -{ - type Output = V; - - /// Returns a reference to the value corresponding to the supplied key. - /// - /// # Panics - /// - /// Panics if the key is not present in the `HashMap`. - #[inline] - fn index(&self, key: &Q) -> &V { - self.get(key).expect("no entry found for key") - } -} - -/// An iterator over the entries of a `HashMap`. -/// -/// This `struct` is created by the [`iter`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`iter`]: struct.HashMap.html#method.iter -/// [`HashMap`]: struct.HashMap.html -pub struct Iter<'a, K, V> { - inner: RawIter<(K, V)>, - marker: PhantomData<(&'a K, &'a V)>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl Clone for Iter<'_, K, V> { - #[inline] - fn clone(&self) -> Self { - Iter { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -impl fmt::Debug for Iter<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// A mutable iterator over the entries of a `HashMap`. -/// -/// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`iter_mut`]: struct.HashMap.html#method.iter_mut -/// [`HashMap`]: struct.HashMap.html -pub struct IterMut<'a, K, V> { - inner: RawIter<(K, V)>, - // To ensure invariance with respect to V - marker: PhantomData<(&'a K, &'a mut V)>, -} - -// We override the default Send impl which has K: Sync instead of K: Send. Both -// are correct, but this one is more general since it allows keys which -// implement Send but not Sync. -unsafe impl Send for IterMut<'_, K, V> {} - -impl IterMut<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[inline] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -/// An owning iterator over the entries of a `HashMap`. -/// -/// This `struct` is created by the [`into_iter`] method on [`HashMap`][`HashMap`] -/// (provided by the `IntoIterator` trait). See its documentation for more. -/// -/// [`into_iter`]: struct.HashMap.html#method.into_iter -/// [`HashMap`]: struct.HashMap.html -pub struct IntoIter { - inner: RawIntoIter<(K, V)>, -} - -impl IntoIter { - /// Returns a iterator of references over the remaining items. - #[inline] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.iter(), - marker: PhantomData, - } - } -} - -/// An iterator over the keys of a `HashMap`. -/// -/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`keys`]: struct.HashMap.html#method.keys -/// [`HashMap`]: struct.HashMap.html -pub struct Keys<'a, K, V> { - inner: Iter<'a, K, V>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl Clone for Keys<'_, K, V> { - #[inline] - fn clone(&self) -> Self { - Keys { - inner: self.inner.clone(), - } - } -} - -impl fmt::Debug for Keys<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// An iterator over the values of a `HashMap`. -/// -/// This `struct` is created by the [`values`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`values`]: struct.HashMap.html#method.values -/// [`HashMap`]: struct.HashMap.html -pub struct Values<'a, K, V> { - inner: Iter<'a, K, V>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl Clone for Values<'_, K, V> { - #[inline] - fn clone(&self) -> Self { - Values { - inner: self.inner.clone(), - } - } -} - -impl fmt::Debug for Values<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// A draining iterator over the entries of a `HashMap`. -/// -/// This `struct` is created by the [`drain`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`drain`]: struct.HashMap.html#method.drain -/// [`HashMap`]: struct.HashMap.html -pub struct Drain<'a, K, V> { - inner: RawDrain<'a, (K, V)>, -} - -impl Drain<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[inline] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.iter(), - marker: PhantomData, - } - } -} - -/// A mutable iterator over the values of a `HashMap`. -/// -/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`values_mut`]: struct.HashMap.html#method.values_mut -/// [`HashMap`]: struct.HashMap.html -pub struct ValuesMut<'a, K, V> { - inner: IterMut<'a, K, V>, -} - -/// A builder for computing where in a [`HashMap`] a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry_mut`] docs for usage examples. -/// -/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -pub struct RawEntryBuilderMut<'a, K, V, S> { - map: &'a mut HashMap, -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This is a lower-level version of [`Entry`]. -/// -/// This `enum` is constructed from the [`raw_entry`] method on [`HashMap`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`Entry`]: enum.Entry.html -/// [`raw_entry`]: struct.HashMap.html#method.raw_entry -pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { - /// An occupied entry. - Occupied(RawOccupiedEntryMut<'a, K, V>), - /// A vacant entry. - Vacant(RawVacantEntryMut<'a, K, V, S>), -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -/// -/// [`RawEntryMut`]: enum.RawEntryMut.html -pub struct RawOccupiedEntryMut<'a, K, V> { - elem: Bucket<(K, V)>, - table: &'a mut RawTable<(K, V)>, -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -/// -/// [`RawEntryMut`]: enum.RawEntryMut.html -pub struct RawVacantEntryMut<'a, K, V, S> { - table: &'a mut RawTable<(K, V)>, - hash_builder: &'a S, -} - -/// A builder for computing where in a [`HashMap`] a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry`] docs for usage examples. -/// -/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -pub struct RawEntryBuilder<'a, K, V, S> { - map: &'a HashMap, -} - -impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> -where - S: BuildHasher, -{ - /// Creates a `RawEntryMut` from the given key. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> - where - K: Borrow, - Q: Hash + Eq, - { - let mut hasher = self.map.hash_builder.build_hasher(); - k.hash(&mut hasher); - self.from_key_hashed_nocheck(hasher.finish(), k) - } - - /// Creates a `RawEntryMut` from the given key and its hash. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> - where - K: Borrow, - Q: Eq, - { - self.from_hash(hash, |q| q.borrow().eq(k)) - } -} - -impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> -where - S: BuildHasher, -{ - /// Creates a `RawEntryMut` from the given hash. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> - where - for<'b> F: FnMut(&'b K) -> bool, - { - self.search(hash, is_match) - } - - #[inline] - fn search(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S> - where - for<'b> F: FnMut(&'b K) -> bool, - { - match self.map.table.find(hash, |(k, _)| is_match(k)) { - Some(elem) => RawEntryMut::Occupied(RawOccupiedEntryMut { - elem, - table: &mut self.map.table, - }), - None => RawEntryMut::Vacant(RawVacantEntryMut { - table: &mut self.map.table, - hash_builder: &self.map.hash_builder, - }), - } - } -} - -impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> -where - S: BuildHasher, -{ - /// Access an entry by key. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> - where - K: Borrow, - Q: Hash + Eq, - { - let mut hasher = self.map.hash_builder.build_hasher(); - k.hash(&mut hasher); - self.from_key_hashed_nocheck(hasher.finish(), k) - } - - /// Access an entry by a key and its hash. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> - where - K: Borrow, - Q: Hash + Eq, - { - self.from_hash(hash, |q| q.borrow().eq(k)) - } - - #[inline] - fn search(self, hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)> - where - F: FnMut(&K) -> bool, - { - self.map - .table - .find(hash, |(k, _)| is_match(k)) - .map(|item| unsafe { - let &(ref key, ref value) = item.as_ref(); - (key, value) - }) - } - - /// Access an entry by hash. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> - where - F: FnMut(&K) -> bool, - { - self.search(hash, is_match) - } -} - -impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[inline] - pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| { - /// ("poneyland", "hoho".to_string()) - /// }); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[inline] - pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) - where - F: FnOnce() -> (K, V), - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => { - let (k, v) = default(); - entry.insert(k, v) - } - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 0); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[inline] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut K, &mut V), - { - match self { - RawEntryMut::Occupied(mut entry) => { - { - let (k, v) = entry.get_key_value_mut(); - f(k, v); - } - RawEntryMut::Occupied(entry) - } - RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry), - } - } -} - -impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { - /// Gets a reference to the key in the entry. - #[inline] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Gets a mutable reference to the key in the entry. - #[inline] - pub fn key_mut(&mut self) -> &mut K { - unsafe { &mut self.elem.as_mut().0 } - } - - /// Converts the entry into a mutable reference to the key in the entry - /// with a lifetime bound to the map itself. - #[inline] - pub fn into_key(self) -> &'a mut K { - unsafe { &mut self.elem.as_mut().0 } - } - - /// Gets a reference to the value in the entry. - #[inline] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - #[inline] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Gets a mutable reference to the value in the entry. - #[inline] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Gets a reference to the key and value in the entry. - #[inline] - pub fn get_key_value(&mut self) -> (&K, &V) { - unsafe { - let &(ref key, ref value) = self.elem.as_ref(); - (key, value) - } - } - - /// Gets a mutable reference to the key and value in the entry. - #[inline] - pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { - unsafe { - let &mut (ref mut key, ref mut value) = self.elem.as_mut(); - (key, value) - } - } - - /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry - /// with a lifetime bound to the map itself. - #[inline] - pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { - unsafe { - let &mut (ref mut key, ref mut value) = self.elem.as_mut(); - (key, value) - } - } - - /// Sets the value of the entry, and returns the entry's old value. - #[inline] - pub fn insert(&mut self, value: V) -> V { - mem::replace(self.get_mut(), value) - } - - /// Sets the value of the entry, and returns the entry's old value. - #[inline] - pub fn insert_key(&mut self, key: K) -> K { - mem::replace(self.key_mut(), key) - } - - /// Takes the value out of the entry, and returns it. - #[inline] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Take the ownership of the key and value from the map. - #[inline] - pub fn remove_entry(self) -> (K, V) { - unsafe { - self.table.erase_no_drop(&self.elem); - self.elem.read() - } - } -} - -impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - #[inline] - pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - let mut hasher = self.hash_builder.build_hasher(); - key.hash(&mut hasher); - self.insert_hashed_nocheck(hasher.finish(), key, value) - } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - #[inline] - #[allow(clippy::shadow_unrelated)] - pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - let hash_builder = self.hash_builder; - self.insert_with_hasher(hash, key, value, |k| make_hash(hash_builder, k)) - } - - /// Set the value of an entry with a custom hasher function. - #[inline] - pub fn insert_with_hasher( - self, - hash: u64, - key: K, - value: V, - hasher: H, - ) -> (&'a mut K, &'a mut V) - where - S: BuildHasher, - H: Fn(&K) -> u64, - { - unsafe { - let elem = self.table.insert(hash, (key, value), |x| hasher(&x.0)); - let &mut (ref mut k, ref mut v) = elem.as_mut(); - (k, v) - } - } -} - -impl Debug for RawEntryBuilderMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() - } -} - -impl Debug for RawEntryMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), - RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(), - } - } -} - -impl Debug for RawOccupiedEntryMut<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawOccupiedEntryMut") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -impl Debug for RawVacantEntryMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawVacantEntryMut").finish() - } -} - -impl Debug for RawEntryBuilder<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This `enum` is constructed from the [`entry`] method on [`HashMap`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`entry`]: struct.HashMap.html#method.entry -pub enum Entry<'a, K: 'a, V: 'a, S: 'a> { - /// An occupied entry. - Occupied(OccupiedEntry<'a, K, V, S>), - - /// A vacant entry. - Vacant(VacantEntry<'a, K, V, S>), -} - -impl Debug for Entry<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), - Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), - } - } -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -pub struct OccupiedEntry<'a, K, V, S> { - key: Option, - elem: Bucket<(K, V)>, - table: &'a mut HashMap, -} - -unsafe impl Send for OccupiedEntry<'_, K, V, S> -where - K: Send, - V: Send, - S: Send, -{ -} -unsafe impl Sync for OccupiedEntry<'_, K, V, S> -where - K: Sync, - V: Sync, - S: Sync, -{ -} - -impl Debug for OccupiedEntry<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -pub struct VacantEntry<'a, K, V, S> { - hash: u64, - key: K, - table: &'a mut HashMap, -} - -impl Debug for VacantEntry<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntry").field(self.key()).finish() - } -} - -impl<'a, K, V, S> IntoIterator for &'a HashMap { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - - #[inline] - fn into_iter(self) -> Iter<'a, K, V> { - self.iter() - } -} - -impl<'a, K, V, S> IntoIterator for &'a mut HashMap { - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - - #[inline] - fn into_iter(self) -> IterMut<'a, K, V> { - self.iter_mut() - } -} - -impl IntoIterator for HashMap { - type Item = (K, V); - type IntoIter = IntoIter; - - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Not possible with .iter() - /// let vec: Vec<(&str, i32)> = map.into_iter().collect(); - /// ``` - #[inline] - fn into_iter(self) -> IntoIter { - IntoIter { - inner: self.table.into_iter(), - } - } -} - -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - #[inline] - fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.inner.next().map(|x| unsafe { - let r = x.as_ref(); - (&r.0, &r.1) - }) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for Iter<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} - -impl FusedIterator for Iter<'_, K, V> {} - -impl<'a, K, V> Iterator for IterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - - #[inline] - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - self.inner.next().map(|x| unsafe { - let r = x.as_mut(); - (&r.0, &mut r.1) - }) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for IterMut<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for IterMut<'_, K, V> {} - -impl fmt::Debug for IterMut<'_, K, V> -where - K: fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl Iterator for IntoIter { - type Item = (K, V); - - #[inline] - fn next(&mut self) -> Option<(K, V)> { - self.inner.next() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for IntoIter { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for IntoIter {} - -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<'a, K, V> Iterator for Keys<'a, K, V> { - type Item = &'a K; - - #[inline] - fn next(&mut self) -> Option<(&'a K)> { - self.inner.next().map(|(k, _)| k) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for Keys<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for Keys<'_, K, V> {} - -impl<'a, K, V> Iterator for Values<'a, K, V> { - type Item = &'a V; - - #[inline] - fn next(&mut self) -> Option<(&'a V)> { - self.inner.next().map(|(_, v)| v) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for Values<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for Values<'_, K, V> {} - -impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { - type Item = &'a mut V; - - #[inline] - fn next(&mut self) -> Option<(&'a mut V)> { - self.inner.next().map(|(_, v)| v) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for ValuesMut<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for ValuesMut<'_, K, V> {} - -impl fmt::Debug for ValuesMut<'_, K, V> -where - K: fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.inner.iter()).finish() - } -} - -impl<'a, K, V> Iterator for Drain<'a, K, V> { - type Item = (K, V); - - #[inline] - fn next(&mut self) -> Option<(K, V)> { - self.inner.next() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} -impl ExactSizeIterator for Drain<'_, K, V> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} -impl FusedIterator for Drain<'_, K, V> {} - -impl fmt::Debug for Drain<'_, K, V> -where - K: fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<'a, K, V, S> Entry<'a, K, V, S> { - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.entry("poneyland").or_insert(3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.entry("poneyland").or_insert(10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[inline] - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(default), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let s = "hoho".to_string(); - /// - /// map.entry("poneyland").or_insert_with(|| s); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[inline] - pub fn or_insert_with V>(self, default: F) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(default()), - } - } - - /// Returns a reference to this entry's key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - match *self { - Entry::Occupied(ref entry) => entry.key(), - Entry::Vacant(ref entry) => entry.key(), - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[inline] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Entry::Occupied(mut entry) => { - f(entry.get_mut()); - Entry::Occupied(entry) - } - Entry::Vacant(entry) => Entry::Vacant(entry), - } - } -} - -impl<'a, K, V: Default, S> Entry<'a, K, V, S> { - /// Ensures a value is in the entry by inserting the default value if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, Option> = HashMap::new(); - /// map.entry("poneyland").or_default(); - /// - /// assert_eq!(map["poneyland"], None); - /// # } - /// ``` - #[inline] - pub fn or_default(self) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(Default::default()), - } - } -} - -impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Take the ownership of the key and value from the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// // We delete the entry from the map. - /// o.remove_entry(); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[inline] - pub fn remove_entry(self) -> (K, V) { - unsafe { - self.table.table.erase_no_drop(&self.elem); - self.elem.read() - } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// assert_eq!(o.get(), &12); - /// } - /// ``` - #[inline] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// If you need a reference to the `OccupiedEntry` which may outlive the - /// destruction of the `Entry` value, see [`into_mut`]. - /// - /// [`into_mut`]: #method.into_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let Entry::Occupied(mut o) = map.entry("poneyland") { - /// *o.get_mut() += 10; - /// assert_eq!(*o.get(), 22); - /// - /// // We can use the same Entry multiple times. - /// *o.get_mut() += 2; - /// } - /// - /// assert_eq!(map["poneyland"], 24); - /// ``` - #[inline] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// *o.into_mut() += 10; - /// } - /// - /// assert_eq!(map["poneyland"], 22); - /// ``` - #[inline] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(mut o) = map.entry("poneyland") { - /// assert_eq!(o.insert(15), 12); - /// } - /// - /// assert_eq!(map["poneyland"], 15); - /// ``` - #[inline] - pub fn insert(&mut self, mut value: V) -> V { - let old_value = self.get_mut(); - mem::swap(&mut value, old_value); - value - } - - /// Takes the value out of the entry, and returns it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// assert_eq!(o.remove(), 12); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[inline] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Replaces the entry, returning the old key and value. The new key in the hash map will be - /// the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap, u32> = HashMap::new(); - /// map.insert(Rc::new("Stringthing".to_string()), 15); - /// - /// let my_key = Rc::new("Stringthing".to_string()); - /// - /// if let Entry::Occupied(entry) = map.entry(my_key) { - /// // Also replace the key with a handle to our other key. - /// let (old_key, old_value): (Rc, u32) = entry.replace_entry(16); - /// } - /// - /// ``` - #[inline] - pub fn replace_entry(self, value: V) -> (K, V) { - let entry = unsafe { self.elem.as_mut() }; - - let old_key = mem::replace(&mut entry.0, self.key.unwrap()); - let old_value = mem::replace(&mut entry.1, value); - - (old_key, old_value) - } - - /// Replaces the key in the hash map with the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap, u32> = HashMap::new(); - /// let mut known_strings: Vec> = Vec::new(); - /// - /// // Initialise known strings, run program, etc. - /// - /// reclaim_memory(&mut map, &known_strings); - /// - /// fn reclaim_memory(map: &mut HashMap, u32>, known_strings: &[Rc] ) { - /// for s in known_strings { - /// if let Entry::Occupied(entry) = map.entry(s.clone()) { - /// // Replaces the entry's key with our version of it in `known_strings`. - /// entry.replace_key(); - /// } - /// } - /// } - /// ``` - #[inline] - pub fn replace_key(self) -> K { - let entry = unsafe { self.elem.as_mut() }; - mem::replace(&mut entry.0, self.key.unwrap()) - } -} - -impl<'a, K, V, S> VacantEntry<'a, K, V, S> { - /// Gets a reference to the key that would be used when inserting a value - /// through the `VacantEntry`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - &self.key - } - - /// Take ownership of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let Entry::Vacant(v) = map.entry("poneyland") { - /// v.into_key(); - /// } - /// ``` - #[inline] - pub fn into_key(self) -> K { - self.key - } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let Entry::Vacant(o) = map.entry("poneyland") { - /// o.insert(37); - /// } - /// assert_eq!(map["poneyland"], 37); - /// ``` - #[inline] - pub fn insert(self, value: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - let hash_builder = &self.table.hash_builder; - let bucket = self.table.table.insert(self.hash, (self.key, value), |x| { - make_hash(hash_builder, &x.0) - }); - unsafe { &mut bucket.as_mut().1 } - } -} - -impl FromIterator<(K, V)> for HashMap -where - K: Eq + Hash, - S: BuildHasher + Default, -{ - #[inline] - fn from_iter>(iter: T) -> Self { - let iter = iter.into_iter(); - let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default()); - iter.for_each(|(k, v)| { - map.insert(k, v); - }); - map - } -} - -impl Extend<(K, V)> for HashMap -where - K: Eq + Hash, - S: BuildHasher, -{ - #[inline] - fn extend>(&mut self, iter: T) { - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire hint lower bound if the map is empty. - // Otherwise reserve half the hint (rounded up), so the map - // will only resize twice in the worst case. - let iter = iter.into_iter(); - let reserve = if self.is_empty() { - iter.size_hint().0 - } else { - (iter.size_hint().0 + 1) / 2 - }; - self.reserve(reserve); - iter.for_each(move |(k, v)| { - self.insert(k, v); - }); - } -} - -impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap -where - K: Eq + Hash + Copy, - V: Copy, - S: BuildHasher, -{ - #[inline] - fn extend>(&mut self, iter: T) { - self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); - } -} - -#[allow(dead_code)] -fn assert_covariance() { - fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> { - v - } - fn map_val<'new>(v: HashMap) -> HashMap { - v - } - fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> { - v - } - fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> { - v - } - fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> { - v - } - fn into_iter_val<'new>(v: IntoIter) -> IntoIter { - v - } - fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> { - v - } - fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> { - v - } - fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> { - v - } - fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> { - v - } - fn drain<'new>( - d: Drain<'static, &'static str, &'static str>, - ) -> Drain<'new, &'new str, &'new str> { - d - } -} - -#[cfg(test)] -mod test_map { - use super::DefaultHashBuilder; - use super::Entry::{Occupied, Vacant}; - use super::{HashMap, RawEntryMut}; - #[cfg(not(miri))] - use crate::CollectionAllocErr::*; - use rand::{rngs::SmallRng, Rng, SeedableRng}; - use std::cell::RefCell; - use std::usize; - use std::vec::Vec; - - #[test] - fn test_zero_capacities() { - type HM = HashMap; - - let m = HM::new(); - assert_eq!(m.capacity(), 0); - - let m = HM::default(); - assert_eq!(m.capacity(), 0); - - let m = HM::with_hasher(DefaultHashBuilder::default()); - assert_eq!(m.capacity(), 0); - - let m = HM::with_capacity(0); - assert_eq!(m.capacity(), 0); - - let m = HM::with_capacity_and_hasher(0, DefaultHashBuilder::default()); - assert_eq!(m.capacity(), 0); - - let mut m = HM::new(); - m.insert(1, 1); - m.insert(2, 2); - m.remove(&1); - m.remove(&2); - m.shrink_to_fit(); - assert_eq!(m.capacity(), 0); - - let mut m = HM::new(); - m.reserve(0); - assert_eq!(m.capacity(), 0); - } - - #[test] - fn test_create_capacity_zero() { - let mut m = HashMap::with_capacity(0); - - assert!(m.insert(1, 1).is_none()); - - assert!(m.contains_key(&1)); - assert!(!m.contains_key(&0)); - } - - #[test] - fn test_insert() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&2).unwrap(), 4); - } - - #[test] - fn test_clone() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - let m2 = m.clone(); - assert_eq!(*m2.get(&1).unwrap(), 2); - assert_eq!(*m2.get(&2).unwrap(), 4); - assert_eq!(m2.len(), 2); - } - - thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } - - #[derive(Hash, PartialEq, Eq)] - struct Droppable { - k: usize, - } - - impl Droppable { - fn new(k: usize) -> Droppable { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[k] += 1; - }); - - Droppable { k } - } - } - - impl Drop for Droppable { - fn drop(&mut self) { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[self.k] -= 1; - }); - } - } - - impl Clone for Droppable { - fn clone(&self) -> Self { - Droppable::new(self.k) - } - } - - #[test] - fn test_drops() { - DROP_VECTOR.with(|slot| { - *slot.borrow_mut() = vec![0; 200]; - }); - - { - let mut m = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Droppable::new(i); - let d2 = Droppable::new(i + 100); - m.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - for i in 0..50 { - let k = Droppable::new(i); - let v = m.remove(&k); - - assert!(v.is_some()); - - DROP_VECTOR.with(|v| { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i + 100], 1); - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..50 { - assert_eq!(v.borrow()[i], 0); - assert_eq!(v.borrow()[i + 100], 0); - } - - for i in 50..100 { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i + 100], 1); - } - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_into_iter_drops() { - DROP_VECTOR.with(|v| { - *v.borrow_mut() = vec![0; 200]; - }); - - let hm = { - let mut hm = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Droppable::new(i); - let d2 = Droppable::new(i + 100); - hm.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - { - let mut half = hm.into_iter().take(50); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - for _ in half.by_ref() {} - - DROP_VECTOR.with(|v| { - let nk = (0..100).filter(|&i| v.borrow()[i] == 1).count(); - - let nv = (0..100).filter(|&i| v.borrow()[i + 100] == 1).count(); - - assert_eq!(nk, 50); - assert_eq!(nv, 50); - }); - }; - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_empty_remove() { - let mut m: HashMap = HashMap::new(); - assert_eq!(m.remove(&0), None); - } - - #[test] - fn test_empty_entry() { - let mut m: HashMap = HashMap::new(); - match m.entry(0) { - Occupied(_) => panic!(), - Vacant(_) => {} - } - assert!(*m.entry(0).or_insert(true)); - assert_eq!(m.len(), 1); - } - - #[test] - fn test_empty_iter() { - let mut m: HashMap = HashMap::new(); - assert_eq!(m.drain().next(), None); - assert_eq!(m.keys().next(), None); - assert_eq!(m.values().next(), None); - assert_eq!(m.values_mut().next(), None); - assert_eq!(m.iter().next(), None); - assert_eq!(m.iter_mut().next(), None); - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - assert_eq!(m.into_iter().next(), None); - } - - #[test] - #[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/654 - fn test_lots_of_insertions() { - let mut m = HashMap::new(); - - // Try this a few times to make sure we never screw up the hashmap's - // internal state. - for _ in 0..10 { - assert!(m.is_empty()); - - for i in 1..1001 { - assert!(m.insert(i, i).is_none()); - - for j in 1..=i { - let r = m.get(&j); - assert_eq!(r, Some(&j)); - } - - for j in i + 1..1001 { - let r = m.get(&j); - assert_eq!(r, None); - } - } - - for i in 1001..2001 { - assert!(!m.contains_key(&i)); - } - - // remove forwards - for i in 1..1001 { - assert!(m.remove(&i).is_some()); - - for j in 1..=i { - assert!(!m.contains_key(&j)); - } - - for j in i + 1..1001 { - assert!(m.contains_key(&j)); - } - } - - for i in 1..1001 { - assert!(!m.contains_key(&i)); - } - - for i in 1..1001 { - assert!(m.insert(i, i).is_none()); - } - - // remove backwards - for i in (1..1001).rev() { - assert!(m.remove(&i).is_some()); - - for j in i..1001 { - assert!(!m.contains_key(&j)); - } - - for j in 1..i { - assert!(m.contains_key(&j)); - } - } - } - } - - #[test] - fn test_find_mut() { - let mut m = HashMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), - Some(x) => *x = new, - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_insert_overwrite() { - let mut m = HashMap::new(); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(!m.insert(1, 3).is_none()); - assert_eq!(*m.get(&1).unwrap(), 3); - } - - #[test] - fn test_insert_conflicts() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(5, 3).is_none()); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&1).unwrap(), 2); - } - - #[test] - fn test_conflict_remove() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(m.insert(5, 3).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&9).unwrap(), 4); - assert!(m.remove(&1).is_some()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - } - - #[test] - fn test_is_empty() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(!m.is_empty()); - assert!(m.remove(&1).is_some()); - assert!(m.is_empty()); - } - - #[test] - fn test_remove() { - let mut m = HashMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_remove_entry() { - let mut m = HashMap::new(); - m.insert(1, 2); - assert_eq!(m.remove_entry(&1), Some((1, 2))); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in 0..32 { - assert!(m.insert(i, i * 2).is_none()); - } - assert_eq!(m.len(), 32); - - let mut observed: u32 = 0; - - for (k, v) in &m { - assert_eq!(*v, *k * 2); - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let keys: Vec<_> = map.keys().cloned().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_values_mut() { - let vec = vec![(1, 1), (2, 2), (3, 3)]; - let mut map: HashMap<_, _> = vec.into_iter().collect(); - for value in map.values_mut() { - *value = (*value) * 2 - } - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&2)); - assert!(values.contains(&4)); - assert!(values.contains(&6)); - } - - #[test] - fn test_find() { - let mut m = HashMap::new(); - assert!(m.get(&1).is_none()); - m.insert(1, 2); - match m.get(&1) { - None => panic!(), - Some(v) => assert_eq!(*v, 2), - } - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); - - let mut m2 = HashMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); - - assert!(m1 != m2); - - m2.insert(3, 4); - - assert_eq!(m1, m2); - } - - #[test] - fn test_show() { - let mut map = HashMap::new(); - let empty: HashMap = HashMap::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_expand() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - - let mut i = 0; - let old_raw_cap = m.raw_capacity(); - while old_raw_cap == m.raw_capacity() { - m.insert(i, i); - i += 1; - } - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - } - - #[test] - fn test_behavior_resize_policy() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert_eq!(m.raw_capacity(), 1); - assert!(m.is_empty()); - - m.insert(0, 0); - m.remove(&0); - assert!(m.is_empty()); - let initial_raw_cap = m.raw_capacity(); - m.reserve(initial_raw_cap); - let raw_cap = m.raw_capacity(); - - assert_eq!(raw_cap, initial_raw_cap * 2); - - let mut i = 0; - for _ in 0..raw_cap * 3 / 4 { - m.insert(i, i); - i += 1; - } - // three quarters full - - assert_eq!(m.len(), i); - assert_eq!(m.raw_capacity(), raw_cap); - - for _ in 0..raw_cap / 4 { - m.insert(i, i); - i += 1; - } - // half full - - let new_raw_cap = m.raw_capacity(); - assert_eq!(new_raw_cap, raw_cap * 2); - - for _ in 0..raw_cap / 2 - 1 { - i -= 1; - m.remove(&i); - assert_eq!(m.raw_capacity(), new_raw_cap); - } - // A little more than one quarter full. - m.shrink_to_fit(); - assert_eq!(m.raw_capacity(), raw_cap); - // again, a little more than half full - for _ in 0..raw_cap / 2 { - i -= 1; - m.remove(&i); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - assert_eq!(m.raw_capacity(), initial_raw_cap); - } - - #[test] - fn test_reserve_shrink_to_fit() { - let mut m = HashMap::new(); - m.insert(0, 0); - m.remove(&0); - assert!(m.capacity() >= m.len()); - for i in 0..128 { - m.insert(i, i); - } - m.reserve(256); - - let usable_cap = m.capacity(); - for i in 128..(128 + 256) { - m.insert(i, i); - assert_eq!(m.capacity(), usable_cap); - } - - for i in 100..(128 + 256) { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), 100); - assert!(!m.is_empty()); - assert!(m.capacity() >= m.len()); - - for i in 0..100 { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - m.insert(0, 0); - - assert_eq!(m.len(), 1); - assert!(m.capacity() >= m.len()); - assert_eq!(m.remove(&0), Some(0)); - } - - #[test] - fn test_from_iter() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_mut_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_mut_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_index() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[&2], 1); - } - - #[test] - #[should_panic] - fn test_index_nonexistent() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[&4]; - } - - #[test] - fn test_entry() { - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } - - #[test] - fn test_entry_take_doesnt_corrupt() { - #![allow(deprecated)] //rand - // Test for #19292 - fn check(m: &HashMap) { - for k in m.keys() { - assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - - // FIXME: https://github.com/rust-lang/miri/issues/653 - let mut rng = { - let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - SmallRng::from_seed(seed) - }; - - // Populate the map with some items. - for _ in 0..50 { - let x = rng.gen_range(-10, 10); - m.insert(x, ()); - } - - for _ in 0..1000 { - let x = rng.gen_range(-10, 10); - match m.entry(x) { - Vacant(_) => {} - Occupied(e) => { - e.remove(); - } - } - - check(&m); - } - } - - #[test] - fn test_extend_ref() { - let mut a = HashMap::new(); - a.insert(1, "one"); - let mut b = HashMap::new(); - b.insert(2, "two"); - b.insert(3, "three"); - - a.extend(&b); - - assert_eq!(a.len(), 3); - assert_eq!(a[&1], "one"); - assert_eq!(a[&2], "two"); - assert_eq!(a[&3], "three"); - } - - #[test] - fn test_capacity_not_less_than_len() { - let mut a = HashMap::new(); - let mut item = 0; - - for _ in 0..116 { - a.insert(item, 0); - item += 1; - } - - assert!(a.capacity() > a.len()); - - let free = a.capacity() - a.len(); - for _ in 0..free { - a.insert(item, 0); - item += 1; - } - - assert_eq!(a.len(), a.capacity()); - - // Insert at capacity should cause allocation. - a.insert(item, 0); - assert!(a.capacity() > a.len()); - } - - #[test] - fn test_occupied_entry_key() { - let mut a = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - assert!(a.is_empty()); - a.insert(key.clone(), value.clone()); - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - - match a.entry(key.clone()) { - Vacant(_) => panic!(), - Occupied(e) => assert_eq!(key, *e.key()), - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_vacant_entry_key() { - let mut a = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - - assert!(a.is_empty()); - match a.entry(key.clone()) { - Occupied(_) => panic!(), - Vacant(e) => { - assert_eq!(key, *e.key()); - e.insert(value.clone()); - } - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_retain() { - let mut map: HashMap = (0..100).map(|x| (x, x * 10)).collect(); - - map.retain(|&k, _| k % 2 == 0); - assert_eq!(map.len(), 50); - assert_eq!(map[&2], 20); - assert_eq!(map[&4], 40); - assert_eq!(map[&6], 60); - } - - #[test] - #[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/655 - fn test_try_reserve() { - let mut empty_bytes: HashMap = HashMap::new(); - - const MAX_USIZE: usize = usize::MAX; - - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!"); - } - - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) { - } else { - // This may succeed if there is enough free memory. Attempt to - // allocate a second hashmap to ensure the allocation will fail. - let mut empty_bytes2: HashMap = HashMap::new(); - if let Err(AllocErr) = empty_bytes2.try_reserve(MAX_USIZE / 8) { - } else { - panic!("usize::MAX / 8 should trigger an OOM!"); - } - } - } - - #[test] - fn test_raw_entry() { - use super::RawEntryMut::{Occupied, Vacant}; - - let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let compute_hash = |map: &HashMap, k: i32| -> u64 { - use core::hash::{BuildHasher, Hash, Hasher}; - - let mut hasher = map.hasher().build_hasher(); - k.hash(&mut hasher); - hasher.finish() - }; - - // Existing key (insert) - match map.raw_entry_mut().from_key(&1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - let hash1 = compute_hash(&map, 1); - assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100)); - assert_eq!( - map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(), - (&1, &100) - ); - assert_eq!( - map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(), - (&1, &100) - ); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.raw_entry_mut().from_key(&2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - let hash2 = compute_hash(&map, 2); - assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200)); - assert_eq!( - map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(), - (&2, &200) - ); - assert_eq!( - map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(), - (&2, &200) - ); - assert_eq!(map.len(), 6); - - // Existing key (take) - let hash3 = compute_hash(&map, 3); - match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove_entry(), (3, 30)); - } - } - assert_eq!(map.raw_entry().from_key(&3), None); - assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None); - assert_eq!(map.len(), 5); - - // Nonexistent key (insert) - match map.raw_entry_mut().from_key(&10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000)); - } - } - assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000)); - assert_eq!(map.len(), 6); - - // Ensure all lookup methods produce equivalent results. - for k in 0..12 { - let hash = compute_hash(&map, k); - let v = map.get(&k).cloned(); - let kv = v.as_ref().map(|v| (&k, v)); - - assert_eq!(map.raw_entry().from_key(&k), kv); - assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv); - - match map.raw_entry_mut().from_key(&k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_hash(hash, |q| *q == k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - } - } - - #[test] - fn test_key_without_hash_impl() { - #[derive(Debug)] - struct IntWrapper(u64); - - let mut m: HashMap = HashMap::new(); - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none()); - } - { - let vacant_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) { - RawEntryMut::Occupied(..) => panic!("Found entry for key 0"), - RawEntryMut::Vacant(e) => e, - }; - vacant_entry.insert_with_hasher(0, IntWrapper(0), (), |k| k.0); - } - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_none()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } - { - let vacant_entry = match m.raw_entry_mut().from_hash(1, |k| k.0 == 1) { - RawEntryMut::Occupied(..) => panic!("Found entry for key 1"), - RawEntryMut::Vacant(e) => e, - }; - vacant_entry.insert_with_hasher(1, IntWrapper(1), (), |k| k.0); - } - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } - { - let occupied_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) { - RawEntryMut::Occupied(e) => e, - RawEntryMut::Vacant(..) => panic!("Couldn't find entry for key 0"), - }; - occupied_entry.remove(); - } - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } -} diff --git a/vendor/hashbrown-0.4.0/src/raw/bitmask.rs b/vendor/hashbrown-0.4.0/src/raw/bitmask.rs deleted file mode 100644 index 6e61d4311e..0000000000 --- a/vendor/hashbrown-0.4.0/src/raw/bitmask.rs +++ /dev/null @@ -1,108 +0,0 @@ -use super::imp::{BitMaskWord, BITMASK_MASK, BITMASK_STRIDE}; -#[cfg(feature = "nightly")] -use core::intrinsics; - -/// A bit mask which contains the result of a `Match` operation on a `Group` and -/// allows iterating through them. -/// -/// The bit mask is arranged so that low-order bits represent lower memory -/// addresses for group match results. -/// -/// For implementation reasons, the bits in the set may be sparsely packed, so -/// that there is only one bit-per-byte used (the high bit, 7). If this is the -/// case, `BITMASK_STRIDE` will be 8 to indicate a divide-by-8 should be -/// performed on counts/indices to normalize this difference. `BITMASK_MASK` is -/// similarly a mask of all the actually-used bits. -#[derive(Copy, Clone)] -pub struct BitMask(pub BitMaskWord); - -#[allow(clippy::use_self)] -impl BitMask { - /// Returns a new `BitMask` with all bits inverted. - #[inline] - #[must_use] - pub fn invert(self) -> Self { - BitMask(self.0 ^ BITMASK_MASK) - } - - /// Returns a new `BitMask` with the lowest bit removed. - #[inline] - #[must_use] - pub fn remove_lowest_bit(self) -> Self { - BitMask(self.0 & (self.0 - 1)) - } - /// Returns whether the `BitMask` has at least one set bit. - #[inline] - pub fn any_bit_set(self) -> bool { - self.0 != 0 - } - - /// Returns the first set bit in the `BitMask`, if there is one. - #[inline] - pub fn lowest_set_bit(self) -> Option { - if self.0 == 0 { - None - } else { - Some(unsafe { self.lowest_set_bit_nonzero() }) - } - } - - /// Returns the first set bit in the `BitMask`, if there is one. The - /// bitmask must not be empty. - #[inline] - #[cfg(feature = "nightly")] - pub unsafe fn lowest_set_bit_nonzero(self) -> usize { - intrinsics::cttz_nonzero(self.0) as usize / BITMASK_STRIDE - } - #[inline] - #[cfg(not(feature = "nightly"))] - pub unsafe fn lowest_set_bit_nonzero(self) -> usize { - self.trailing_zeros() - } - - /// Returns the number of trailing zeroes in the `BitMask`. - #[inline] - pub fn trailing_zeros(self) -> usize { - // ARM doesn't have a trailing_zeroes instruction, and instead uses - // reverse_bits (RBIT) + leading_zeroes (CLZ). However older ARM - // versions (pre-ARMv7) don't have RBIT and need to emulate it - // instead. Since we only have 1 bit set in each byte on ARM, we can - // use swap_bytes (REV) + leading_zeroes instead. - if cfg!(target_arch = "arm") && BITMASK_STRIDE % 8 == 0 { - self.0.swap_bytes().leading_zeros() as usize / BITMASK_STRIDE - } else { - self.0.trailing_zeros() as usize / BITMASK_STRIDE - } - } - - /// Returns the number of leading zeroes in the `BitMask`. - #[inline] - pub fn leading_zeros(self) -> usize { - self.0.leading_zeros() as usize / BITMASK_STRIDE - } -} - -impl IntoIterator for BitMask { - type Item = usize; - type IntoIter = BitMaskIter; - - #[inline] - fn into_iter(self) -> BitMaskIter { - BitMaskIter(self) - } -} - -/// Iterator over the contents of a `BitMask`, returning the indicies of set -/// bits. -pub struct BitMaskIter(BitMask); - -impl Iterator for BitMaskIter { - type Item = usize; - - #[inline] - fn next(&mut self) -> Option { - let bit = self.0.lowest_set_bit()?; - self.0 = self.0.remove_lowest_bit(); - Some(bit) - } -} diff --git a/vendor/hashbrown-0.4.0/src/raw/generic.rs b/vendor/hashbrown-0.4.0/src/raw/generic.rs deleted file mode 100644 index 2dee2ea512..0000000000 --- a/vendor/hashbrown-0.4.0/src/raw/generic.rs +++ /dev/null @@ -1,157 +0,0 @@ -use super::bitmask::BitMask; -use super::EMPTY; -use core::{mem, ptr}; - -// Use the native word size as the group size. Using a 64-bit group size on -// a 32-bit architecture will just end up being more expensive because -// shifts and multiplies will need to be emulated. -#[cfg(any( - target_pointer_width = "64", - target_arch = "aarch64", - target_arch = "x86_64", -))] -type GroupWord = u64; -#[cfg(all( - target_pointer_width = "32", - not(target_arch = "aarch64"), - not(target_arch = "x86_64"), -))] -type GroupWord = u32; - -pub type BitMaskWord = GroupWord; -pub const BITMASK_STRIDE: usize = 8; -// We only care about the highest bit of each byte for the mask. -#[allow( - clippy::cast_possible_truncation, - clippy::unnecessary_cast, -)] -pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord; - -/// Helper function to replicate a byte across a `GroupWord`. -#[inline] -fn repeat(byte: u8) -> GroupWord { - let repeat = GroupWord::from(byte); - let repeat = repeat | repeat.wrapping_shl(8); - let repeat = repeat | repeat.wrapping_shl(16); - // This last line is a no-op with a 32-bit GroupWord - repeat | repeat.wrapping_shl(32) -} - -/// Abstraction over a group of control bytes which can be scanned in -/// parallel. -/// -/// This implementation uses a word-sized integer. -#[derive(Copy, Clone)] -pub struct Group(GroupWord); - -// We perform all operations in the native endianess, and convert to -// little-endian just before creating a BitMask. The can potentially -// enable the compiler to eliminate unnecessary byte swaps if we are -// only checking whether a BitMask is empty. -#[allow(clippy::use_self)] -impl Group { - /// Number of bytes in the group. - pub const WIDTH: usize = mem::size_of::(); - - /// Returns a full group of empty bytes, suitable for use as the initial - /// value for an empty hash table. - /// - /// This is guaranteed to be aligned to the group size. - #[inline] - pub fn static_empty() -> &'static [u8] { - union AlignedBytes { - _align: Group, - bytes: [u8; Group::WIDTH], - }; - const ALIGNED_BYTES: AlignedBytes = AlignedBytes { - bytes: [EMPTY; Group::WIDTH], - }; - unsafe { &ALIGNED_BYTES.bytes } - } - - /// Loads a group of bytes starting at the given address. - #[inline] - #[allow(clippy::cast_ptr_alignment)] // unaligned load - pub unsafe fn load(ptr: *const u8) -> Self { - Group(ptr::read_unaligned(ptr as *const _)) - } - - /// Loads a group of bytes starting at the given address, which must be - /// aligned to `mem::align_of::()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn load_aligned(ptr: *const u8) -> Self { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::() - 1), 0); - Group(ptr::read(ptr as *const _)) - } - - /// Stores the group of bytes to the given address, which must be - /// aligned to `mem::align_of::()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn store_aligned(self, ptr: *mut u8) { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::() - 1), 0); - ptr::write(ptr as *mut _, self.0); - } - - /// Returns a `BitMask` indicating all bytes in the group which *may* - /// have the given value. - /// - /// This function may return a false positive in certain cases where - /// the byte in the group differs from the searched value only in its - /// lowest bit. This is fine because: - /// - This never happens for `EMPTY` and `DELETED`, only full entries. - /// - The check for key equality will catch these. - /// - This only happens if there is at least 1 true match. - /// - The chance of this happening is very low (< 1% chance per byte). - #[inline] - pub fn match_byte(self, byte: u8) -> BitMask { - // This algorithm is derived from - // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord - let cmp = self.0 ^ repeat(byte); - BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY`. - #[inline] - pub fn match_empty(self) -> BitMask { - // If the high bit is set, then the byte must be either: - // 1111_1111 (EMPTY) or 1000_0000 (DELETED). - // So we can just check if the top two bits are 1 by ANDing them. - BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY` or `DELETED`. - #[inline] - pub fn match_empty_or_deleted(self) -> BitMask { - // A byte is EMPTY or DELETED iff the high bit is set - BitMask((self.0 & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are full. - #[inline] - pub fn match_full(&self) -> BitMask { - self.match_empty_or_deleted().invert() - } - - /// Performs the following transformation on all bytes in the group: - /// - `EMPTY => EMPTY` - /// - `DELETED => EMPTY` - /// - `FULL => DELETED` - #[inline] - pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self { - // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111 - // and high_bit = 0 (FULL) to 1000_0000 - // - // Here's this logic expanded to concrete values: - // let full = 1000_0000 (true) or 0000_0000 (false) - // !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry) - // !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry) - let full = !self.0 & repeat(0x80); - Group(!full + (full >> 7)) - } -} diff --git a/vendor/hashbrown-0.4.0/src/raw/mod.rs b/vendor/hashbrown-0.4.0/src/raw/mod.rs deleted file mode 100644 index 822b5c9c31..0000000000 --- a/vendor/hashbrown-0.4.0/src/raw/mod.rs +++ /dev/null @@ -1,1374 +0,0 @@ -use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error}; -use crate::scopeguard::guard; -use crate::CollectionAllocErr; -use core::alloc::Layout; -use core::hint; -use core::iter::FusedIterator; -use core::marker::PhantomData; -use core::mem; -use core::mem::ManuallyDrop; -use core::ptr::NonNull; - -cfg_if! { - // Use the SSE2 implementation if possible: it allows us to scan 16 buckets - // at once instead of 8. We don't bother with AVX since it would require - // runtime dispatch and wouldn't gain us much anyways: the probability of - // finding a match drops off drastically after the first few buckets. - // - // I attempted an implementation on ARM using NEON instructions, but it - // turns out that most NEON instructions have multi-cycle latency, which in - // the end outweighs any gains over the generic implementation. - if #[cfg(all( - target_feature = "sse2", - any(target_arch = "x86", target_arch = "x86_64"), - not(miri) - ))] { - #[path = "sse2.rs"] - mod imp; - } else { - #[path = "generic.rs"] - mod imp; - } -} - -mod bitmask; - -use self::bitmask::BitMask; -use self::imp::Group; - -// Branch prediction hint. This is currently only available on nightly but it -// consistently improves performance by 10-15%. -#[cfg(feature = "nightly")] -use core::intrinsics::{likely, unlikely}; -#[cfg(not(feature = "nightly"))] -#[inline] -fn likely(b: bool) -> bool { - b -} -#[cfg(not(feature = "nightly"))] -#[inline] -fn unlikely(b: bool) -> bool { - b -} - -#[cfg(feature = "nightly")] -#[inline] -unsafe fn offset_from(to: *const T, from: *const T) -> usize { - to.offset_from(from) as usize -} -#[cfg(not(feature = "nightly"))] -#[inline] -unsafe fn offset_from(to: *const T, from: *const T) -> usize { - (to as usize - from as usize) / mem::size_of::() -} - -/// Whether memory allocation errors should return an error or abort. -#[derive(Copy, Clone)] -enum Fallibility { - Fallible, - Infallible, -} - -impl Fallibility { - /// Error to return on capacity overflow. - #[inline] - fn capacity_overflow(self) -> CollectionAllocErr { - match self { - Fallibility::Fallible => CollectionAllocErr::CapacityOverflow, - Fallibility::Infallible => panic!("Hash table capacity overflow"), - } - } - - /// Error to return on allocation error. - #[inline] - fn alloc_err(self, layout: Layout) -> CollectionAllocErr { - match self { - Fallibility::Fallible => CollectionAllocErr::AllocErr, - Fallibility::Infallible => handle_alloc_error(layout), - } - } -} - -/// Control byte value for an empty bucket. -const EMPTY: u8 = 0b1111_1111; - -/// Control byte value for a deleted bucket. -const DELETED: u8 = 0b1000_0000; - -/// Checks whether a control byte represents a full bucket (top bit is clear). -#[inline] -fn is_full(ctrl: u8) -> bool { - ctrl & 0x80 == 0 -} - -/// Checks whether a control byte represents a special value (top bit is set). -#[inline] -fn is_special(ctrl: u8) -> bool { - ctrl & 0x80 != 0 -} - -/// Checks whether a special control value is EMPTY (just check 1 bit). -#[inline] -fn special_is_empty(ctrl: u8) -> bool { - debug_assert!(is_special(ctrl)); - ctrl & 0x01 != 0 -} - -/// Primary hash function, used to select the initial bucket to probe from. -#[inline] -#[allow(clippy::cast_possible_truncation)] -fn h1(hash: u64) -> usize { - // On 32-bit platforms we simply ignore the higher hash bits. - hash as usize -} - -/// Secondary hash function, saved in the low 7 bits of the control byte. -#[inline] -#[allow(clippy::cast_possible_truncation)] -fn h2(hash: u64) -> u8 { - // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit - // value, some hash functions (such as FxHash) produce a usize result - // instead, which means that the top 32 bits are 0 on 32-bit platforms. - let hash_len = usize::min(mem::size_of::(), mem::size_of::()); - let top7 = hash >> (hash_len * 8 - 7); - (top7 & 0x7f) as u8 // truncation -} - -/// Probe sequence based on triangular numbers, which is guaranteed (since our -/// table size is a power of two) to visit every group of elements exactly once. -/// -/// A triangular probe has us jump by 1 more group every time. So first we -/// jump by 1 group (meaning we just continue our linear scan), then 2 groups -/// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on. -/// -/// Proof that the probe will visit every group in the table: -/// -struct ProbeSeq { - bucket_mask: usize, - pos: usize, - stride: usize, -} - -impl Iterator for ProbeSeq { - type Item = usize; - - #[inline] - fn next(&mut self) -> Option { - // We should have found an empty bucket by now and ended the probe. - debug_assert!( - self.stride <= self.bucket_mask, - "Went past end of probe sequence" - ); - - let result = self.pos; - self.stride += Group::WIDTH; - self.pos += self.stride; - self.pos &= self.bucket_mask; - Some(result) - } -} - -/// Returns the number of buckets needed to hold the given number of items, -/// taking the maximum load factor into account. -/// -/// Returns `None` if an overflow occurs. -#[inline] -// Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258 -#[cfg_attr(target_os = "emscripten", inline(never))] -fn capacity_to_buckets(cap: usize) -> Option { - let adjusted_cap = if cap < 8 { - // Need at least 1 free bucket on small tables - cap + 1 - } else { - // Otherwise require 1/8 buckets to be empty (87.5% load) - // - // Be careful when modifying this, calculate_layout relies on the - // overflow check here. - cap.checked_mul(8)? / 7 - }; - - // Any overflows will have been caught by the checked_mul. Also, any - // rounding errors from the division above will be cleaned up by - // next_power_of_two (which can't overflow because of the previous divison). - Some(adjusted_cap.next_power_of_two()) -} - -/// Returns the maximum effective capacity for the given bucket mask, taking -/// the maximum load factor into account. -#[inline] -fn bucket_mask_to_capacity(bucket_mask: usize) -> usize { - if bucket_mask < 8 { - // For tables with 1/2/4/8 buckets, we always reserve one empty slot. - // Keep in mind that the bucket mask is one less than the bucket count. - bucket_mask - } else { - // For larger tables we reserve 12.5% of the slots as empty. - ((bucket_mask + 1) / 8) * 7 - } -} - -// Returns a Layout which describes the allocation required for a hash table, -// and the offset of the buckets in the allocation. -/// -/// Returns `None` if an overflow occurs. -#[inline] -#[cfg(feature = "nightly")] -fn calculate_layout(buckets: usize) -> Option<(Layout, usize)> { - debug_assert!(buckets.is_power_of_two()); - - // Array of buckets - let data = Layout::array::(buckets).ok()?; - - // Array of control bytes. This must be aligned to the group size. - // - // We add `Group::WIDTH` control bytes at the end of the array which - // replicate the bytes at the start of the array and thus avoids the need to - // perform bounds-checking while probing. - // - // There is no possible overflow here since buckets is a power of two and - // Group::WIDTH is a small number. - let ctrl = unsafe { Layout::from_size_align_unchecked(buckets + Group::WIDTH, Group::WIDTH) }; - - ctrl.extend(data).ok() -} - -// Returns a Layout which describes the allocation required for a hash table, -// and the offset of the buckets in the allocation. -#[inline] -#[cfg(not(feature = "nightly"))] -fn calculate_layout(buckets: usize) -> Option<(Layout, usize)> { - debug_assert!(buckets.is_power_of_two()); - - // Manual layout calculation since Layout methods are not yet stable. - let data_align = usize::max(mem::align_of::(), Group::WIDTH); - let data_offset = (buckets + Group::WIDTH).checked_add(data_align - 1)? & !(data_align - 1); - let len = data_offset.checked_add(mem::size_of::().checked_mul(buckets)?)?; - - Some(( - unsafe { Layout::from_size_align_unchecked(len, data_align) }, - data_offset, - )) -} - -/// A reference to a hash table bucket containing a `T`. -/// -/// This is usually just a pointer to the element itself. However if the element -/// is a ZST, then we instead track the index of the element in the table so -/// that `erase` works properly. -pub struct Bucket { - // Using *const for variance - ptr: *const T, -} - -// This Send impl is needed for rayon support. This is safe since Bucket is -// never exposed in a public API. -unsafe impl Send for Bucket {} - -impl Clone for Bucket { - #[inline] - fn clone(&self) -> Self { - Self { ptr: self.ptr } - } -} - -impl Bucket { - #[inline] - unsafe fn from_base_index(base: *const T, index: usize) -> Self { - let ptr = if mem::size_of::() == 0 { - index as *const T - } else { - base.add(index) - }; - Self { ptr } - } - #[inline] - pub unsafe fn as_ptr(&self) -> *mut T { - if mem::size_of::() == 0 { - // Just return an arbitrary ZST pointer which is properly aligned - mem::align_of::() as *mut T - } else { - self.ptr as *mut T - } - } - #[inline] - unsafe fn add(&self, offset: usize) -> Self { - let ptr = if mem::size_of::() == 0 { - (self.ptr as usize + offset) as *const T - } else { - self.ptr.add(offset) - }; - Self { ptr } - } - #[inline] - pub unsafe fn drop(&self) { - self.as_ptr().drop_in_place(); - } - #[inline] - pub unsafe fn read(&self) -> T { - self.as_ptr().read() - } - #[inline] - pub unsafe fn write(&self, val: T) { - self.as_ptr().write(val); - } - #[inline] - pub unsafe fn as_ref<'a>(&self) -> &'a T { - &*self.as_ptr() - } - #[inline] - pub unsafe fn as_mut<'a>(&self) -> &'a mut T { - &mut *self.as_ptr() - } - #[inline] - pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) { - self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1); - } -} - -/// A raw hash table with an unsafe API. -pub struct RawTable { - // Mask to get an index from a hash value. The value is one less than the - // number of buckets in the table. - bucket_mask: usize, - - // Pointer to the array of control bytes - ctrl: NonNull, - - // Pointer to the array of buckets - data: NonNull, - - // Number of elements that can be inserted before we need to grow the table - growth_left: usize, - - // Number of elements in the table, only really used by len() - items: usize, - - // Tell dropck that we own instances of T. - marker: PhantomData, -} - -impl RawTable { - /// Creates a new empty hash table without allocating any memory. - /// - /// In effect this returns a table with exactly 1 bucket. However we can - /// leave the data pointer dangling since that bucket is never written to - /// due to our load factor forcing us to always have at least 1 free bucket. - #[inline] - pub fn new() -> Self { - Self { - data: NonNull::dangling(), - // Be careful to cast the entire slice to a raw pointer. - ctrl: unsafe { NonNull::new_unchecked(Group::static_empty().as_ptr() as *mut u8) }, - bucket_mask: 0, - items: 0, - growth_left: 0, - marker: PhantomData, - } - } - - /// Allocates a new hash table with the given number of buckets. - /// - /// The control bytes are left uninitialized. - #[inline] - unsafe fn new_uninitialized( - buckets: usize, - fallability: Fallibility, - ) -> Result { - let (layout, data_offset) = - calculate_layout::(buckets).ok_or_else(|| fallability.capacity_overflow())?; - let ctrl = NonNull::new(alloc(layout)).ok_or_else(|| fallability.alloc_err(layout))?; - let data = NonNull::new_unchecked(ctrl.as_ptr().add(data_offset) as *mut T); - Ok(Self { - data, - ctrl, - bucket_mask: buckets - 1, - items: 0, - growth_left: bucket_mask_to_capacity(buckets - 1), - marker: PhantomData, - }) - } - - /// Attempts to allocate a new hash table with at least enough capacity - /// for inserting the given number of elements without reallocating. - fn try_with_capacity( - capacity: usize, - fallability: Fallibility, - ) -> Result { - if capacity == 0 { - Ok(Self::new()) - } else { - unsafe { - let buckets = - capacity_to_buckets(capacity).ok_or_else(|| fallability.capacity_overflow())?; - let result = Self::new_uninitialized(buckets, fallability)?; - result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes()); - - Ok(result) - } - } - } - - /// Allocates a new hash table with at least enough capacity for inserting - /// the given number of elements without reallocating. - pub fn with_capacity(capacity: usize) -> Self { - Self::try_with_capacity(capacity, Fallibility::Infallible) - .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }) - } - - /// Deallocates the table without dropping any entries. - #[inline] - unsafe fn free_buckets(&mut self) { - let (layout, _) = - calculate_layout::(self.buckets()).unwrap_or_else(|| hint::unreachable_unchecked()); - dealloc(self.ctrl.as_ptr(), layout); - } - - /// Returns the index of a bucket from a `Bucket`. - #[inline] - unsafe fn bucket_index(&self, bucket: &Bucket) -> usize { - if mem::size_of::() == 0 { - bucket.ptr as usize - } else { - offset_from(bucket.ptr, self.data.as_ptr()) - } - } - - /// Returns a pointer to a control byte. - #[inline] - unsafe fn ctrl(&self, index: usize) -> *mut u8 { - debug_assert!(index < self.num_ctrl_bytes()); - self.ctrl.as_ptr().add(index) - } - - /// Returns a pointer to an element in the table. - #[inline] - pub unsafe fn bucket(&self, index: usize) -> Bucket { - debug_assert_ne!(self.bucket_mask, 0); - debug_assert!(index < self.buckets()); - Bucket::from_base_index(self.data.as_ptr(), index) - } - - /// Erases an element from the table without dropping it. - #[inline] - pub unsafe fn erase_no_drop(&mut self, item: &Bucket) { - let index = self.bucket_index(item); - let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask; - let empty_before = Group::load(self.ctrl(index_before)).match_empty(); - let empty_after = Group::load(self.ctrl(index)).match_empty(); - - // If we are inside a continuous block of Group::WIDTH full or deleted - // cells then a probe window may have seen a full block when trying to - // insert. We therefore need to keep that block non-empty so that - // lookups will continue searching to the next probe window. - // - // Note that in this context `leading_zeros` refers to the bytes at the - // end of a group, while `trailing_zeros` refers to the bytes at the - // begining of a group. - let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH { - DELETED - } else { - self.growth_left += 1; - EMPTY - }; - self.set_ctrl(index, ctrl); - self.items -= 1; - } - - /// Returns an iterator for a probe sequence on the table. - /// - /// This iterator never terminates, but is guaranteed to visit each bucket - /// group exactly once. The loop using `probe_seq` must terminate upon - /// reaching a group containing an empty bucket. - #[inline] - fn probe_seq(&self, hash: u64) -> ProbeSeq { - ProbeSeq { - bucket_mask: self.bucket_mask, - pos: h1(hash) & self.bucket_mask, - stride: 0, - } - } - - /// Sets a control byte, and possibly also the replicated control byte at - /// the end of the array. - #[inline] - unsafe fn set_ctrl(&self, index: usize, ctrl: u8) { - // Replicate the first Group::WIDTH control bytes at the end of - // the array without using a branch: - // - If index >= Group::WIDTH then index == index2. - // - Otherwise index2 == self.bucket_mask + 1 + index. - // - // The very last replicated control byte is never actually read because - // we mask the initial index for unaligned loads, but we write it - // anyways because it makes the set_ctrl implementation simpler. - // - // If there are fewer buckets than Group::WIDTH then this code will - // replicate the buckets at the end of the trailing group. For example - // with 2 buckets and a group size of 4, the control bytes will look - // like this: - // - // Real | Replicated - // --------------------------------------------- - // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] | - // --------------------------------------------- - let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH; - - *self.ctrl(index) = ctrl; - *self.ctrl(index2) = ctrl; - } - - /// Searches for an empty or deleted bucket which is suitable for inserting - /// a new element. - /// - /// There must be at least 1 empty bucket in the table. - #[inline] - fn find_insert_slot(&self, hash: u64) -> usize { - for pos in self.probe_seq(hash) { - unsafe { - let group = Group::load(self.ctrl(pos)); - if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() { - let result = (pos + bit) & self.bucket_mask; - - // In tables smaller than the group width, trailing control - // bytes outside the range of the table are filled with - // EMPTY entries. These will unfortunately trigger a - // match, but once masked may point to a full bucket that - // is already occupied. We detect this situation here and - // perform a second scan starting at the begining of the - // table. This second scan is guaranteed to find an empty - // slot (due to the load factor) before hitting the trailing - // control bytes (containing EMPTY). - if unlikely(is_full(*self.ctrl(result))) { - debug_assert!(self.bucket_mask < Group::WIDTH); - debug_assert_ne!(pos, 0); - return Group::load_aligned(self.ctrl(0)) - .match_empty_or_deleted() - .lowest_set_bit_nonzero(); - } else { - return result; - } - } - } - } - - // probe_seq never returns. - unreachable!(); - } - - /// Marks all table buckets as empty without dropping their contents. - #[inline] - pub fn clear_no_drop(&mut self) { - if !self.is_empty_singleton() { - unsafe { - self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes()); - } - } - self.items = 0; - self.growth_left = bucket_mask_to_capacity(self.bucket_mask); - } - - /// Removes all elements from the table without freeing the backing memory. - #[inline] - pub fn clear(&mut self) { - // Ensure that the table is reset even if one of the drops panic - let self_ = guard(self, |self_| self_.clear_no_drop()); - - if mem::needs_drop::() { - unsafe { - for item in self_.iter() { - item.drop(); - } - } - } - } - - /// Shrinks the table to fit `max(self.len(), min_size)` elements. - #[inline] - pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) { - // Calculate the minimal number of elements that we need to reserve - // space for. - let min_size = usize::max(self.items, min_size); - if min_size == 0 { - *self = Self::new(); - return; - } - - // Calculate the number of buckets that we need for this number of - // elements. If the calculation overflows then the requested bucket - // count must be larger than what we have right and nothing needs to be - // done. - let min_buckets = match capacity_to_buckets(min_size) { - Some(buckets) => buckets, - None => return, - }; - - // If we have more buckets than we need, shrink the table. - if min_buckets < self.buckets() { - // Fast path if the table is empty - if self.items == 0 { - *self = Self::with_capacity(min_size) - } else { - self.resize(min_size, hasher, Fallibility::Infallible) - .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); - } - } - } - - /// Ensures that at least `additional` items can be inserted into the table - /// without reallocation. - #[inline] - pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) { - if additional > self.growth_left { - self.reserve_rehash(additional, hasher, Fallibility::Infallible) - .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); - } - } - - /// Tries to ensure that at least `additional` items can be inserted into - /// the table without reallocation. - #[inline] - pub fn try_reserve( - &mut self, - additional: usize, - hasher: impl Fn(&T) -> u64, - ) -> Result<(), CollectionAllocErr> { - if additional > self.growth_left { - self.reserve_rehash(additional, hasher, Fallibility::Fallible) - } else { - Ok(()) - } - } - - /// Out-of-line slow path for `reserve` and `try_reserve`. - #[cold] - #[inline(never)] - fn reserve_rehash( - &mut self, - additional: usize, - hasher: impl Fn(&T) -> u64, - fallability: Fallibility, - ) -> Result<(), CollectionAllocErr> { - let new_items = self - .items - .checked_add(additional) - .ok_or_else(|| fallability.capacity_overflow())?; - - // Rehash in-place without re-allocating if we have plenty of spare - // capacity that is locked up due to DELETED entries. - if new_items < bucket_mask_to_capacity(self.bucket_mask) / 2 { - self.rehash_in_place(hasher); - Ok(()) - } else { - self.resize(new_items, hasher, fallability) - } - } - - /// Rehashes the contents of the table in place (i.e. without changing the - /// allocation). - /// - /// If `hasher` panics then some the table's contents may be lost. - fn rehash_in_place(&mut self, hasher: impl Fn(&T) -> u64) { - unsafe { - // Bulk convert all full control bytes to DELETED, and all DELETED - // control bytes to EMPTY. This effectively frees up all buckets - // containing a DELETED entry. - for i in (0..self.buckets()).step_by(Group::WIDTH) { - let group = Group::load_aligned(self.ctrl(i)); - let group = group.convert_special_to_empty_and_full_to_deleted(); - group.store_aligned(self.ctrl(i)); - } - - // Fix up the trailing control bytes. See the comments in set_ctrl - // for the handling of tables smaller than the group width. - if self.buckets() < Group::WIDTH { - self.ctrl(0) - .copy_to(self.ctrl(Group::WIDTH), self.buckets()); - } else { - self.ctrl(0) - .copy_to(self.ctrl(self.buckets()), Group::WIDTH); - } - - // If the hash function panics then properly clean up any elements - // that we haven't rehashed yet. We unfortunately can't preserve the - // element since we lost their hash and have no way of recovering it - // without risking another panic. - let mut guard = guard(self, |self_| { - if mem::needs_drop::() { - for i in 0..self_.buckets() { - if *self_.ctrl(i) == DELETED { - self_.set_ctrl(i, EMPTY); - self_.bucket(i).drop(); - self_.items -= 1; - } - } - } - self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items; - }); - - // At this point, DELETED elements are elements that we haven't - // rehashed yet. Find them and re-insert them at their ideal - // position. - 'outer: for i in 0..guard.buckets() { - if *guard.ctrl(i) != DELETED { - continue; - } - 'inner: loop { - // Hash the current item - let item = guard.bucket(i); - let hash = hasher(item.as_ref()); - - // Search for a suitable place to put it - let new_i = guard.find_insert_slot(hash); - - // Probing works by scanning through all of the control - // bytes in groups, which may not be aligned to the group - // size. If both the new and old position fall within the - // same unaligned group, then there is no benefit in moving - // it and we can just continue to the next item. - let probe_index = |pos: usize| { - (pos.wrapping_sub(guard.probe_seq(hash).pos) & guard.bucket_mask) - / Group::WIDTH - }; - if likely(probe_index(i) == probe_index(new_i)) { - guard.set_ctrl(i, h2(hash)); - continue 'outer; - } - - // We are moving the current item to a new position. Write - // our H2 to the control byte of the new position. - let prev_ctrl = *guard.ctrl(new_i); - guard.set_ctrl(new_i, h2(hash)); - - if prev_ctrl == EMPTY { - // If the target slot is empty, simply move the current - // element into the new slot and clear the old control - // byte. - guard.set_ctrl(i, EMPTY); - guard.bucket(new_i).copy_from_nonoverlapping(&item); - continue 'outer; - } else { - // If the target slot is occupied, swap the two elements - // and then continue processing the element that we just - // swapped into the old slot. - debug_assert_eq!(prev_ctrl, DELETED); - mem::swap(guard.bucket(new_i).as_mut(), item.as_mut()); - continue 'inner; - } - } - } - - guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items; - mem::forget(guard); - } - } - - /// Allocates a new table of a different size and moves the contents of the - /// current table into it. - fn resize( - &mut self, - capacity: usize, - hasher: impl Fn(&T) -> u64, - fallability: Fallibility, - ) -> Result<(), CollectionAllocErr> { - unsafe { - debug_assert!(self.items <= capacity); - - // Allocate and initialize the new table. - let mut new_table = Self::try_with_capacity(capacity, fallability)?; - new_table.growth_left -= self.items; - new_table.items = self.items; - - // The hash function may panic, in which case we simply free the new - // table without dropping any elements that may have been copied into - // it. - // - // This guard is also used to free the old table on success, see - // the comment at the bottom of this function. - let mut new_table = guard(ManuallyDrop::new(new_table), |new_table| { - if !new_table.is_empty_singleton() { - new_table.free_buckets(); - } - }); - - // Copy all elements to the new table. - for item in self.iter() { - // This may panic. - let hash = hasher(item.as_ref()); - - // We can use a simpler version of insert() here since: - // - there are no DELETED entries. - // - we know there is enough space in the table. - // - all elements are unique. - let index = new_table.find_insert_slot(hash); - new_table.set_ctrl(index, h2(hash)); - new_table.bucket(index).copy_from_nonoverlapping(&item); - } - - // We successfully copied all elements without panicking. Now replace - // self with the new table. The old table will have its memory freed but - // the items will not be dropped (since they have been moved into the - // new table). - mem::swap(self, &mut new_table); - - Ok(()) - } - } - - /// Inserts a new element into the table. - /// - /// This does not check if the given element already exists in the table. - #[inline] - pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket { - self.reserve(1, hasher); - self.insert_no_grow(hash, value) - } - - /// Inserts a new element into the table, without growing the table. - /// - /// There must be enough space in the table to insert the new element. - /// - /// This does not check if the given element already exists in the table. - #[inline] - pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket { - unsafe { - let index = self.find_insert_slot(hash); - let bucket = self.bucket(index); - - // If we are replacing a DELETED entry then we don't need to update - // the load counter. - let old_ctrl = *self.ctrl(index); - self.growth_left -= special_is_empty(old_ctrl) as usize; - - self.set_ctrl(index, h2(hash)); - bucket.write(value); - self.items += 1; - bucket - } - } - - /// Searches for an element in the table. - #[inline] - pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option> { - unsafe { - for pos in self.probe_seq(hash) { - let group = Group::load(self.ctrl(pos)); - for bit in group.match_byte(h2(hash)) { - let index = (pos + bit) & self.bucket_mask; - let bucket = self.bucket(index); - if likely(eq(bucket.as_ref())) { - return Some(bucket); - } - } - if likely(group.match_empty().any_bit_set()) { - return None; - } - } - } - - // probe_seq never returns. - unreachable!(); - } - - /// Returns the number of elements the map can hold without reallocating. - /// - /// This number is a lower bound; the table might be able to hold - /// more, but is guaranteed to be able to hold at least this many. - #[inline] - pub fn capacity(&self) -> usize { - self.items + self.growth_left - } - - /// Returns the number of elements in the table. - #[inline] - pub fn len(&self) -> usize { - self.items - } - - /// Returns the number of buckets in the table. - #[inline] - pub fn buckets(&self) -> usize { - self.bucket_mask + 1 - } - - /// Returns the number of control bytes in the table. - #[inline] - fn num_ctrl_bytes(&self) -> usize { - self.bucket_mask + 1 + Group::WIDTH - } - - /// Returns whether this table points to the empty singleton with a capacity - /// of 0. - #[inline] - fn is_empty_singleton(&self) -> bool { - self.bucket_mask == 0 - } - - /// Returns an iterator over every element in the table. It is up to - /// the caller to ensure that the `RawTable` outlives the `RawIter`. - /// Because we cannot make the `next` method unsafe on the `RawIter` - /// struct, we have to make the `iter` method unsafe. - #[inline] - pub unsafe fn iter(&self) -> RawIter { - let data = Bucket::from_base_index(self.data.as_ptr(), 0); - RawIter { - iter: RawIterRange::new(self.ctrl.as_ptr(), data, self.buckets()), - items: self.items, - } - } - - /// Returns an iterator which removes all elements from the table without - /// freeing the memory. It is up to the caller to ensure that the `RawTable` - /// outlives the `RawDrain`. Because we cannot make the `next` method unsafe - /// on the `RawDrain`, we have to make the `drain` method unsafe. - #[inline] - pub unsafe fn drain(&mut self) -> RawDrain<'_, T> { - RawDrain { - iter: self.iter(), - table: ManuallyDrop::new(mem::replace(self, Self::new())), - orig_table: NonNull::from(self), - marker: PhantomData, - } - } - - /// Converts the table into a raw allocation. The contents of the table - /// should be dropped using a `RawIter` before freeing the allocation. - #[inline] - pub fn into_alloc(self) -> Option<(NonNull, Layout)> { - let alloc = if self.is_empty_singleton() { - None - } else { - let (layout, _) = calculate_layout::(self.buckets()) - .unwrap_or_else(|| unsafe { hint::unreachable_unchecked() }); - Some((self.ctrl.cast(), layout)) - }; - mem::forget(self); - alloc - } -} - -unsafe impl Send for RawTable where T: Send {} -unsafe impl Sync for RawTable where T: Sync {} - -impl Clone for RawTable { - fn clone(&self) -> Self { - if self.is_empty_singleton() { - Self::new() - } else { - unsafe { - let mut new_table = ManuallyDrop::new( - Self::new_uninitialized(self.buckets(), Fallibility::Infallible) - .unwrap_or_else(|_| hint::unreachable_unchecked()), - ); - - // Copy the control bytes unchanged. We do this in a single pass - self.ctrl(0) - .copy_to_nonoverlapping(new_table.ctrl(0), self.num_ctrl_bytes()); - - { - // The cloning of elements may panic, in which case we need - // to make sure we drop only the elements that have been - // cloned so far. - let mut guard = guard((0, &mut new_table), |(index, new_table)| { - if mem::needs_drop::() { - for i in 0..=*index { - if is_full(*new_table.ctrl(i)) { - new_table.bucket(i).drop(); - } - } - } - new_table.free_buckets(); - }); - - for from in self.iter() { - let index = self.bucket_index(&from); - let to = guard.1.bucket(index); - to.write(from.as_ref().clone()); - - // Update the index in case we need to unwind. - guard.0 = index; - } - - // Successfully cloned all items, no need to clean up. - mem::forget(guard); - } - - // Return the newly created table. - new_table.items = self.items; - new_table.growth_left = self.growth_left; - ManuallyDrop::into_inner(new_table) - } - } - } -} - -#[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T> Drop for RawTable { - #[inline] - fn drop(&mut self) { - if !self.is_empty_singleton() { - unsafe { - if mem::needs_drop::() { - for item in self.iter() { - item.drop(); - } - } - self.free_buckets(); - } - } - } -} -#[cfg(not(feature = "nightly"))] -impl Drop for RawTable { - #[inline] - fn drop(&mut self) { - if !self.is_empty_singleton() { - unsafe { - if mem::needs_drop::() { - for item in self.iter() { - item.drop(); - } - } - self.free_buckets(); - } - } - } -} - -impl IntoIterator for RawTable { - type Item = T; - type IntoIter = RawIntoIter; - - #[inline] - fn into_iter(self) -> RawIntoIter { - unsafe { - let iter = self.iter(); - let alloc = self.into_alloc(); - RawIntoIter { - iter, - alloc, - marker: PhantomData, - } - } - } -} - -/// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does -/// not track an item count. -pub struct RawIterRange { - // Mask of full buckets in the current group. Bits are cleared from this - // mask as each element is processed. - current_group: BitMask, - - // Pointer to the buckets for the current group. - data: Bucket, - - // Pointer to the next group of control bytes, - // Must be aligned to the group size. - next_ctrl: *const u8, - - // Pointer one past the last control byte of this range. - end: *const u8, -} - -impl RawIterRange { - /// Returns a `RawIterRange` covering a subset of a table. - /// - /// The control byte address must be aligned to the group size. - #[inline] - unsafe fn new(ctrl: *const u8, data: Bucket, len: usize) -> Self { - debug_assert_ne!(len, 0); - debug_assert_eq!(ctrl as usize % Group::WIDTH, 0); - let end = ctrl.add(len); - - // Load the first group and advance ctrl to point to the next group - let current_group = Group::load_aligned(ctrl).match_full(); - let next_ctrl = ctrl.add(Group::WIDTH); - - Self { - current_group, - data, - next_ctrl, - end, - } - } - - /// Splits a `RawIterRange` into two halves. - /// - /// Returns `None` if the remaining range is smaller than or equal to the - /// group width. - #[inline] - #[cfg(feature = "rayon")] - pub fn split(mut self) -> (Self, Option>) { - unsafe { - if self.end <= self.next_ctrl { - // Nothing to split if the group that we are current processing - // is the last one. - (self, None) - } else { - // len is the remaining number of elements after the group that - // we are currently processing. It must be a multiple of the - // group size (small tables are caught by the check above). - let len = offset_from(self.end, self.next_ctrl); - debug_assert_eq!(len % Group::WIDTH, 0); - - // Split the remaining elements into two halves, but round the - // midpoint down in case there is an odd number of groups - // remaining. This ensures that: - // - The tail is at least 1 group long. - // - The split is roughly even considering we still have the - // current group to process. - let mid = (len / 2) & !(Group::WIDTH - 1); - - let tail = Self::new( - self.next_ctrl.add(mid), - self.data.add(Group::WIDTH).add(mid), - len - mid, - ); - debug_assert_eq!(self.data.add(Group::WIDTH).add(mid).ptr, tail.data.ptr); - debug_assert_eq!(self.end, tail.end); - self.end = self.next_ctrl.add(mid); - debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl); - (self, Some(tail)) - } - } - } -} - -// We make raw iterators unconditionally Send and Sync, and let the PhantomData -// in the actual iterator implementations determine the real Send/Sync bounds. -unsafe impl Send for RawIterRange {} -unsafe impl Sync for RawIterRange {} - -impl Clone for RawIterRange { - #[inline] - fn clone(&self) -> Self { - Self { - data: self.data.clone(), - next_ctrl: self.next_ctrl, - current_group: self.current_group, - end: self.end, - } - } -} - -impl Iterator for RawIterRange { - type Item = Bucket; - - #[inline] - fn next(&mut self) -> Option> { - unsafe { - loop { - if let Some(index) = self.current_group.lowest_set_bit() { - self.current_group = self.current_group.remove_lowest_bit(); - return Some(self.data.add(index)); - } - - if self.next_ctrl >= self.end { - return None; - } - - // We might read past self.end up to the next group boundary, - // but this is fine because it only occurs on tables smaller - // than the group size where the trailing control bytes are all - // EMPTY. On larger tables self.end is guaranteed to be aligned - // to the group size (since tables are power-of-two sized). - self.current_group = Group::load_aligned(self.next_ctrl).match_full(); - self.data = self.data.add(Group::WIDTH); - self.next_ctrl = self.next_ctrl.add(Group::WIDTH); - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - // We don't have an item count, so just guess based on the range size. - ( - 0, - Some(unsafe { offset_from(self.end, self.next_ctrl) + Group::WIDTH }), - ) - } -} - -impl FusedIterator for RawIterRange {} - -/// Iterator which returns a raw pointer to every full bucket in the table. -pub struct RawIter { - pub iter: RawIterRange, - items: usize, -} - -impl Clone for RawIter { - #[inline] - fn clone(&self) -> Self { - Self { - iter: self.iter.clone(), - items: self.items, - } - } -} - -impl Iterator for RawIter { - type Item = Bucket; - - #[inline] - fn next(&mut self) -> Option> { - if let Some(b) = self.iter.next() { - self.items -= 1; - Some(b) - } else { - // We don't check against items == 0 here to allow the - // compiler to optimize away the item count entirely if the - // iterator length is never queried. - debug_assert_eq!(self.items, 0); - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.items, Some(self.items)) - } -} - -impl ExactSizeIterator for RawIter {} -impl FusedIterator for RawIter {} - -/// Iterator which consumes a table and returns elements. -pub struct RawIntoIter { - iter: RawIter, - alloc: Option<(NonNull, Layout)>, - marker: PhantomData, -} - -impl RawIntoIter { - #[inline] - pub fn iter(&self) -> RawIter { - self.iter.clone() - } -} - -unsafe impl Send for RawIntoIter where T: Send {} -unsafe impl Sync for RawIntoIter where T: Sync {} - -#[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T> Drop for RawIntoIter { - #[inline] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements - if mem::needs_drop::() { - while let Some(item) = self.iter.next() { - item.drop(); - } - } - - // Free the table - if let Some((ptr, layout)) = self.alloc { - dealloc(ptr.as_ptr(), layout); - } - } - } -} -#[cfg(not(feature = "nightly"))] -impl Drop for RawIntoIter { - #[inline] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements - if mem::needs_drop::() { - while let Some(item) = self.iter.next() { - item.drop(); - } - } - - // Free the table - if let Some((ptr, layout)) = self.alloc { - dealloc(ptr.as_ptr(), layout); - } - } - } -} - -impl Iterator for RawIntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - unsafe { Some(self.iter.next()?.read()) } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for RawIntoIter {} -impl FusedIterator for RawIntoIter {} - -/// Iterator which consumes elements without freeing the table storage. -pub struct RawDrain<'a, T> { - iter: RawIter, - - // The table is moved into the iterator for the duration of the drain. This - // ensures that an empty table is left if the drain iterator is leaked - // without dropping. - table: ManuallyDrop>, - orig_table: NonNull>, - - // We don't use a &'a mut RawTable because we want RawDrain to be - // covariant over T. - marker: PhantomData<&'a RawTable>, -} - -impl RawDrain<'_, T> { - #[inline] - pub fn iter(&self) -> RawIter { - self.iter.clone() - } -} - -unsafe impl Send for RawDrain<'_, T> where T: Send {} -unsafe impl Sync for RawDrain<'_, T> where T: Sync {} - -impl Drop for RawDrain<'_, T> { - #[inline] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements. Note that this may panic. - if mem::needs_drop::() { - while let Some(item) = self.iter.next() { - item.drop(); - } - } - - // Reset the contents of the table now that all elements have been - // dropped. - self.table.clear_no_drop(); - - // Move the now empty table back to its original location. - self.orig_table - .as_ptr() - .copy_from_nonoverlapping(&*self.table, 1); - } - } -} - -impl Iterator for RawDrain<'_, T> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - unsafe { - let item = self.iter.next()?; - Some(item.read()) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for RawDrain<'_, T> {} -impl FusedIterator for RawDrain<'_, T> {} diff --git a/vendor/hashbrown-0.4.0/src/raw/sse2.rs b/vendor/hashbrown-0.4.0/src/raw/sse2.rs deleted file mode 100644 index c9a1c54110..0000000000 --- a/vendor/hashbrown-0.4.0/src/raw/sse2.rs +++ /dev/null @@ -1,140 +0,0 @@ -use super::bitmask::BitMask; -use super::EMPTY; -use core::mem; - -#[cfg(target_arch = "x86")] -use core::arch::x86; -#[cfg(target_arch = "x86_64")] -use core::arch::x86_64 as x86; - -pub type BitMaskWord = u16; -pub const BITMASK_STRIDE: usize = 1; -pub const BITMASK_MASK: BitMaskWord = 0xffff; - -/// Abstraction over a group of control bytes which can be scanned in -/// parallel. -/// -/// This implementation uses a 128-bit SSE value. -#[derive(Copy, Clone)] -pub struct Group(x86::__m128i); - -// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859 -#[allow(clippy::use_self)] -impl Group { - /// Number of bytes in the group. - pub const WIDTH: usize = mem::size_of::(); - - /// Returns a full group of empty bytes, suitable for use as the initial - /// value for an empty hash table. - /// - /// This is guaranteed to be aligned to the group size. - #[inline] - pub fn static_empty() -> &'static [u8] { - union AlignedBytes { - _align: Group, - bytes: [u8; Group::WIDTH], - }; - const ALIGNED_BYTES: AlignedBytes = AlignedBytes { - bytes: [EMPTY; Group::WIDTH], - }; - unsafe { &ALIGNED_BYTES.bytes } - } - - /// Loads a group of bytes starting at the given address. - #[inline] - #[allow(clippy::cast_ptr_alignment)] // unaligned load - pub unsafe fn load(ptr: *const u8) -> Self { - Group(x86::_mm_loadu_si128(ptr as *const _)) - } - - /// Loads a group of bytes starting at the given address, which must be - /// aligned to `mem::align_of::()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn load_aligned(ptr: *const u8) -> Self { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::() - 1), 0); - Group(x86::_mm_load_si128(ptr as *const _)) - } - - /// Stores the group of bytes to the given address, which must be - /// aligned to `mem::align_of::()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn store_aligned(self, ptr: *mut u8) { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::() - 1), 0); - x86::_mm_store_si128(ptr as *mut _, self.0); - } - - /// Returns a `BitMask` indicating all bytes in the group which have - /// the given value. - #[inline] - pub fn match_byte(self, byte: u8) -> BitMask { - #[allow( - clippy::cast_possible_wrap, // byte: u8 as i8 - // byte: i32 as u16 - // note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the - // upper 16-bits of the i32 are zeroed: - clippy::cast_sign_loss, - clippy::cast_possible_truncation - )] - unsafe { - let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8)); - BitMask(x86::_mm_movemask_epi8(cmp) as u16) - } - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY`. - #[inline] - pub fn match_empty(self) -> BitMask { - self.match_byte(EMPTY) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY` or `DELETED`. - #[inline] - pub fn match_empty_or_deleted(self) -> BitMask { - #[allow( - // byte: i32 as u16 - // note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the - // upper 16-bits of the i32 are zeroed: - clippy::cast_sign_loss, - clippy::cast_possible_truncation - )] - unsafe { - // A byte is EMPTY or DELETED iff the high bit is set - BitMask(x86::_mm_movemask_epi8(self.0) as u16) - } - } - - /// Returns a `BitMask` indicating all bytes in the group which are full. - #[inline] - pub fn match_full(&self) -> BitMask { - self.match_empty_or_deleted().invert() - } - - /// Performs the following transformation on all bytes in the group: - /// - `EMPTY => EMPTY` - /// - `DELETED => EMPTY` - /// - `FULL => DELETED` - #[inline] - pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self { - // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111 - // and high_bit = 0 (FULL) to 1000_0000 - // - // Here's this logic expanded to concrete values: - // let special = 0 > byte = 1111_1111 (true) or 0000_0000 (false) - // 1111_1111 | 1000_0000 = 1111_1111 - // 0000_0000 | 1000_0000 = 1000_0000 - #[allow( - clippy::cast_possible_wrap, // byte: 0x80_u8 as i8 - )] - unsafe { - let zero = x86::_mm_setzero_si128(); - let special = x86::_mm_cmpgt_epi8(zero, self.0); - Group(x86::_mm_or_si128(special, x86::_mm_set1_epi8(0x80_u8 as i8))) - } - } -} diff --git a/vendor/hashbrown-0.4.0/src/rustc_entry.rs b/vendor/hashbrown-0.4.0/src/rustc_entry.rs deleted file mode 100644 index 5cc3bd51ae..0000000000 --- a/vendor/hashbrown-0.4.0/src/rustc_entry.rs +++ /dev/null @@ -1,573 +0,0 @@ -use self::RustcEntry::*; -use crate::map::{make_hash, Drain, HashMap, IntoIter, Iter, IterMut}; -use crate::raw::{Bucket, RawTable}; -use core::fmt::{self, Debug}; -use core::hash::{BuildHasher, Hash}; -use core::mem; - -impl HashMap -where - K: Eq + Hash, - S: BuildHasher, -{ - /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut letters = HashMap::new(); - /// - /// for ch in "a short treatise on fungi".chars() { - /// let counter = letters.rustc_entry(ch).or_insert(0); - /// *counter += 1; - /// } - /// - /// assert_eq!(letters[&'s'], 2); - /// assert_eq!(letters[&'t'], 3); - /// assert_eq!(letters[&'u'], 1); - /// assert_eq!(letters.get(&'y'), None); - /// ``` - #[inline] - pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V> { - let hash = make_hash(&self.hash_builder, &key); - if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { - RustcEntry::Occupied(RustcOccupiedEntry { - key: Some(key), - elem, - table: &mut self.table, - }) - } else { - // Ideally we would put this in VacantEntry::insert, but Entry is not - // generic over the BuildHasher and adding a generic parameter would be - // a breaking change. - self.reserve(1); - - RustcEntry::Vacant(RustcVacantEntry { - hash, - key, - table: &mut self.table, - }) - } - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This `enum` is constructed from the [`entry`] method on [`HashMap`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`entry`]: struct.HashMap.html#method.rustc_entry -pub enum RustcEntry<'a, K: 'a, V: 'a> { - /// An occupied entry. - Occupied(RustcOccupiedEntry<'a, K, V>), - - /// A vacant entry. - Vacant(RustcVacantEntry<'a, K, V>), -} - -impl Debug for RustcEntry<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), - Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), - } - } -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`RustcEntry`] enum. -/// -/// [`RustcEntry`]: enum.RustcEntry.html -pub struct RustcOccupiedEntry<'a, K, V> { - key: Option, - elem: Bucket<(K, V)>, - table: &'a mut RawTable<(K, V)>, -} - -unsafe impl Send for RustcOccupiedEntry<'_, K, V> -where - K: Send, - V: Send, -{ -} -unsafe impl Sync for RustcOccupiedEntry<'_, K, V> -where - K: Sync, - V: Sync, -{ -} - -impl Debug for RustcOccupiedEntry<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`RustcEntry`] enum. -/// -/// [`RustcEntry`]: enum.RustcEntry.html -pub struct RustcVacantEntry<'a, K, V> { - hash: u64, - key: K, - table: &'a mut RawTable<(K, V)>, -} - -impl Debug for RustcVacantEntry<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntry").field(self.key()).finish() - } -} - -impl<'a, K, V> RustcEntry<'a, K, V> { - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.rustc_entry("poneyland").or_insert(3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.rustc_entry("poneyland").or_insert(10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[inline] - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let s = "hoho".to_string(); - /// - /// map.rustc_entry("poneyland").or_insert_with(|| s); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[inline] - pub fn or_insert_with V>(self, default: F) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), - } - } - - /// Returns a reference to this entry's key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - match *self { - Occupied(ref entry) => entry.key(), - Vacant(ref entry) => entry.key(), - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.rustc_entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.rustc_entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[inline] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Occupied(mut entry) => { - f(entry.get_mut()); - Occupied(entry) - } - Vacant(entry) => Vacant(entry), - } - } -} - -impl<'a, K, V: Default> RustcEntry<'a, K, V> { - /// Ensures a value is in the entry by inserting the default value if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, Option> = HashMap::new(); - /// map.rustc_entry("poneyland").or_default(); - /// - /// assert_eq!(map["poneyland"], None); - /// # } - /// ``` - #[inline] - pub fn or_default(self) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(Default::default()), - } - } -} - -impl<'a, K, V> RustcOccupiedEntry<'a, K, V> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Take the ownership of the key and value from the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// // We delete the entry from the map. - /// o.remove_entry(); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[inline] - pub fn remove_entry(self) -> (K, V) { - unsafe { - self.table.erase_no_drop(&self.elem); - self.elem.read() - } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.get(), &12); - /// } - /// ``` - #[inline] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// If you need a reference to the `RustcOccupiedEntry` which may outlive the - /// destruction of the `RustcEntry` value, see [`into_mut`]. - /// - /// [`into_mut`]: #method.into_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") { - /// *o.get_mut() += 10; - /// assert_eq!(*o.get(), 22); - /// - /// // We can use the same RustcEntry multiple times. - /// *o.get_mut() += 2; - /// } - /// - /// assert_eq!(map["poneyland"], 24); - /// ``` - #[inline] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Converts the RustcOccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// If you need multiple references to the `RustcOccupiedEntry`, see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// *o.into_mut() += 10; - /// } - /// - /// assert_eq!(map["poneyland"], 22); - /// ``` - #[inline] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.insert(15), 12); - /// } - /// - /// assert_eq!(map["poneyland"], 15); - /// ``` - #[inline] - pub fn insert(&mut self, mut value: V) -> V { - let old_value = self.get_mut(); - mem::swap(&mut value, old_value); - value - } - - /// Takes the value out of the entry, and returns it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.remove(), 12); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[inline] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Replaces the entry, returning the old key and value. The new key in the hash map will be - /// the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{RustcEntry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap, u32> = HashMap::new(); - /// map.insert(Rc::new("Stringthing".to_string()), 15); - /// - /// let my_key = Rc::new("Stringthing".to_string()); - /// - /// if let RustcEntry::Occupied(entry) = map.rustc_entry(my_key) { - /// // Also replace the key with a handle to our other key. - /// let (old_key, old_value): (Rc, u32) = entry.replace_entry(16); - /// } - /// - /// ``` - #[inline] - pub fn replace_entry(self, value: V) -> (K, V) { - let entry = unsafe { self.elem.as_mut() }; - - let old_key = mem::replace(&mut entry.0, self.key.unwrap()); - let old_value = mem::replace(&mut entry.1, value); - - (old_key, old_value) - } - - /// Replaces the key in the hash map with the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{RustcEntry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap, u32> = HashMap::new(); - /// let mut known_strings: Vec> = Vec::new(); - /// - /// // Initialise known strings, run program, etc. - /// - /// reclaim_memory(&mut map, &known_strings); - /// - /// fn reclaim_memory(map: &mut HashMap, u32>, known_strings: &[Rc] ) { - /// for s in known_strings { - /// if let RustcEntry::Occupied(entry) = map.rustc_entry(s.clone()) { - /// // Replaces the entry's key with our version of it in `known_strings`. - /// entry.replace_key(); - /// } - /// } - /// } - /// ``` - #[inline] - pub fn replace_key(self) -> K { - let entry = unsafe { self.elem.as_mut() }; - mem::replace(&mut entry.0, self.key.unwrap()) - } -} - -impl<'a, K, V> RustcVacantEntry<'a, K, V> { - /// Gets a reference to the key that would be used when inserting a value - /// through the `RustcVacantEntry`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[inline] - pub fn key(&self) -> &K { - &self.key - } - - /// Take ownership of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") { - /// v.into_key(); - /// } - /// ``` - #[inline] - pub fn into_key(self) -> K { - self.key - } - - /// Sets the value of the entry with the RustcVacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let RustcEntry::Vacant(o) = map.rustc_entry("poneyland") { - /// o.insert(37); - /// } - /// assert_eq!(map["poneyland"], 37); - /// ``` - #[inline] - pub fn insert(self, value: V) -> &'a mut V { - let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); - unsafe { &mut bucket.as_mut().1 } - } -} - -impl IterMut<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[inline] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} - -impl IntoIter { - /// Returns a iterator of references over the remaining items. - #[inline] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} - -impl Drain<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[inline] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} diff --git a/vendor/hashbrown-0.4.0/src/scopeguard.rs b/vendor/hashbrown-0.4.0/src/scopeguard.rs deleted file mode 100644 index 4e9bf045ad..0000000000 --- a/vendor/hashbrown-0.4.0/src/scopeguard.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Extracted from the scopeguard crate -use core::ops::{Deref, DerefMut}; - -pub struct ScopeGuard -where - F: FnMut(&mut T), -{ - dropfn: F, - value: T, -} - -#[inline] -pub fn guard(value: T, dropfn: F) -> ScopeGuard -where - F: FnMut(&mut T), -{ - ScopeGuard { dropfn, value } -} - -impl Deref for ScopeGuard -where - F: FnMut(&mut T), -{ - type Target = T; - #[inline] - fn deref(&self) -> &T { - &self.value - } -} - -impl DerefMut for ScopeGuard -where - F: FnMut(&mut T), -{ - #[inline] - fn deref_mut(&mut self) -> &mut T { - &mut self.value - } -} - -impl Drop for ScopeGuard -where - F: FnMut(&mut T), -{ - #[inline] - fn drop(&mut self) { - (self.dropfn)(&mut self.value) - } -} diff --git a/vendor/hashbrown-0.4.0/src/set.rs b/vendor/hashbrown-0.4.0/src/set.rs deleted file mode 100644 index ade77267ac..0000000000 --- a/vendor/hashbrown-0.4.0/src/set.rs +++ /dev/null @@ -1,1829 +0,0 @@ -use crate::CollectionAllocErr; -use core::borrow::Borrow; -use core::fmt; -use core::hash::{BuildHasher, Hash}; -use core::iter::{Chain, FromIterator, FusedIterator}; -use core::ops::{BitAnd, BitOr, BitXor, Sub}; - -use super::map::{self, DefaultHashBuilder, HashMap, Keys}; - -// Future Optimization (FIXME!) -// ============================= -// -// Iteration over zero sized values is a noop. There is no need -// for `bucket.val` in the case of HashSet. I suppose we would need HKT -// to get rid of it properly. - -/// A hash set implemented as a `HashMap` where the value is `()`. -/// -/// As with the [`HashMap`] type, a `HashSet` requires that the elements -/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by -/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself, -/// it is important that the following property holds: -/// -/// ```text -/// k1 == k2 -> hash(k1) == hash(k2) -/// ``` -/// -/// In other words, if two keys are equal, their hashes must be equal. -/// -/// -/// It is a logic error for an item to be modified in such a way that the -/// item's hash, as determined by the [`Hash`] trait, or its equality, as -/// determined by the [`Eq`] trait, changes while it is in the set. This is -/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or -/// unsafe code. -/// -/// It is also a logic error for the [`Hash`] implementation of a key to panic. -/// This is generally only possible if the trait is implemented manually. If a -/// panic does occur then the contents of the `HashSet` may become corrupted and -/// some items may be dropped from the table. -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashSet; -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashSet` in this example). -/// let mut books = HashSet::new(); -/// -/// // Add some books. -/// books.insert("A Dance With Dragons".to_string()); -/// books.insert("To Kill a Mockingbird".to_string()); -/// books.insert("The Odyssey".to_string()); -/// books.insert("The Great Gatsby".to_string()); -/// -/// // Check for a specific one. -/// if !books.contains("The Winds of Winter") { -/// println!("We have {} books, but The Winds of Winter ain't one.", -/// books.len()); -/// } -/// -/// // Remove a book. -/// books.remove("The Odyssey"); -/// -/// // Iterate over everything. -/// for book in &books { -/// println!("{}", book); -/// } -/// ``` -/// -/// The easiest way to use `HashSet` with a custom type is to derive -/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`], this will in the -/// future be implied by [`Eq`]. -/// -/// ``` -/// use hashbrown::HashSet; -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking { -/// name: String, -/// power: usize, -/// } -/// -/// let mut vikings = HashSet::new(); -/// -/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 }); -/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 }); -/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 }); -/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 }); -/// -/// // Use derived implementation to print the vikings. -/// for x in &vikings { -/// println!("{:?}", x); -/// } -/// ``` -/// -/// A `HashSet` with fixed list of elements can be initialized from an array: -/// -/// ``` -/// use hashbrown::HashSet; -/// -/// fn main() { -/// let viking_names: HashSet<&'static str> = -/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); -/// // use the values stored in the set -/// } -/// ``` -/// -/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html -/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html -/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html -/// [`HashMap`]: struct.HashMap.html -/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html -/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html -#[derive(Clone)] -pub struct HashSet { - pub(crate) map: HashMap, -} - -impl HashSet { - /// Creates an empty `HashSet`. - /// - /// The hash set is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet = HashSet::new(); - /// ``` - #[inline] - pub fn new() -> Self { - Self { - map: HashMap::new(), - } - } - - /// Creates an empty `HashSet` with the specified capacity. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet = HashSet::with_capacity(10); - /// assert!(set.capacity() >= 10); - /// ``` - #[inline] - pub fn with_capacity(capacity: usize) -> Self { - Self { - map: HashMap::with_capacity(capacity), - } - } -} - -impl HashSet { - /// Returns the number of elements the set can hold without reallocating. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet = HashSet::with_capacity(100); - /// assert!(set.capacity() >= 100); - /// ``` - #[inline] - pub fn capacity(&self) -> usize { - self.map.capacity() - } - - /// An iterator visiting all elements in arbitrary order. - /// The iterator element type is `&'a T`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a"); - /// set.insert("b"); - /// - /// // Will print in an arbitrary order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter(&self) -> Iter<'_, T> { - Iter { - iter: self.map.keys(), - } - } - - /// Returns the number of elements in the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> usize { - self.map.len() - } - - /// Returns `true` if the set contains no elements. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - /// Clears the set, returning all elements in an iterator. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert!(!set.is_empty()); - /// - /// // print 1, 2, 3 in an arbitrary order - /// for i in set.drain() { - /// println!("{}", i); - /// } - /// - /// assert!(set.is_empty()); - /// ``` - #[inline] - pub fn drain(&mut self) -> Drain<'_, T> { - Drain { - iter: self.map.drain(), - } - } - - /// Clears the set, removing all values. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { - self.map.clear() - } -} - -impl HashSet -where - T: Eq + Hash, - S: BuildHasher, -{ - /// Creates a new empty hash set which will use the given hasher to hash - /// keys. - /// - /// The hash set is also created with the default initial capacity. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow `HashSet`s to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_hasher(s); - /// set.insert(2); - /// ``` - #[inline] - pub fn with_hasher(hasher: S) -> Self { - Self { - map: HashMap::with_hasher(hasher), - } - } - - /// Creates an empty `HashSet` with the specified capacity, using - /// `hasher` to hash the keys. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow `HashSet`s to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_capacity_and_hasher(10, s); - /// set.insert(1); - /// ``` - #[inline] - pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self { - Self { - map: HashMap::with_capacity_and_hasher(capacity, hasher), - } - } - - /// Returns a reference to the set's [`BuildHasher`]. - /// - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let hasher = DefaultHashBuilder::default(); - /// let set: HashSet = HashSet::with_hasher(hasher); - /// let hasher: &DefaultHashBuilder = set.hasher(); - /// ``` - #[inline] - pub fn hasher(&self) -> &S { - self.map.hasher() - } - - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new allocation size overflows `usize`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// set.reserve(10); - /// assert!(set.capacity() >= 10); - /// ``` - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.map.reserve(additional) - } - - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); - /// ``` - #[inline] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - self.map.try_reserve(additional) - } - - /// Shrinks the capacity of the set as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::with_capacity(100); - /// set.insert(1); - /// set.insert(2); - /// assert!(set.capacity() >= 100); - /// set.shrink_to_fit(); - /// assert!(set.capacity() >= 2); - /// ``` - #[inline] - pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit() - } - - /// Shrinks the capacity of the set with a lower limit. It will drop - /// down no lower than the supplied limit while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// Panics if the current capacity is smaller than the supplied - /// minimum capacity. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::with_capacity(100); - /// set.insert(1); - /// set.insert(2); - /// assert!(set.capacity() >= 100); - /// set.shrink_to(10); - /// assert!(set.capacity() >= 10); - /// set.shrink_to(0); - /// assert!(set.capacity() >= 2); - /// ``` - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.map.shrink_to(min_capacity) - } - - /// Visits the values representing the difference, - /// i.e., the values that are in `self` but not in `other`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Can be seen as `a - b`. - /// for x in a.difference(&b) { - /// println!("{}", x); // Print 1 - /// } - /// - /// let diff: HashSet<_> = a.difference(&b).collect(); - /// assert_eq!(diff, [1].iter().collect()); - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else: - /// let diff: HashSet<_> = b.difference(&a).collect(); - /// assert_eq!(diff, [4].iter().collect()); - /// ``` - #[inline] - pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S> { - Difference { - iter: self.iter(), - other, - } - } - - /// Visits the values representing the symmetric difference, - /// i.e., the values that are in `self` or in `other` but not in both. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 1, 4 in arbitrary order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect(); - /// let diff2: HashSet<_> = b.symmetric_difference(&a).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 4].iter().collect()); - /// ``` - #[inline] - pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S> { - SymmetricDifference { - iter: self.difference(other).chain(other.difference(self)), - } - } - - /// Visits the values representing the intersection, - /// i.e., the values that are both in `self` and `other`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 2, 3 in arbitrary order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let intersection: HashSet<_> = a.intersection(&b).collect(); - /// assert_eq!(intersection, [2, 3].iter().collect()); - /// ``` - #[inline] - pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S> { - Intersection { - iter: self.iter(), - other, - } - } - - /// Visits the values representing the union, - /// i.e., all the values in `self` or `other`, without duplicates. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 1, 2, 3, 4 in arbitrary order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let union: HashSet<_> = a.union(&b).collect(); - /// assert_eq!(union, [1, 2, 3, 4].iter().collect()); - /// ``` - #[inline] - pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S> { - Union { - iter: self.iter().chain(other.difference(self)), - } - } - - /// Returns `true` if the set contains a value. - /// - /// The value may be any borrowed form of the set's value type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the value type. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[inline] - pub fn contains(&self, value: &Q) -> bool - where - T: Borrow, - Q: Hash + Eq, - { - self.map.contains_key(value) - } - - /// Returns a reference to the value in the set, if any, that is equal to the given value. - /// - /// The value may be any borrowed form of the set's value type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the value type. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.get(&2), Some(&2)); - /// assert_eq!(set.get(&4), None); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[inline] - pub fn get(&self, value: &Q) -> Option<&T> - where - T: Borrow, - Q: Hash + Eq, - { - self.map.get_key_value(value).map(|(k, _)| k) - } - - /// Returns `true` if `self` has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut b = HashSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - pub fn is_disjoint(&self, other: &Self) -> bool { - self.iter().all(|v| !other.contains(v)) - } - - /// Returns `true` if the set is a subset of another, - /// i.e., `other` contains at least all the values in `self`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - pub fn is_subset(&self, other: &Self) -> bool { - if self.len() <= other.len() { - self.iter().all(|v| other.contains(v)) - } else { - false - } - } - - /// Returns `true` if the set is a superset of another, - /// i.e., `self` contains at least all the values in `other`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[inline] - pub fn is_superset(&self, other: &Self) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. - /// - /// If the set did not have this value present, `true` is returned. - /// - /// If the set did have this value present, `false` is returned. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[inline] - pub fn insert(&mut self, value: T) -> bool { - self.map.insert(value, ()).is_none() - } - - /// Adds a value to the set, replacing the existing value, if any, that is equal to the given - /// one. Returns the replaced value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// set.insert(Vec::::new()); - /// - /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); - /// set.replace(Vec::with_capacity(10)); - /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); - /// ``` - #[inline] - pub fn replace(&mut self, value: T) -> Option { - match self.map.entry(value) { - map::Entry::Occupied(occupied) => Some(occupied.replace_key()), - map::Entry::Vacant(vacant) => { - vacant.insert(()); - None - } - } - } - - /// Removes a value from the set. Returns whether the value was - /// present in the set. - /// - /// The value may be any borrowed form of the set's value type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the value type. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// set.insert(2); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[inline] - pub fn remove(&mut self, value: &Q) -> bool - where - T: Borrow, - Q: Hash + Eq, - { - self.map.remove(value).is_some() - } - - /// Removes and returns the value in the set, if any, that is equal to the given one. - /// - /// The value may be any borrowed form of the set's value type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the value type. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.take(&2), Some(2)); - /// assert_eq!(set.take(&2), None); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[inline] - pub fn take(&mut self, value: &Q) -> Option - where - T: Borrow, - Q: Hash + Eq, - { - self.map.remove_entry(value).map(|(k, _)| k) - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let xs = [1,2,3,4,5,6]; - /// let mut set: HashSet = xs.iter().cloned().collect(); - /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); - /// ``` - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&T) -> bool, - { - self.map.retain(|k, _| f(k)); - } -} - -impl PartialEq for HashSet -where - T: Eq + Hash, - S: BuildHasher, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - self.iter().all(|key| other.contains(key)) - } -} - -impl Eq for HashSet -where - T: Eq + Hash, - S: BuildHasher, -{ -} - -impl fmt::Debug for HashSet -where - T: Eq + Hash + fmt::Debug, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.iter()).finish() - } -} - -impl FromIterator for HashSet -where - T: Eq + Hash, - S: BuildHasher + Default, -{ - #[inline] - fn from_iter>(iter: I) -> Self { - let mut set = Self::with_hasher(Default::default()); - set.extend(iter); - set - } -} - -impl Extend for HashSet -where - T: Eq + Hash, - S: BuildHasher, -{ - #[inline] - fn extend>(&mut self, iter: I) { - self.map.extend(iter.into_iter().map(|k| (k, ()))); - } -} - -impl<'a, T, S> Extend<&'a T> for HashSet -where - T: 'a + Eq + Hash + Copy, - S: BuildHasher, -{ - #[inline] - fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); - } -} - -impl Default for HashSet -where - T: Eq + Hash, - S: BuildHasher + Default, -{ - /// Creates an empty `HashSet` with the `Default` value for the hasher. - #[inline] - fn default() -> Self { - Self { - map: HashMap::default(), - } - } -} - -impl BitOr<&HashSet> for &HashSet -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet; - - /// Returns the union of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a | &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 3, 4, 5]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitor(self, rhs: &HashSet) -> HashSet { - self.union(rhs).cloned().collect() - } -} - -impl BitAnd<&HashSet> for &HashSet -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet; - - /// Returns the intersection of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect(); - /// - /// let set = &a & &b; - /// - /// let mut i = 0; - /// let expected = [2, 3]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitand(self, rhs: &HashSet) -> HashSet { - self.intersection(rhs).cloned().collect() - } -} - -impl BitXor<&HashSet> for &HashSet -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet; - - /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a ^ &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 4, 5]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitxor(self, rhs: &HashSet) -> HashSet { - self.symmetric_difference(rhs).cloned().collect() - } -} - -impl Sub<&HashSet> for &HashSet -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet; - - /// Returns the difference of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a - &b; - /// - /// let mut i = 0; - /// let expected = [1, 2]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn sub(self, rhs: &HashSet) -> HashSet { - self.difference(rhs).cloned().collect() - } -} - -/// An iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`iter`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`iter`]: struct.HashSet.html#method.iter -pub struct Iter<'a, K> { - iter: Keys<'a, K, ()>, -} - -/// An owning iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`into_iter`] method on [`HashSet`][`HashSet`] -/// (provided by the `IntoIterator` trait). See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`into_iter`]: struct.HashSet.html#method.into_iter -pub struct IntoIter { - iter: map::IntoIter, -} - -/// A draining iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`drain`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`drain`]: struct.HashSet.html#method.drain -pub struct Drain<'a, K> { - iter: map::Drain<'a, K, ()>, -} - -/// A lazy iterator producing elements in the intersection of `HashSet`s. -/// -/// This `struct` is created by the [`intersection`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`intersection`]: struct.HashSet.html#method.intersection -pub struct Intersection<'a, T, S> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet, -} - -/// A lazy iterator producing elements in the difference of `HashSet`s. -/// -/// This `struct` is created by the [`difference`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`difference`]: struct.HashSet.html#method.difference -pub struct Difference<'a, T, S> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet, -} - -/// A lazy iterator producing elements in the symmetric difference of `HashSet`s. -/// -/// This `struct` is created by the [`symmetric_difference`] method on -/// [`HashSet`]. See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference -pub struct SymmetricDifference<'a, T, S> { - iter: Chain, Difference<'a, T, S>>, -} - -/// A lazy iterator producing elements in the union of `HashSet`s. -/// -/// This `struct` is created by the [`union`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`union`]: struct.HashSet.html#method.union -pub struct Union<'a, T, S> { - iter: Chain, Difference<'a, T, S>>, -} - -impl<'a, T, S> IntoIterator for &'a HashSet { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - #[inline] - fn into_iter(self) -> Iter<'a, T> { - self.iter() - } -} - -impl IntoIterator for HashSet { - type Item = T; - type IntoIter = IntoIter; - - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec with a regular `.iter()`. - /// let v: Vec = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in &v { - /// println!("{}", x); - /// } - /// ``` - #[inline] - fn into_iter(self) -> IntoIter { - IntoIter { - iter: self.map.into_iter(), - } - } -} - -impl Clone for Iter<'_, K> { - #[inline] - fn clone(&self) -> Self { - Iter { - iter: self.iter.clone(), - } - } -} -impl<'a, K> Iterator for Iter<'a, K> { - type Item = &'a K; - - #[inline] - fn next(&mut self) -> Option<&'a K> { - self.iter.next() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} -impl<'a, K> ExactSizeIterator for Iter<'a, K> { - #[inline] - fn len(&self) -> usize { - self.iter.len() - } -} -impl FusedIterator for Iter<'_, K> {} - -impl fmt::Debug for Iter<'_, K> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl Iterator for IntoIter { - type Item = K; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|(k, _)| k) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} -impl ExactSizeIterator for IntoIter { - #[inline] - fn len(&self) -> usize { - self.iter.len() - } -} -impl FusedIterator for IntoIter {} - -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let entries_iter = self.iter.iter().map(|(k, _)| k); - f.debug_list().entries(entries_iter).finish() - } -} - -impl Iterator for Drain<'_, K> { - type Item = K; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|(k, _)| k) - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} -impl ExactSizeIterator for Drain<'_, K> { - #[inline] - fn len(&self) -> usize { - self.iter.len() - } -} -impl FusedIterator for Drain<'_, K> {} - -impl fmt::Debug for Drain<'_, K> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let entries_iter = self.iter.iter().map(|(k, _)| k); - f.debug_list().entries(entries_iter).finish() - } -} - -impl Clone for Intersection<'_, T, S> { - #[inline] - fn clone(&self) -> Self { - Intersection { - iter: self.iter.clone(), - ..*self - } - } -} - -impl<'a, T, S> Iterator for Intersection<'a, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ - type Item = &'a T; - - #[inline] - fn next(&mut self) -> Option<&'a T> { - loop { - let elt = self.iter.next()?; - if self.other.contains(elt) { - return Some(elt); - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -impl fmt::Debug for Intersection<'_, T, S> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl FusedIterator for Intersection<'_, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ -} - -impl Clone for Difference<'_, T, S> { - #[inline] - fn clone(&self) -> Self { - Difference { - iter: self.iter.clone(), - ..*self - } - } -} - -impl<'a, T, S> Iterator for Difference<'a, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ - type Item = &'a T; - - #[inline] - fn next(&mut self) -> Option<&'a T> { - loop { - let elt = self.iter.next()?; - if !self.other.contains(elt) { - return Some(elt); - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -impl FusedIterator for Difference<'_, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ -} - -impl fmt::Debug for Difference<'_, T, S> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl Clone for SymmetricDifference<'_, T, S> { - #[inline] - fn clone(&self) -> Self { - SymmetricDifference { - iter: self.iter.clone(), - } - } -} - -impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ - type Item = &'a T; - - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl FusedIterator for SymmetricDifference<'_, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ -} - -impl fmt::Debug for SymmetricDifference<'_, T, S> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl Clone for Union<'_, T, S> { - #[inline] - fn clone(&self) -> Self { - Union { - iter: self.iter.clone(), - } - } -} - -impl FusedIterator for Union<'_, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ -} - -impl fmt::Debug for Union<'_, T, S> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<'a, T, S> Iterator for Union<'a, T, S> -where - T: Eq + Hash, - S: BuildHasher, -{ - type Item = &'a T; - - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[allow(dead_code)] -fn assert_covariance() { - fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> { - v - } - fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { - v - } - fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { - v - } - fn difference<'a, 'new>( - v: Difference<'a, &'static str, DefaultHashBuilder>, - ) -> Difference<'a, &'new str, DefaultHashBuilder> { - v - } - fn symmetric_difference<'a, 'new>( - v: SymmetricDifference<'a, &'static str, DefaultHashBuilder>, - ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder> { - v - } - fn intersection<'a, 'new>( - v: Intersection<'a, &'static str, DefaultHashBuilder>, - ) -> Intersection<'a, &'new str, DefaultHashBuilder> { - v - } - fn union<'a, 'new>( - v: Union<'a, &'static str, DefaultHashBuilder>, - ) -> Union<'a, &'new str, DefaultHashBuilder> { - v - } - fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { - d - } -} - -#[cfg(test)] -mod test_set { - use super::super::map::DefaultHashBuilder; - use super::HashSet; - use std::vec::Vec; - - #[test] - fn test_zero_capacities() { - type HS = HashSet; - - let s = HS::new(); - assert_eq!(s.capacity(), 0); - - let s = HS::default(); - assert_eq!(s.capacity(), 0); - - let s = HS::with_hasher(DefaultHashBuilder::default()); - assert_eq!(s.capacity(), 0); - - let s = HS::with_capacity(0); - assert_eq!(s.capacity(), 0); - - let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default()); - assert_eq!(s.capacity(), 0); - - let mut s = HS::new(); - s.insert(1); - s.insert(2); - s.remove(&1); - s.remove(&2); - s.shrink_to_fit(); - assert_eq!(s.capacity(), 0); - - let mut s = HS::new(); - s.reserve(0); - assert_eq!(s.capacity(), 0); - } - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in 0..32 { - assert!(a.insert(i)); - } - let mut observed: u32 = 0; - for k in &a { - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let mut i = 0; - let expected = [3, 5, 11, 77]; - for x in a.intersection(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let mut i = 0; - let expected = [1, 5, 11]; - for x in a.difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let mut i = 0; - let expected = [-2, 1, 5, 11, 14, 22]; - for x in a.symmetric_difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let mut i = 0; - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - for x in a.union(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet<_> = xs.iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_iter().collect::>(); - assert!(v == ['a', 'b'] || v == ['b', 'a']); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1); - s2.insert(2); - - assert!(s1 != s2); - - s2.insert(3); - - assert_eq!(s1, s2); - } - - #[test] - fn test_show() { - let mut set = HashSet::new(); - let empty = HashSet::::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_trivial_drain() { - let mut s = HashSet::::new(); - for _ in s.drain() {} - assert!(s.is_empty()); - drop(s); - - let mut s = HashSet::::new(); - drop(s.drain()); - assert!(s.is_empty()); - } - - #[test] - fn test_drain() { - let mut s: HashSet<_> = (1..100).collect(); - - // try this a bunch of times to make sure we don't screw up internal state. - for _ in 0..20 { - assert_eq!(s.len(), 99); - - { - let mut last_i = 0; - let mut d = s.drain(); - for (i, x) in d.by_ref().take(50).enumerate() { - last_i = i; - assert!(x != 0); - } - assert_eq!(last_i, 49); - } - - for _ in &s { - panic!("s should be empty!"); - } - - // reset to try again. - s.extend(1..100); - } - } - - #[test] - fn test_replace() { - use core::hash; - - #[derive(Debug)] - struct Foo(&'static str, i32); - - impl PartialEq for Foo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl Eq for Foo {} - - impl hash::Hash for Foo { - fn hash(&self, h: &mut H) { - self.0.hash(h); - } - } - - let mut s = HashSet::new(); - assert_eq!(s.replace(Foo("a", 1)), None); - assert_eq!(s.len(), 1); - assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); - assert_eq!(s.len(), 1); - - let mut it = s.iter(); - assert_eq!(it.next(), Some(&Foo("a", 2))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_extend_ref() { - let mut a = HashSet::new(); - a.insert(1); - - a.extend(&[2, 3, 4]); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - - let mut b = HashSet::new(); - b.insert(5); - b.insert(6); - - a.extend(&b); - - assert_eq!(a.len(), 6); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - assert!(a.contains(&5)); - assert!(a.contains(&6)); - } - - #[test] - fn test_retain() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut set: HashSet = xs.iter().cloned().collect(); - set.retain(|&k| k % 2 == 0); - assert_eq!(set.len(), 3); - assert!(set.contains(&2)); - assert!(set.contains(&4)); - assert!(set.contains(&6)); - } -} diff --git a/vendor/hashbrown-0.4.0/tests/hasher.rs b/vendor/hashbrown-0.4.0/tests/hasher.rs deleted file mode 100644 index e455e3d3c9..0000000000 --- a/vendor/hashbrown-0.4.0/tests/hasher.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Sanity check that alternate hashers work correctly. - -#![cfg(not(miri))] // FIXME: takes too long - -use hashbrown::HashSet; -use std::hash::{BuildHasher, BuildHasherDefault, Hasher}; - -fn check() { - let range = 0..1_000; - - let mut set = HashSet::::default(); - set.extend(range.clone()); - - assert!(!set.contains(&i32::min_value())); - assert!(!set.contains(&(range.start - 1))); - for i in range.clone() { - assert!(set.contains(&i)); - } - assert!(!set.contains(&range.end)); - assert!(!set.contains(&i32::max_value())); -} - -/// Use hashbrown's default hasher. -#[test] -fn default() { - check::(); -} - -/// Use std's default hasher. -#[test] -fn random_state() { - check::(); -} - -/// Use a constant 0 hash. -#[test] -fn zero() { - #[derive(Default)] - struct ZeroHasher; - - impl Hasher for ZeroHasher { - fn finish(&self) -> u64 { - 0 - } - fn write(&mut self, _: &[u8]) {} - } - - check::>(); -} - -/// Use a constant maximum hash. -#[test] -fn max() { - #[derive(Default)] - struct MaxHasher; - - impl Hasher for MaxHasher { - fn finish(&self) -> u64 { - u64::max_value() - } - fn write(&mut self, _: &[u8]) {} - } - - check::>(); -} diff --git a/vendor/hashbrown-0.4.0/tests/rayon.rs b/vendor/hashbrown-0.4.0/tests/rayon.rs deleted file mode 100644 index 39b47708dd..0000000000 --- a/vendor/hashbrown-0.4.0/tests/rayon.rs +++ /dev/null @@ -1,533 +0,0 @@ -#![cfg(feature = "rayon")] - -#[macro_use] -extern crate lazy_static; - -use hashbrown::{HashMap, HashSet}; -use rayon::iter::{ - IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelExtend, - ParallelIterator, -}; - -macro_rules! assert_eq3 { - ($e1:expr, $e2:expr, $e3:expr) => {{ - assert_eq!($e1, $e2); - assert_eq!($e1, $e3); - assert_eq!($e2, $e3); - }}; -} - -lazy_static! { - static ref MAP_EMPTY: HashMap = HashMap::new(); - static ref MAP: HashMap = { - let mut m = HashMap::new(); - m.insert('b', 20); - m.insert('a', 10); - m.insert('c', 30); - m.insert('e', 50); - m.insert('f', 60); - m.insert('d', 40); - m - }; -} - -#[test] -fn map_seq_par_equivalence_iter_empty() { - let vec_seq = MAP_EMPTY.iter().collect::>(); - let vec_par = MAP_EMPTY.par_iter().collect::>(); - - assert_eq3!(vec_seq, vec_par, []); -} - -#[test] -fn map_seq_par_equivalence_iter() { - let mut vec_seq = MAP.iter().collect::>(); - let mut vec_par = MAP.par_iter().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [ - (&'a', &10), - (&'b', &20), - (&'c', &30), - (&'d', &40), - (&'e', &50), - (&'f', &60), - ]; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn map_seq_par_equivalence_keys_empty() { - let vec_seq = MAP_EMPTY.keys().collect::>(); - let vec_par = MAP_EMPTY.par_keys().collect::>(); - - let expected: [&char; 0] = []; - - assert_eq3!(vec_seq, vec_par, expected); -} - -#[test] -fn map_seq_par_equivalence_keys() { - let mut vec_seq = MAP.keys().collect::>(); - let mut vec_par = MAP.par_keys().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f']; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn map_seq_par_equivalence_values_empty() { - let vec_seq = MAP_EMPTY.values().collect::>(); - let vec_par = MAP_EMPTY.par_values().collect::>(); - - let expected: [&u32; 0] = []; - - assert_eq3!(vec_seq, vec_par, expected); -} - -#[test] -fn map_seq_par_equivalence_values() { - let mut vec_seq = MAP.values().collect::>(); - let mut vec_par = MAP.par_values().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [&10, &20, &30, &40, &50, &60]; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn map_seq_par_equivalence_iter_mut_empty() { - let mut map1 = MAP_EMPTY.clone(); - let mut map2 = MAP_EMPTY.clone(); - - let vec_seq = map1.iter_mut().collect::>(); - let vec_par = map2.par_iter_mut().collect::>(); - - assert_eq3!(vec_seq, vec_par, []); -} - -#[test] -fn map_seq_par_equivalence_iter_mut() { - let mut map1 = MAP.clone(); - let mut map2 = MAP.clone(); - - let mut vec_seq = map1.iter_mut().collect::>(); - let mut vec_par = map2.par_iter_mut().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [ - (&'a', &mut 10), - (&'b', &mut 20), - (&'c', &mut 30), - (&'d', &mut 40), - (&'e', &mut 50), - (&'f', &mut 60), - ]; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn map_seq_par_equivalence_values_mut_empty() { - let mut map1 = MAP_EMPTY.clone(); - let mut map2 = MAP_EMPTY.clone(); - - let vec_seq = map1.values_mut().collect::>(); - let vec_par = map2.par_values_mut().collect::>(); - - let expected: [&u32; 0] = []; - - assert_eq3!(vec_seq, vec_par, expected); -} - -#[test] -fn map_seq_par_equivalence_values_mut() { - let mut map1 = MAP.clone(); - let mut map2 = MAP.clone(); - - let mut vec_seq = map1.values_mut().collect::>(); - let mut vec_par = map2.par_values_mut().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [&mut 10, &mut 20, &mut 30, &mut 40, &mut 50, &mut 60]; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn map_seq_par_equivalence_into_iter_empty() { - let vec_seq = MAP_EMPTY.clone().into_iter().collect::>(); - let vec_par = MAP_EMPTY.clone().into_par_iter().collect::>(); - - assert_eq3!(vec_seq, vec_par, []); -} - -#[test] -fn map_seq_par_equivalence_into_iter() { - let mut vec_seq = MAP.clone().into_iter().collect::>(); - let mut vec_par = MAP.clone().into_par_iter().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [ - ('a', 10), - ('b', 20), - ('c', 30), - ('d', 40), - ('e', 50), - ('f', 60), - ]; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -lazy_static! { - static ref MAP_VEC_EMPTY: Vec<(char, u32)> = vec![]; - static ref MAP_VEC: Vec<(char, u32)> = vec![ - ('b', 20), - ('a', 10), - ('c', 30), - ('e', 50), - ('f', 60), - ('d', 40), - ]; -} - -#[test] -fn map_seq_par_equivalence_collect_empty() { - let map_expected = MAP_EMPTY.clone(); - let map_seq = MAP_VEC_EMPTY.clone().into_iter().collect::>(); - let map_par = MAP_VEC_EMPTY - .clone() - .into_par_iter() - .collect::>(); - - assert_eq!(map_seq, map_par); - assert_eq!(map_seq, map_expected); - assert_eq!(map_par, map_expected); -} - -#[test] -fn map_seq_par_equivalence_collect() { - let map_expected = MAP.clone(); - let map_seq = MAP_VEC.clone().into_iter().collect::>(); - let map_par = MAP_VEC.clone().into_par_iter().collect::>(); - - assert_eq!(map_seq, map_par); - assert_eq!(map_seq, map_expected); - assert_eq!(map_par, map_expected); -} - -lazy_static! { - static ref MAP_EXISTING_EMPTY: HashMap = HashMap::new(); - static ref MAP_EXISTING: HashMap = { - let mut m = HashMap::new(); - m.insert('b', 20); - m.insert('a', 10); - m - }; - static ref MAP_EXTENSION_EMPTY: Vec<(char, u32)> = vec![]; - static ref MAP_EXTENSION: Vec<(char, u32)> = vec![('c', 30), ('e', 50), ('f', 60), ('d', 40),]; -} - -#[test] -fn map_seq_par_equivalence_existing_empty_extend_empty() { - let expected = HashMap::new(); - let mut map_seq = MAP_EXISTING_EMPTY.clone(); - let mut map_par = MAP_EXISTING_EMPTY.clone(); - - map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned()); - map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned()); - - assert_eq3!(map_seq, map_par, expected); -} - -#[test] -fn map_seq_par_equivalence_existing_empty_extend() { - let expected = MAP_EXTENSION.iter().cloned().collect::>(); - let mut map_seq = MAP_EXISTING_EMPTY.clone(); - let mut map_par = MAP_EXISTING_EMPTY.clone(); - - map_seq.extend(MAP_EXTENSION.iter().cloned()); - map_par.par_extend(MAP_EXTENSION.par_iter().cloned()); - - assert_eq3!(map_seq, map_par, expected); -} - -#[test] -fn map_seq_par_equivalence_existing_extend_empty() { - let expected = MAP_EXISTING.clone(); - let mut map_seq = MAP_EXISTING.clone(); - let mut map_par = MAP_EXISTING.clone(); - - map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned()); - map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned()); - - assert_eq3!(map_seq, map_par, expected); -} - -#[test] -fn map_seq_par_equivalence_existing_extend() { - let expected = MAP.clone(); - let mut map_seq = MAP_EXISTING.clone(); - let mut map_par = MAP_EXISTING.clone(); - - map_seq.extend(MAP_EXTENSION.iter().cloned()); - map_par.par_extend(MAP_EXTENSION.par_iter().cloned()); - - assert_eq3!(map_seq, map_par, expected); -} - -lazy_static! { - static ref SET_EMPTY: HashSet = HashSet::new(); - static ref SET: HashSet = { - let mut s = HashSet::new(); - s.insert('b'); - s.insert('a'); - s.insert('c'); - s.insert('e'); - s.insert('f'); - s.insert('d'); - s - }; -} - -#[test] -fn set_seq_par_equivalence_iter_empty() { - let vec_seq = SET_EMPTY.iter().collect::>(); - let vec_par = SET_EMPTY.par_iter().collect::>(); - - let expected: [&char; 0] = []; - - assert_eq3!(vec_seq, vec_par, expected); -} - -#[test] -fn set_seq_par_equivalence_iter() { - let mut vec_seq = SET.iter().collect::>(); - let mut vec_par = SET.par_iter().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f']; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -#[test] -fn set_seq_par_equivalence_into_iter_empty() { - let vec_seq = SET_EMPTY.clone().into_iter().collect::>(); - let vec_par = SET_EMPTY.clone().into_par_iter().collect::>(); - - assert_eq3!(vec_seq, vec_par, []); -} - -#[test] -fn set_seq_par_equivalence_into_iter() { - let mut vec_seq = SET.clone().into_iter().collect::>(); - let mut vec_par = SET.clone().into_par_iter().collect::>(); - - assert_eq!(vec_seq, vec_par); - - // Do not depend on the exact order of values - let expected_sorted = ['a', 'b', 'c', 'd', 'e', 'f']; - - vec_seq.sort_unstable(); - vec_par.sort_unstable(); - - assert_eq3!(vec_seq, vec_par, expected_sorted); -} - -lazy_static! { - static ref SET_VEC_EMPTY: Vec = vec![]; - static ref SET_VEC: Vec = vec!['b', 'a', 'c', 'e', 'f', 'd',]; -} - -#[test] -fn set_seq_par_equivalence_collect_empty() { - let set_expected = SET_EMPTY.clone(); - let set_seq = SET_VEC_EMPTY.clone().into_iter().collect::>(); - let set_par = SET_VEC_EMPTY - .clone() - .into_par_iter() - .collect::>(); - - assert_eq!(set_seq, set_par); - assert_eq!(set_seq, set_expected); - assert_eq!(set_par, set_expected); -} - -#[test] -fn set_seq_par_equivalence_collect() { - let set_expected = SET.clone(); - let set_seq = SET_VEC.clone().into_iter().collect::>(); - let set_par = SET_VEC.clone().into_par_iter().collect::>(); - - assert_eq!(set_seq, set_par); - assert_eq!(set_seq, set_expected); - assert_eq!(set_par, set_expected); -} - -lazy_static! { - static ref SET_EXISTING_EMPTY: HashSet = HashSet::new(); - static ref SET_EXISTING: HashSet = { - let mut s = HashSet::new(); - s.insert('b'); - s.insert('a'); - s - }; - static ref SET_EXTENSION_EMPTY: Vec = vec![]; - static ref SET_EXTENSION: Vec = vec!['c', 'e', 'f', 'd',]; -} - -#[test] -fn set_seq_par_equivalence_existing_empty_extend_empty() { - let expected = HashSet::new(); - let mut set_seq = SET_EXISTING_EMPTY.clone(); - let mut set_par = SET_EXISTING_EMPTY.clone(); - - set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned()); - set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned()); - - assert_eq3!(set_seq, set_par, expected); -} - -#[test] -fn set_seq_par_equivalence_existing_empty_extend() { - let expected = SET_EXTENSION.iter().cloned().collect::>(); - let mut set_seq = SET_EXISTING_EMPTY.clone(); - let mut set_par = SET_EXISTING_EMPTY.clone(); - - set_seq.extend(SET_EXTENSION.iter().cloned()); - set_par.par_extend(SET_EXTENSION.par_iter().cloned()); - - assert_eq3!(set_seq, set_par, expected); -} - -#[test] -fn set_seq_par_equivalence_existing_extend_empty() { - let expected = SET_EXISTING.clone(); - let mut set_seq = SET_EXISTING.clone(); - let mut set_par = SET_EXISTING.clone(); - - set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned()); - set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned()); - - assert_eq3!(set_seq, set_par, expected); -} - -#[test] -fn set_seq_par_equivalence_existing_extend() { - let expected = SET.clone(); - let mut set_seq = SET_EXISTING.clone(); - let mut set_par = SET_EXISTING.clone(); - - set_seq.extend(SET_EXTENSION.iter().cloned()); - set_par.par_extend(SET_EXTENSION.par_iter().cloned()); - - assert_eq3!(set_seq, set_par, expected); -} - -lazy_static! { - static ref SET_A: HashSet = ['a', 'b', 'c', 'd'].iter().cloned().collect(); - static ref SET_B: HashSet = ['a', 'b', 'e', 'f'].iter().cloned().collect(); - static ref SET_DIFF_AB: HashSet = ['c', 'd'].iter().cloned().collect(); - static ref SET_DIFF_BA: HashSet = ['e', 'f'].iter().cloned().collect(); - static ref SET_SYMM_DIFF_AB: HashSet = ['c', 'd', 'e', 'f'].iter().cloned().collect(); - static ref SET_INTERSECTION_AB: HashSet = ['a', 'b'].iter().cloned().collect(); - static ref SET_UNION_AB: HashSet = - ['a', 'b', 'c', 'd', 'e', 'f'].iter().cloned().collect(); -} - -#[test] -fn set_seq_par_equivalence_difference() { - let diff_ab_seq = SET_A.difference(&*SET_B).cloned().collect::>(); - let diff_ab_par = SET_A - .par_difference(&*SET_B) - .cloned() - .collect::>(); - - assert_eq3!(diff_ab_seq, diff_ab_par, *SET_DIFF_AB); - - let diff_ba_seq = SET_B.difference(&*SET_A).cloned().collect::>(); - let diff_ba_par = SET_B - .par_difference(&*SET_A) - .cloned() - .collect::>(); - - assert_eq3!(diff_ba_seq, diff_ba_par, *SET_DIFF_BA); -} - -#[test] -fn set_seq_par_equivalence_symmetric_difference() { - let symm_diff_ab_seq = SET_A - .symmetric_difference(&*SET_B) - .cloned() - .collect::>(); - let symm_diff_ab_par = SET_A - .par_symmetric_difference(&*SET_B) - .cloned() - .collect::>(); - - assert_eq3!(symm_diff_ab_seq, symm_diff_ab_par, *SET_SYMM_DIFF_AB); -} - -#[test] -fn set_seq_par_equivalence_intersection() { - let intersection_ab_seq = SET_A.intersection(&*SET_B).cloned().collect::>(); - let intersection_ab_par = SET_A - .par_intersection(&*SET_B) - .cloned() - .collect::>(); - - assert_eq3!( - intersection_ab_seq, - intersection_ab_par, - *SET_INTERSECTION_AB - ); -} - -#[test] -fn set_seq_par_equivalence_union() { - let union_ab_seq = SET_A.union(&*SET_B).cloned().collect::>(); - let union_ab_par = SET_A.par_union(&*SET_B).cloned().collect::>(); - - assert_eq3!(union_ab_seq, union_ab_par, *SET_UNION_AB); -} diff --git a/vendor/hashbrown-0.4.0/tests/serde.rs b/vendor/hashbrown-0.4.0/tests/serde.rs deleted file mode 100644 index f32cd98481..0000000000 --- a/vendor/hashbrown-0.4.0/tests/serde.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![cfg(feature = "serde")] - -use hashbrown::{HashMap, HashSet}; -use serde_test::{assert_tokens, Token}; - -#[test] -fn map_serde_tokens_empty() { - let map = HashMap::::new(); - - assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); -} - -#[test] -fn map_serde_tokens() { - let mut map = HashMap::new(); - map.insert('b', 20); - map.insert('a', 10); - map.insert('c', 30); - - assert_tokens( - &map, - &[ - Token::Map { len: Some(3) }, - Token::Char('a'), - Token::I32(10), - Token::Char('b'), - Token::I32(20), - Token::Char('c'), - Token::I32(30), - Token::MapEnd, - ], - ); -} - -#[test] -fn set_serde_tokens_empty() { - let set = HashSet::::new(); - - assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]); -} - -#[test] -fn set_serde_tokens() { - let mut set = HashSet::new(); - set.insert(20); - set.insert(10); - set.insert(30); - - assert_tokens( - &set, - &[ - Token::Seq { len: Some(3) }, - Token::I32(20), - Token::I32(10), - Token::I32(30), - Token::SeqEnd, - ], - ); -} diff --git a/vendor/hashbrown-0.4.0/tests/set.rs b/vendor/hashbrown-0.4.0/tests/set.rs deleted file mode 100644 index 332f3f6f07..0000000000 --- a/vendor/hashbrown-0.4.0/tests/set.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![cfg(not(miri))] // FIXME: takes too long - -use hashbrown::HashSet; -use rand::{distributions::Alphanumeric, Rng, SeedableRng, XorShiftRng}; - -#[test] -fn test_hashset_insert_remove() { - let mut m: HashSet> = HashSet::new(); - //let num: u32 = 4096; - //let tx: Vec> = (0..num).map(|i| (i..(16 + i)).collect()).collect(); - let seed: [u8; 16] = [ - 130, 220, 246, 217, 111, 124, 221, 189, 190, 234, 121, 93, 67, 95, 100, 43, - ]; - - let mut rng: XorShiftRng = SeedableRng::from_seed(seed); - //let mut rng: XorShiftRng = XorShiftRng::new_unseeded(); - let tx: Vec> = (0..4096) - .map(|_| (rng.sample_iter(&Alphanumeric).take(32).collect())) - .collect(); - - for _ in 0..32 { - for i in 0..4096 { - assert_eq!(m.contains(&tx[i].clone()), false); - assert_eq!(m.insert(tx[i].clone()), true); - } - for i in 0..4096 { - println!("removing {} {:?}", i, tx[i]); - assert_eq!(m.remove(&tx[i]), true); - } - } -} diff --git a/vendor/kernel32-sys/.cargo-checksum.json b/vendor/kernel32-sys/.cargo-checksum.json new file mode 100644 index 0000000000..55bf9d9dde --- /dev/null +++ b/vendor/kernel32-sys/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"79c920ca9323e28acd5f5a80f2ce0ab81aa6227584397a9f742e78dce36a2117","README.md":"00afb50f0a5a7d548e40feb1f09ce8fa678b46e04c9a72d909fa36fb85fb2200","build.rs":"89e77c6e9e79dcd782fd006431b948d093ec4aeda3b69a280ec857077b7f2020","src/lib.rs":"ab0a8a104a6f747f6389a70d26a62e156ab97cc7c8f4daf1de99b820024da993"},"package":"7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"} \ No newline at end of file diff --git a/vendor/kernel32-sys/Cargo.toml b/vendor/kernel32-sys/Cargo.toml new file mode 100644 index 0000000000..5d28426f34 --- /dev/null +++ b/vendor/kernel32-sys/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "kernel32-sys" +version = "0.2.2" +authors = ["Peter Atashian "] +description = "Contains function definitions for the Windows API library kernel32. See winapi for types and constants." +documentation = "https://retep998.github.io/doc/kernel32/" +repository = "https://github.com/retep998/winapi-rs" +readme = "README.md" +keywords = ["windows", "ffi", "win32"] +license = "MIT" +build = "build.rs" +[lib] +name = "kernel32" +[dependencies] +winapi = { version = "0.2.5", path = "../.." } +[build-dependencies] +winapi-build = { version = "0.1.1", path = "../../build" } diff --git a/vendor/kernel32-sys/README.md b/vendor/kernel32-sys/README.md new file mode 100644 index 0000000000..07ee5a6d6f --- /dev/null +++ b/vendor/kernel32-sys/README.md @@ -0,0 +1,13 @@ +# kernel32 # +Contains function definitions for the Windows API library kernel32. See winapi for types and constants. + +```toml +[dependencies] +kernel32-sys = "0.2.1" +``` + +```rust +extern crate kernel32; +``` + +[Documentation](https://retep998.github.io/doc/kernel32/) diff --git a/vendor/kernel32-sys/build.rs b/vendor/kernel32-sys/build.rs new file mode 100644 index 0000000000..cf323fc2e5 --- /dev/null +++ b/vendor/kernel32-sys/build.rs @@ -0,0 +1,6 @@ +// Copyright © 2015, Peter Atashian +// Licensed under the MIT License +extern crate build; +fn main() { + build::link("kernel32", false) +} diff --git a/vendor/kernel32-sys/src/lib.rs b/vendor/kernel32-sys/src/lib.rs new file mode 100644 index 0000000000..ca7683594c --- /dev/null +++ b/vendor/kernel32-sys/src/lib.rs @@ -0,0 +1,2754 @@ +// Copyright © 2015, Peter Atashian +// Licensed under the MIT License +//! FFI bindings to kernel32. +#![cfg(windows)] +extern crate winapi; +use winapi::*; +extern "system" { + pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK); + pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK); + pub fn ActivateActCtx(hActCtx: HANDLE, lpCookie: *mut ULONG_PTR) -> BOOL; + pub fn AddAtomA(lpString: LPCSTR) -> ATOM; + pub fn AddAtomW(lpString: LPCWSTR) -> ATOM; + pub fn AddConsoleAliasA(Source: LPSTR, Target: LPSTR, ExeName: LPSTR) -> BOOL; + pub fn AddConsoleAliasW(Source: LPWSTR, Target: LPWSTR, ExeName: LPWSTR) -> BOOL; + pub fn AddDllDirectory(NewDirectory: PCWSTR) -> DLL_DIRECTORY_COOKIE; + pub fn AddIntegrityLabelToBoundaryDescriptor( + BoundaryDescriptor: *mut HANDLE, IntegrityLabel: PSID, + ) -> BOOL; + // pub fn AddLocalAlternateComputerNameA(); + // pub fn AddLocalAlternateComputerNameW(); + pub fn AddRefActCtx(hActCtx: HANDLE); + pub fn AddResourceAttributeAce( + pAcl: PACL, dwAceRevision: DWORD, AceFlags: DWORD, AccessMask: DWORD, pSid: PSID, + pAttributeInfo: PCLAIM_SECURITY_ATTRIBUTES_INFORMATION, pReturnLength: PDWORD, + ) -> BOOL; + pub fn AddSIDToBoundaryDescriptor(BoundaryDescriptor: *mut HANDLE, RequiredSid: PSID) -> BOOL; + pub fn AddScopedPolicyIDAce( + pAcl: PACL, dwAceRevision: DWORD, AceFlags: DWORD, AccessMask: DWORD, pSid: PSID, + ) -> BOOL; + pub fn AddSecureMemoryCacheCallback(pfnCallBack: PSECURE_MEMORY_CACHE_CALLBACK) -> BOOL; + pub fn AddVectoredContinueHandler(First: ULONG, Handler: PVECTORED_EXCEPTION_HANDLER) -> PVOID; + pub fn AddVectoredExceptionHandler( + First: ULONG, Handler: PVECTORED_EXCEPTION_HANDLER, + ) -> PVOID; + pub fn AllocConsole() -> BOOL; + pub fn AllocateUserPhysicalPages( + hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, + ) -> BOOL; + pub fn AllocateUserPhysicalPagesNuma( + hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, nndPreferred: DWORD, + ) -> BOOL; + // pub fn AppXGetOSMaxVersionTested(); + pub fn ApplicationRecoveryFinished(bSuccess: BOOL); + pub fn ApplicationRecoveryInProgress(pbCancelled: PBOOL) -> HRESULT; + pub fn AreFileApisANSI() -> BOOL; + pub fn AssignProcessToJobObject(hJob: HANDLE, hProcess: HANDLE) -> BOOL; + pub fn AttachConsole(dwProcessId: DWORD) -> BOOL; + pub fn BackupRead( + hFile: HANDLE, lpBuffer: LPBYTE, nNumberOfBytesToRead: DWORD, lpNumberOfBytesRead: LPDWORD, + bAbort: BOOL, bProcessSecurity: BOOL, lpContext: *mut LPVOID, + ) -> BOOL; + pub fn BackupSeek( + hFile: HANDLE, dwLowBytesToSeek: DWORD, dwHighBytesToSeek: DWORD, + lpdwLowByteSeeked: LPDWORD, lpdwHighByteSeeked: LPDWORD, lpContext: *mut LPVOID, + ) -> BOOL; + pub fn BackupWrite( + hFile: HANDLE, lpBuffer: LPBYTE, nNumberOfBytesToWrite: DWORD, + lpNumberOfBytesWritten: LPDWORD, bAbort: BOOL, bProcessSecurity: BOOL, + lpContext: *mut LPVOID, + ) -> BOOL; + // pub fn BaseSetLastNTError(); + pub fn Beep(dwFreq: DWORD, dwDuration: DWORD) -> BOOL; + pub fn BeginUpdateResourceA(pFileName: LPCSTR, bDeleteExistingResources: BOOL) -> HANDLE; + pub fn BeginUpdateResourceW(pFileName: LPCWSTR, bDeleteExistingResources: BOOL) -> HANDLE; + pub fn BindIoCompletionCallback( + FileHandle: HANDLE, Function: LPOVERLAPPED_COMPLETION_ROUTINE, Flags: ULONG, + ) -> BOOL; + pub fn BuildCommDCBA(lpDef: LPCSTR, lpDCB: LPDCB) -> BOOL; + pub fn BuildCommDCBAndTimeoutsA( + lpDef: LPCSTR, lpDCB: LPDCB, lpCommTimeouts: LPCOMMTIMEOUTS, + ) -> BOOL; + pub fn BuildCommDCBAndTimeoutsW( + lpDef: LPCWSTR, lpDCB: LPDCB, lpCommTimeouts: LPCOMMTIMEOUTS, + ) -> BOOL; + pub fn BuildCommDCBW(lpDef: LPCWSTR, lpDCB: LPDCB) -> BOOL; + pub fn CallNamedPipeA( + lpNamedPipeName: LPCSTR, lpInBuffer: LPVOID, nInBufferSize: DWORD, lpOutBuffer: LPVOID, + nOutBufferSize: DWORD, lpBytesRead: LPDWORD, nTimeOut: DWORD, + ) -> BOOL; + pub fn CallNamedPipeW( + lpNamedPipeName: LPCWSTR, lpInBuffer: LPVOID, nInBufferSize: DWORD, lpOutBuffer: LPVOID, + nOutBufferSize: DWORD, lpBytesRead: LPDWORD, nTimeOut: DWORD, + ) -> BOOL; + pub fn CallbackMayRunLong(pci: PTP_CALLBACK_INSTANCE) -> BOOL; + pub fn CalloutOnFiberStack( + lpFiber: PVOID, lpStartAddress: PFIBER_CALLOUT_ROUTINE, lpParameter: PVOID, + ) -> PVOID; + pub fn CancelDeviceWakeupRequest(hDevice: HANDLE) -> BOOL; + pub fn CancelIo(hFile: HANDLE) -> BOOL; + pub fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL; + pub fn CancelSynchronousIo(hThread: HANDLE) -> BOOL; + pub fn CancelThreadpoolIo(pio: PTP_IO); + pub fn CancelTimerQueueTimer(TimerQueue: HANDLE, Timer: HANDLE) -> BOOL; + pub fn CancelWaitableTimer(hTimer: HANDLE) -> BOOL; + pub fn CeipIsOptedIn() -> BOOL; + pub fn ChangeTimerQueueTimer( + TimerQueue: HANDLE, Timer: HANDLE, DueTime: ULONG, Period: ULONG, + ) -> BOOL; + // pub fn CheckElevation(); + // pub fn CheckElevationEnabled(); + pub fn CheckNameLegalDOS8Dot3A( + lpName: LPCSTR, lpOemName: LPSTR, OemNameSize: DWORD, pbNameContainsSpaces: PBOOL, + pbNameLegal: PBOOL, + ) -> BOOL; + pub fn CheckNameLegalDOS8Dot3W( + lpName: LPCWSTR, lpOemName: LPSTR, OemNameSize: DWORD, pbNameContainsSpaces: PBOOL, + pbNameLegal: PBOOL, + ) -> BOOL; + pub fn CheckRemoteDebuggerPresent(hProcess: HANDLE, pbDebuggerPresent: PBOOL) -> BOOL; + pub fn CheckTokenCapability( + TokenHandle: HANDLE, CapabilitySidToCheck: PSID, HasCapability: PBOOL, + ) -> BOOL; + pub fn CheckTokenMembershipEx( + TokenHandle: HANDLE, SidToCheck: PSID, Flags: DWORD, IsMember: PBOOL, + ) -> BOOL; + pub fn ClearCommBreak(hFile: HANDLE) -> BOOL; + pub fn ClearCommError(hFile: HANDLE, lpErrors: LPDWORD, lpStat: LPCOMSTAT) -> BOOL; + pub fn CloseHandle(hObject: HANDLE) -> BOOL; + // pub fn ClosePackageInfo(); + pub fn ClosePrivateNamespace(Handle: HANDLE, Flags: ULONG) -> BOOLEAN; + // pub fn CloseState(); + pub fn CloseThreadpool(ptpp: PTP_POOL); + pub fn CloseThreadpoolCleanupGroup(ptpcg: PTP_CLEANUP_GROUP); + pub fn CloseThreadpoolCleanupGroupMembers( + ptpcg: PTP_CLEANUP_GROUP, fCancelPendingCallbacks: BOOL, pvCleanupContext: PVOID, + ); + pub fn CloseThreadpoolIo(pio: PTP_IO); + pub fn CloseThreadpoolTimer(pti: PTP_TIMER); + pub fn CloseThreadpoolWait(pwa: PTP_WAIT); + pub fn CloseThreadpoolWork(pwk: PTP_WORK); + pub fn CommConfigDialogA(lpszName: LPCSTR, hWnd: HWND, lpCC: LPCOMMCONFIG) -> BOOL; + pub fn CommConfigDialogW(lpszName: LPCWSTR, hWnd: HWND, lpCC: LPCOMMCONFIG) -> BOOL; + pub fn CompareFileTime(lpFileTime1: *const FILETIME, lpFileTime2: *const FILETIME) -> LONG; + pub fn CompareStringA( + Locale: LCID, dwCmpFlags: DWORD, lpString1: PCNZCH, cchCount1: c_int, lpString2: PCNZCH, + cchCount2: c_int, + ) -> c_int; + pub fn CompareStringEx( + lpLocaleName: LPCWSTR, dwCmpFlags: DWORD, lpString1: LPCWCH, cchCount1: c_int, + lpString2: LPCWCH, cchCount2: c_int, lpVersionInformation: LPNLSVERSIONINFO, + lpReserved: LPVOID, lParam: LPARAM, + ) -> c_int; + pub fn CompareStringOrdinal( + lpString1: LPCWCH, cchCount1: c_int, lpString2: LPCWCH, cchCount2: c_int, bIgnoreCase: BOOL, + ) -> c_int; + pub fn CompareStringW( + Locale: LCID, dwCmpFlags: DWORD, lpString1: PCNZWCH, cchCount1: c_int, lpString2: PCNZWCH, + cchCount2: c_int, + ) -> c_int; + pub fn ConnectNamedPipe(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL; + pub fn ContinueDebugEvent( + dwProcessId: DWORD, dwThreadId: DWORD, dwContinueStatus: DWORD, + ) -> BOOL; + pub fn ConvertDefaultLocale(Locale: LCID) -> LCID; + pub fn ConvertFiberToThread() -> BOOL; + pub fn ConvertThreadToFiber(lpParameter: LPVOID) -> LPVOID; + pub fn ConvertThreadToFiberEx(lpParameter: LPVOID, dwFlags: DWORD) -> LPVOID; + pub fn CopyContext(Destination: PCONTEXT, ContextFlags: DWORD, Source: PCONTEXT) -> BOOL; + pub fn CopyFile2( + pwszExistingFileName: PCWSTR, pwszNewFileName: PCWSTR, + pExtendedParameters: *mut COPYFILE2_EXTENDED_PARAMETERS, + ) -> HRESULT; + pub fn CopyFileA( + lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL + ) -> BOOL; + pub fn CopyFileExA( + lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, pbCancel: LPBOOL, dwCopyFlags: DWORD, + ) -> BOOL; + pub fn CopyFileExW( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, pbCancel: LPBOOL, dwCopyFlags: DWORD, + ) -> BOOL; + pub fn CopyFileTransactedA( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, pbCancel: LPBOOL, dwCopyFlags: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn CopyFileTransactedW( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, pbCancel: LPBOOL, dwCopyFlags: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn CopyFileW( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL + ) -> BOOL; + pub fn CreateActCtxA(pActCtx: PCACTCTXA) -> HANDLE; + pub fn CreateActCtxW(pActCtx: PCACTCTXW) -> HANDLE; + pub fn CreateBoundaryDescriptorA(Name: LPCSTR, Flags: ULONG) -> HANDLE; + pub fn CreateBoundaryDescriptorW(Name: LPCWSTR, Flags: ULONG) -> HANDLE; + pub fn CreateConsoleScreenBuffer( + dwDesiredAccess: DWORD, dwShareMode: DWORD, + lpSecurityAttributes: *const SECURITY_ATTRIBUTES, dwFlags: DWORD, + lpScreenBufferData: LPVOID, + ) -> HANDLE; + pub fn CreateDirectoryA( + lpPathName: LPCSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateDirectoryExA( + lpTemplateDirectory: LPCSTR, lpNewDirectory: LPCSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateDirectoryExW( + lpTemplateDirectory: LPCWSTR, lpNewDirectory: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateDirectoryTransactedA( + lpTemplateDirectory: LPCSTR, lpNewDirectory: LPCSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, hTransaction: HANDLE, + ) -> BOOL; + pub fn CreateDirectoryTransactedW( + lpTemplateDirectory: LPCWSTR, lpNewDirectory: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, hTransaction: HANDLE, + ) -> BOOL; + pub fn CreateDirectoryW( + lpPathName: LPCWSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateEventA( + lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, bInitialState: BOOL, + lpName: LPCSTR, + ) -> HANDLE; + pub fn CreateEventW( + lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, bInitialState: BOOL, + lpName: LPCWSTR, + ) -> HANDLE; + pub fn CreateEventExA( + lpEventAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateEventExW( + lpEventAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCWSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateFiber( + dwStackSize: SIZE_T, lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID, + ) -> LPVOID; + pub fn CreateFiberEx( + dwStackCommitSize: SIZE_T, dwStackReserveSize: SIZE_T, dwFlags: DWORD, + lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID, + ) -> LPVOID; + pub fn CreateFile2( + lpFileName: LPCWSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, + dwCreationDisposition: DWORD, pCreateExParams: LPCREATEFILE2_EXTENDED_PARAMETERS, + ) -> HANDLE; + pub fn CreateFileA( + lpFileName: LPCSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, + dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, + ) -> HANDLE; + pub fn CreateFileMappingA( + hFile: HANDLE, lpAttributes: LPSECURITY_ATTRIBUTES, flProtect: DWORD, + dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: LPCSTR, + ) -> HANDLE; + pub fn CreateFileMappingFromApp( + hFile: HANDLE, SecurityAttributes: PSECURITY_ATTRIBUTES, PageProtection: ULONG, + MaximumSize: ULONG64, Name: PCWSTR, + ) -> HANDLE; + pub fn CreateFileMappingNumaA( + hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, flProtect: DWORD, + dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: LPCSTR, nndPreferred: DWORD, + ) -> HANDLE; + pub fn CreateFileMappingNumaW( + hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, flProtect: DWORD, + dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: LPCWSTR, nndPreferred: DWORD, + ) -> HANDLE; + pub fn CreateFileMappingW( + hFile: HANDLE, lpAttributes: LPSECURITY_ATTRIBUTES, flProtect: DWORD, + dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: LPCWSTR, + ) -> HANDLE; + pub fn CreateFileTransactedA( + lpFileName: LPCSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, + dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, hTransaction: HANDLE, + pusMiniVersion: PUSHORT, lpExtendedParameter: PVOID, + ) -> HANDLE; + pub fn CreateFileTransactedW( + lpFileName: LPCWSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, + dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, hTransaction: HANDLE, + pusMiniVersion: PUSHORT, lpExtendedParameter: PVOID, + ) -> HANDLE; + pub fn CreateFileW( + lpFileName: LPCWSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, + dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, + ) -> HANDLE; + pub fn CreateHardLinkA( + lpFileName: LPCSTR, lpExistingFileName: LPCSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateHardLinkTransactedA( + lpFileName: LPCSTR, lpExistingFileName: LPCSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + hTransaction: HANDLE, + ) -> BOOL; + pub fn CreateHardLinkTransactedW( + lpFileName: LPCWSTR, lpExistingFileName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, hTransaction: HANDLE, + ); + pub fn CreateHardLinkW( + lpFileName: LPCWSTR, lpExistingFileName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> BOOL; + pub fn CreateIoCompletionPort( + FileHandle: HANDLE, ExistingCompletionPort: HANDLE, CompletionKey: ULONG_PTR, + NumberOfConcurrentThreads: DWORD, + ) -> HANDLE; + pub fn CreateJobObjectA(lpJobAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCSTR) -> HANDLE; + pub fn CreateJobObjectW(lpJobAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCWSTR) -> HANDLE; + pub fn CreateJobSet(NumJob: ULONG, UserJobSet: PJOB_SET_ARRAY, Flags: ULONG) -> BOOL; + pub fn CreateMailslotA( + lpName: LPCSTR, nMaxMessageSize: DWORD, lReadTimeout: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> HANDLE; + pub fn CreateMailslotW( + lpName: LPCWSTR, nMaxMessageSize: DWORD, lReadTimeout: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> HANDLE; + pub fn CreateMemoryResourceNotification( + NotificationType: MEMORY_RESOURCE_NOTIFICATION_TYPE, + ) -> HANDLE; + pub fn CreateMutexA( + lpMutexAttributes: LPSECURITY_ATTRIBUTES, bInitialOwner: BOOL, lpName: LPCSTR, + ) -> HANDLE; + pub fn CreateMutexExA( + lpMutexAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateMutexExW( + lpMutexAttributes: LPSECURITY_ATTRIBUTES, lpName: LPCWSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateMutexW( + lpMutexAttributes: LPSECURITY_ATTRIBUTES, bInitialOwner: BOOL, lpName: LPCWSTR, + ) -> HANDLE; + pub fn CreateNamedPipeA( + lpName: LPCSTR, dwOpenMode: DWORD, dwPipeMode: DWORD, nMaxInstances: DWORD, + nOutBufferSize: DWORD, nInBufferSize: DWORD, nDefaultTimeOut: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> HANDLE; + pub fn CreateNamedPipeW( + lpName: LPCWSTR, dwOpenMode: DWORD, dwPipeMode: DWORD, nMaxInstances: DWORD, + nOutBufferSize: DWORD, nInBufferSize: DWORD, nDefaultTimeOut: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + ) -> HANDLE; + pub fn CreatePipe( + hReadPipe: PHANDLE, hWritePipe: PHANDLE, lpPipeAttributes: LPSECURITY_ATTRIBUTES, + nSize: DWORD, + ) -> BOOL; + pub fn CreatePrivateNamespaceA( + lpPrivateNamespaceAttributes: LPSECURITY_ATTRIBUTES, lpBoundaryDescriptor: LPVOID, + lpAliasPrefix: LPCSTR, + ) -> HANDLE; + pub fn CreatePrivateNamespaceW( + lpPrivateNamespaceAttributes: LPSECURITY_ATTRIBUTES, lpBoundaryDescriptor: LPVOID, + lpAliasPrefix: LPCWSTR, + ) -> HANDLE; + pub fn CreateProcessA( + lpApplicationName: LPCSTR, lpCommandLine: LPSTR, lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, bInheritHandles: BOOL, dwCreationFlags: DWORD, + lpEnvironment: LPVOID, lpCurrentDirectory: LPCSTR, lpStartupInfo: LPSTARTUPINFOA, + lpProcessInformation: LPPROCESS_INFORMATION, + ) -> BOOL; + pub fn CreateProcessW( + lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, dwCreationFlags: DWORD, lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, lpStartupInfo: LPSTARTUPINFOW, + lpProcessInformation: LPPROCESS_INFORMATION, + ) -> BOOL; + pub fn CreateRemoteThread( + hProcess: HANDLE, lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, + lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: LPVOID, dwCreationFlags: DWORD, + lpThreadId: LPDWORD, + ) -> HANDLE; + pub fn CreateRemoteThreadEx( + hProcess: HANDLE, lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, + lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: LPVOID, dwCreationFlags: DWORD, + lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, lpThreadId: LPDWORD, + ) -> HANDLE; + pub fn CreateSemaphoreA( + lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, + lpName: LPCSTR, + ) -> HANDLE; + pub fn CreateSemaphoreExA( + lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, + lpName: LPCSTR, dwFlags: DWORD, dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateSemaphoreExW( + lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, + lpName: LPCWSTR, dwFlags: DWORD, dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateSemaphoreW( + lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, + lpName: LPCWSTR, + ) -> HANDLE; + pub fn CreateSymbolicLinkA( + lpSymlinkFileName: LPCSTR, lpTargetFileName: LPCSTR, dwFlags: DWORD, + ) -> BOOLEAN; + pub fn CreateSymbolicLinkTransactedA( + lpSymlinkFileName: LPCSTR, lpTargetFileName: LPCSTR, dwFlags: DWORD, hTransaction: HANDLE, + ) -> BOOLEAN; + pub fn CreateSymbolicLinkTransactedW( + lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, dwFlags: DWORD, hTransaction: HANDLE, + ) -> BOOLEAN; + pub fn CreateSymbolicLinkW( + lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, dwFlags: DWORD, + ) -> BOOLEAN; + pub fn CreateTapePartition( + hDevice: HANDLE, dwPartitionMethod: DWORD, dwCount: DWORD, dwSize: DWORD, + ) -> DWORD; + pub fn CreateThread( + lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, + lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: LPVOID, dwCreationFlags: DWORD, + lpThreadId: LPDWORD, + ) -> HANDLE; + pub fn CreateThreadpool(reserved: PVOID) -> PTP_POOL; + pub fn CreateThreadpoolCleanupGroup() -> PTP_CLEANUP_GROUP; + pub fn CreateThreadpoolIo( + fl: HANDLE, pfnio: PTP_WIN32_IO_CALLBACK, pv: PVOID, pcbe: PTP_CALLBACK_ENVIRON, + ) -> PTP_IO; + pub fn CreateThreadpoolTimer( + pfnti: PTP_TIMER_CALLBACK, pv: PVOID, pcbe: PTP_CALLBACK_ENVIRON, + ) -> PTP_TIMER; + pub fn CreateThreadpoolWait( + pfnwa: PTP_WAIT_CALLBACK, pv: PVOID, pcbe: PTP_CALLBACK_ENVIRON, + ) -> PTP_WAIT; + pub fn CreateThreadpoolWork( + pfnwk: PTP_WORK_CALLBACK, pv: PVOID, pcbe: PTP_CALLBACK_ENVIRON, + ) -> PTP_WORK; + pub fn CreateTimerQueue() -> HANDLE; + pub fn CreateTimerQueueTimer( + phNewTimer: PHANDLE, TimerQueue: HANDLE, Callback: WAITORTIMERCALLBACK, Parameter: PVOID, + DueTime: DWORD, Period: DWORD, Flags: ULONG, + ) -> BOOL; + pub fn CreateToolhelp32Snapshot(dwFlags: DWORD, th32ProcessID: DWORD) -> HANDLE; + #[cfg(target_arch = "x86_64")] + pub fn CreateUmsCompletionList(UmsCompletionList: *mut PUMS_COMPLETION_LIST) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn CreateUmsThreadContext(lpUmsThread: *mut PUMS_CONTEXT) -> BOOL; + pub fn CreateWaitableTimerA( + lpTimerAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, lpTimerName: LPCSTR, + ) -> HANDLE; + pub fn CreateWaitableTimerExA( + lpTimerAttributes: LPSECURITY_ATTRIBUTES, lpTimerName: LPCSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateWaitableTimerExW( + lpTimerAttributes: LPSECURITY_ATTRIBUTES, lpTimerName: LPCWSTR, dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE; + pub fn CreateWaitableTimerW( + lpTimerAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, lpTimerName: LPCWSTR, + ) -> HANDLE; + // pub fn CtrlRoutine(); + pub fn DeactivateActCtx(dwFlags: DWORD, ulCookie: ULONG_PTR) -> BOOL; + pub fn DebugActiveProcess(dwProcessId: DWORD) -> BOOL; + pub fn DebugActiveProcessStop(dwProcessId: DWORD) -> BOOL; + pub fn DebugBreak(); + pub fn DebugBreakProcess(Process: HANDLE) -> BOOL; + pub fn DebugSetProcessKillOnExit(KillOnExit: BOOL) -> BOOL; + pub fn DecodePointer(Ptr: PVOID) -> PVOID; + pub fn DecodeSystemPointer(Ptr: PVOID) -> PVOID; + pub fn DefineDosDeviceA(dwFlags: DWORD, lpDeviceName: LPCSTR, lpTargetPath: LPCSTR) -> BOOL; + pub fn DefineDosDeviceW(dwFlags: DWORD, lpDeviceName: LPCWSTR, lpTargetPath: LPCWSTR) -> BOOL; + pub fn DelayLoadFailureHook(pszDllName: LPCSTR, pszProcName: LPCSTR) -> FARPROC; + pub fn DeleteAtom(nAtom: ATOM) -> ATOM; + pub fn DeleteBoundaryDescriptor(BoundaryDescriptor: HANDLE); + pub fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + pub fn DeleteFiber(lpFiber: LPVOID); + pub fn DeleteFileA(lpFileName: LPCSTR) -> BOOL; + pub fn DeleteFileTransactedA(lpFileName: LPCSTR, hTransaction: HANDLE) -> BOOL; + pub fn DeleteFileTransactedW(lpFileName: LPCWSTR, hTransaction: HANDLE) -> BOOL; + pub fn DeleteFileW(lpFileName: LPCWSTR) -> BOOL; + pub fn DeleteProcThreadAttributeList(lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST); + pub fn DeleteSynchronizationBarrier(lpBarrier: LPSYNCHRONIZATION_BARRIER) -> BOOL; + pub fn DeleteTimerQueue(TimerQueue: HANDLE) -> BOOL; + pub fn DeleteTimerQueueEx(TimerQueue: HANDLE, CompletionEvent: HANDLE) -> BOOL; + pub fn DeleteTimerQueueTimer( + TimerQueue: HANDLE, Timer: HANDLE, CompletionEvent: HANDLE, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn DeleteUmsCompletionList(UmsCompletionList: PUMS_COMPLETION_LIST) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn DeleteUmsThreadContext(UmsThread: PUMS_CONTEXT) -> BOOL; + pub fn DeleteVolumeMountPointA(lpszVolumeMountPoint: LPCSTR) -> BOOL; + pub fn DeleteVolumeMountPointW(lpszVolumeMountPoint: LPCWSTR) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn DequeueUmsCompletionListItems( + UmsCompletionList: PUMS_COMPLETION_LIST, WaitTimeOut: DWORD, + UmsThreadList: *mut PUMS_CONTEXT, + ) -> BOOL; + pub fn DeviceIoControl( + hDevice: HANDLE, dwIoControlCode: DWORD, lpInBuffer: LPVOID, nInBufferSize: DWORD, + lpOutBuffer: LPVOID, nOutBufferSize: DWORD, lpBytesReturned: LPDWORD, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn DisableThreadLibraryCalls(hLibModule: HMODULE) -> BOOL; + pub fn DisableThreadProfiling(PerformanceDataHandle: HANDLE) -> DWORD; + pub fn DisassociateCurrentThreadFromCallback(pci: PTP_CALLBACK_INSTANCE); + pub fn DisconnectNamedPipe(hNamedPipe: HANDLE) -> BOOL; + pub fn DnsHostnameToComputerNameA( + Hostname: LPCSTR, ComputerName: LPCSTR, nSize: LPDWORD, + ) -> BOOL; + pub fn DnsHostnameToComputerNameExW( + Hostname: LPCWSTR, ComputerName: LPWSTR, nSize: LPDWORD, + ) -> BOOL; + pub fn DnsHostnameToComputerNameW( + Hostname: LPCWSTR, ComputerName: LPWSTR, nSize: LPDWORD, + ) -> BOOL; + pub fn DosDateTimeToFileTime(wFatDate: WORD, wFatTime: WORD, lpFileTime: LPFILETIME) -> BOOL; + // pub fn DosPathToSessionPathW(); + pub fn DuplicateHandle( + hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, + lpTargetHandle: LPHANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD, + ) -> BOOL; + pub fn EnableThreadProfiling( + ThreadHandle: HANDLE, Flags: DWORD, HardwareCounters: DWORD64, + PerformanceDataHandle: *mut HANDLE, + ) -> BOOL; + pub fn EncodePointer(Ptr: PVOID) -> PVOID; + pub fn EncodeSystemPointer(Ptr: PVOID) -> PVOID; + pub fn EndUpdateResourceA(hUpdate: HANDLE, fDiscard: BOOL) -> BOOL; + pub fn EndUpdateResourceW(hUpdate: HANDLE, fDiscard: BOOL) -> BOOL; + pub fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + pub fn EnterSynchronizationBarrier( + lpBarrier: LPSYNCHRONIZATION_BARRIER, dwFlags: DWORD, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn EnterUmsSchedulingMode(SchedulerStartupInfo: PUMS_SCHEDULER_STARTUP_INFO) -> BOOL; + pub fn EnumCalendarInfoA( + lpCalInfoEnumProc: CALINFO_ENUMPROCA, Locale: LCID, Calendar: CALID, CalType: CALTYPE, + ) -> BOOL; + pub fn EnumCalendarInfoExA( + lpCalInfoEnumProcEx: CALINFO_ENUMPROCEXA, Locale: LCID, Calendar: CALID, CalType: CALTYPE, + ) -> BOOL; + pub fn EnumCalendarInfoExEx( + pCalInfoEnumProcExEx: CALINFO_ENUMPROCEXEX, lpLocaleName: LPCWSTR, Calendar: CALID, + lpReserved: LPCWSTR, CalType: CALTYPE, lParam: LPARAM, + ) -> BOOL; + pub fn EnumCalendarInfoExW( + lpCalInfoEnumProcEx: CALINFO_ENUMPROCEXW, Locale: LCID, Calendar: CALID, CalType: CALTYPE, + ) -> BOOL; + pub fn EnumCalendarInfoW( + lpCalInfoEnumProc: CALINFO_ENUMPROCW, Locale: LCID, Calendar: CALID, CalType: CALTYPE, + ) -> BOOL; + pub fn EnumDateFormatsA( + lpDateFmtEnumProc: DATEFMT_ENUMPROCA, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumDateFormatsExA( + lpDateFmtEnumProcEx: DATEFMT_ENUMPROCEXA, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumDateFormatsExEx( + lpDateFmtEnumProcExEx: DATEFMT_ENUMPROCEXEX, lpLocaleName: LPCWSTR, dwFlags: DWORD, + lParam: LPARAM, + ) -> BOOL; + pub fn EnumDateFormatsExW( + lpDateFmtEnumProcEx: DATEFMT_ENUMPROCEXW, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumDateFormatsW( + lpDateFmtEnumProc: DATEFMT_ENUMPROCW, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumLanguageGroupLocalesA( + lpLangGroupLocaleEnumProc: LANGGROUPLOCALE_ENUMPROCA, LanguageGroup: LGRPID, dwFlags: DWORD, + lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumLanguageGroupLocalesW( + lpLangGroupLocaleEnumProc: LANGGROUPLOCALE_ENUMPROCW, LanguageGroup: LGRPID, dwFlags: DWORD, + lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceLanguagesA( + hModule: HMODULE, lpType: LPCSTR, lpName: LPCSTR, lpEnumFunc: ENUMRESLANGPROCA, + lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceLanguagesExA( + hModule: HMODULE, lpType: LPCSTR, lpName: LPCSTR, lpEnumFunc: ENUMRESLANGPROCA, + lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceLanguagesExW( + hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, lpEnumFunc: ENUMRESLANGPROCW, + lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceLanguagesW( + hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, lpEnumFunc: ENUMRESLANGPROCW, + lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceNamesA( + hModule: HMODULE, lpType: LPCSTR, lpEnumFunc: ENUMRESNAMEPROCA, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceNamesExA( + hModule: HMODULE, lpType: LPCSTR, lpEnumFunc: ENUMRESNAMEPROCA, lParam: LONG_PTR, + dwFlags: DWORD, LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceNamesExW( + hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR, + dwFlags: DWORD, LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceNamesW( + hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceTypesA( + hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCA, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumResourceTypesExA( + hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCA, lParam: LONG_PTR, dwFlags: DWORD, + LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceTypesExW( + hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCW, lParam: LONG_PTR, dwFlags: DWORD, + LangId: LANGID, + ) -> BOOL; + pub fn EnumResourceTypesW( + hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCW, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumSystemCodePagesA(lpCodePageEnumProc: CODEPAGE_ENUMPROCA, dwFlags: DWORD) -> BOOL; + pub fn EnumSystemCodePagesW(lpCodePageEnumProc: CODEPAGE_ENUMPROCW, dwFlags: DWORD) -> BOOL; + pub fn EnumSystemFirmwareTables( + FirmwareTableProviderSignature: DWORD, pFirmwareTableEnumBuffer: PVOID, BufferSize: DWORD, + ) -> UINT; + pub fn EnumSystemGeoID( + GeoClass: GEOCLASS, ParentGeoId: GEOID, lpGeoEnumProc: GEO_ENUMPROC, + ) -> BOOL; + pub fn EnumSystemLanguageGroupsA( + lpLanguageGroupEnumProc: LANGUAGEGROUP_ENUMPROCA, dwFlags: DWORD, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumSystemLanguageGroupsW( + lpLanguageGroupEnumProc: LANGUAGEGROUP_ENUMPROCW, dwFlags: DWORD, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumSystemLocalesA(lpLocaleEnumProc: LOCALE_ENUMPROCA, dwFlags: DWORD) -> BOOL; + pub fn EnumSystemLocalesEx( + lpLocaleEnumProcEx: LOCALE_ENUMPROCEX, dwFlags: DWORD, lParam: LPARAM, lpReserved: LPVOID, + ) -> BOOL; + pub fn EnumSystemLocalesW(lpLocaleEnumProc: LOCALE_ENUMPROCW, dwFlags: DWORD) -> BOOL; + pub fn EnumTimeFormatsA( + lpTimeFmtEnumProc: TIMEFMT_ENUMPROCA, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumTimeFormatsEx( + lpTimeFmtEnumProcEx: TIMEFMT_ENUMPROCEX, lpLocaleName: LPCWSTR, dwFlags: DWORD, + lParam: LPARAM, + ) -> BOOL; + pub fn EnumTimeFormatsW( + lpTimeFmtEnumProc: TIMEFMT_ENUMPROCW, Locale: LCID, dwFlags: DWORD, + ) -> BOOL; + pub fn EnumUILanguagesA( + lpUILanguageEnumProc: UILANGUAGE_ENUMPROCA, dwFlags: DWORD, lParam: LONG_PTR, + ) -> BOOL; + pub fn EnumUILanguagesW( + lpUILanguageEnumProc: UILANGUAGE_ENUMPROCW, dwFlags: DWORD, lParam: LONG_PTR, + ) -> BOOL; + // pub fn EnumerateLocalComputerNamesA(); + // pub fn EnumerateLocalComputerNamesW(); + pub fn EraseTape(hDevice: HANDLE, dwEraseType: DWORD, bImmediate: BOOL) -> DWORD; + pub fn EscapeCommFunction(hFile: HANDLE, dwFunc: DWORD) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn ExecuteUmsThread(UmsThread: PUMS_CONTEXT) -> BOOL; + pub fn ExitProcess(uExitCode: UINT); + pub fn ExitThread(dwExitCode: DWORD); + pub fn ExpandEnvironmentStringsA(lpSrc: LPCSTR, lpDst: LPSTR, nSize: DWORD) -> DWORD; + pub fn ExpandEnvironmentStringsW(lpSrc: LPCWSTR, lpDst: LPWSTR, nSize: DWORD) -> DWORD; + pub fn FatalAppExitA(uAction: UINT, lpMessageText: LPCSTR); + pub fn FatalAppExitW(uAction: UINT, lpMessageText: LPCWSTR); + pub fn FatalExit(ExitCode: c_int); + pub fn FileTimeToDosDateTime( + lpFileTime: *const FILETIME, lpFatDate: LPWORD, lpFatTime: LPWORD, + ) -> BOOL; + pub fn FileTimeToLocalFileTime( + lpFileTime: *const FILETIME, lpLocalFileTime: LPFILETIME, + ) -> BOOL; + pub fn FileTimeToSystemTime( + lpFileTime: *const FILETIME, lpSystemTime: LPSYSTEMTIME, + ) -> BOOL; + pub fn FillConsoleOutputAttribute( + hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfAttrsWritten: LPDWORD, + ) -> BOOL; + pub fn FillConsoleOutputCharacterA( + hConsoleOutput: HANDLE, cCharacter: CHAR, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfCharsWritten: LPDWORD, + ) -> BOOL; + pub fn FillConsoleOutputCharacterW( + hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfCharsWritten: LPDWORD, + ) -> BOOL; + pub fn FindActCtxSectionGuid( + dwFlags: DWORD, lpExtensionGuid: *const GUID, ulSectionId: ULONG, lpGuidToFind: *const GUID, + ReturnedData: PACTCTX_SECTION_KEYED_DATA, + ) -> BOOL; + pub fn FindActCtxSectionStringA( + dwFlags: DWORD, lpExtensionGuid: *const GUID, ulSectionId: ULONG, lpStringToFind: LPCSTR, + ReturnedData: PACTCTX_SECTION_KEYED_DATA, + ) -> BOOL; + pub fn FindActCtxSectionStringW( + dwFlags: DWORD, lpExtensionGuid: *const GUID, ulSectionId: ULONG, lpStringToFind: LPCWSTR, + ReturnedData: PACTCTX_SECTION_KEYED_DATA, + ) -> BOOL; + pub fn FindAtomA(lpString: LPCSTR) -> ATOM; + pub fn FindAtomW(lpString: LPCWSTR) -> ATOM; + pub fn FindClose(hFindFile: HANDLE) -> BOOL; + pub fn FindCloseChangeNotification(hChangeHandle: HANDLE) -> BOOL; + pub fn FindFirstChangeNotificationA( + lpPathName: LPCSTR, bWatchSubtree: BOOL, dwNotifyFilter: DWORD, + ) -> HANDLE; + pub fn FindFirstChangeNotificationW( + lpPathName: LPCWSTR, bWatchSubtree: BOOL, dwNotifyFilter: DWORD, + ) -> HANDLE; + pub fn FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: LPWIN32_FIND_DATAA) -> HANDLE; + pub fn FindFirstFileExA( + lpFileName: LPCSTR, fInfoLevelId: FINDEX_INFO_LEVELS, lpFindFileData: LPVOID, + fSearchOp: FINDEX_SEARCH_OPS, lpSearchFilter: LPVOID, dwAdditionalFlags: DWORD, + ) -> HANDLE; + pub fn FindFirstFileExW( + lpFileName: LPCWSTR, fInfoLevelId: FINDEX_INFO_LEVELS, lpFindFileData: LPVOID, + fSearchOp: FINDEX_SEARCH_OPS, lpSearchFilter: LPVOID, dwAdditionalFlags: DWORD, + ) -> HANDLE; + pub fn FindFirstFileNameTransactedW( + lpFileName: LPCWSTR, dwFlags: DWORD, StringLength: LPDWORD, LinkName: PWSTR, + hTransaction: HANDLE, + ) -> HANDLE; + pub fn FindFirstFileNameW( + lpFileName: LPCWSTR, dwFlags: DWORD, StringLength: LPDWORD, LinkName: PWSTR, + ) -> HANDLE; + pub fn FindFirstFileTransactedA( + lpFileName: LPCSTR, fInfoLevelId: FINDEX_INFO_LEVELS, lpFindFileData: LPVOID, + fSearchOp: FINDEX_SEARCH_OPS, lpSearchFilter: LPVOID, dwAdditionalFlags: DWORD, + hTransaction: HANDLE, + ) -> HANDLE; + pub fn FindFirstFileTransactedW( + lpFileName: LPCWSTR, fInfoLevelId: FINDEX_INFO_LEVELS, lpFindFileData: LPVOID, + fSearchOp: FINDEX_SEARCH_OPS, lpSearchFilter: LPVOID, dwAdditionalFlags: DWORD, + hTransaction: HANDLE, + ) -> HANDLE; + pub fn FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: LPWIN32_FIND_DATAW) -> HANDLE; + pub fn FindFirstStreamTransactedW( + lpFileName: LPCWSTR, InfoLevel: STREAM_INFO_LEVELS, lpFindStreamData: LPVOID, + dwFlags: DWORD, hTransaction: HANDLE, + ) -> HANDLE; + pub fn FindFirstStreamW( + lpFileName: LPCWSTR, InfoLevel: STREAM_INFO_LEVELS, lpFindStreamData: LPVOID, + dwFlags: DWORD, + ) -> HANDLE; + pub fn FindFirstVolumeA(lpszVolumeName: LPSTR, cchBufferLength: DWORD) -> HANDLE; + pub fn FindFirstVolumeMountPointA( + lpszRootPathName: LPCSTR, lpszVolumeMountPoint: LPSTR, cchBufferLength: DWORD, + ) -> HANDLE; + pub fn FindFirstVolumeMountPointW( + lpszRootPathName: LPCWSTR, lpszVolumeMountPoint: LPWSTR, cchBufferLength: DWORD, + ) -> HANDLE; + pub fn FindFirstVolumeW(lpszVolumeName: LPWSTR, cchBufferLength: DWORD) -> HANDLE; + pub fn FindNLSString( + Locale: LCID, dwFindNLSStringFlags: DWORD, lpStringSource: LPCWSTR, cchSource: c_int, + lpStringValue: LPCWSTR, cchValue: c_int, pcchFound: LPINT, + ) -> c_int; + pub fn FindNLSStringEx( + lpLocaleName: LPCWSTR, dwFindNLSStringFlags: DWORD, lpStringSource: LPCWSTR, + cchSource: c_int, lpStringValue: LPCWSTR, cchValue: c_int, pcchFound: LPINT, + lpVersionInformation: LPNLSVERSIONINFO, lpReserved: LPVOID, sortHandle: LPARAM, + ) -> c_int; + pub fn FindNextChangeNotification(hChangeHandle: HANDLE) -> BOOL; + pub fn FindNextFileA(hFindFile: HANDLE, lpFindFileData: LPWIN32_FIND_DATAA) -> BOOL; + pub fn FindNextFileNameW(hFindStream: HANDLE, StringLength: LPDWORD, LinkName: PWSTR) -> BOOL; + pub fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: LPWIN32_FIND_DATAW) -> BOOL; + pub fn FindNextStreamW(hFindStream: HANDLE, lpFindStreamData: LPVOID) -> BOOL; + pub fn FindNextVolumeA( + hFindVolume: HANDLE, lpszVolumeName: LPSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn FindNextVolumeMountPointA( + hFindVolumeMountPoint: HANDLE, lpszVolumeMountPoint: LPSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn FindNextVolumeMountPointW( + hFindVolumeMountPoint: HANDLE, lpszVolumeMountPoint: LPWSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn FindNextVolumeW( + hFindVolume: HANDLE, lpszVolumeName: LPWSTR, cchBufferLength: DWORD, + ) -> BOOL; + // pub fn FindPackagesByPackageFamily(); + pub fn FindResourceA(hModule: HMODULE, lpName: LPCSTR, lpType: LPCSTR) -> HRSRC; + pub fn FindResourceExA( + hModule: HMODULE, lpName: LPCSTR, lpType: LPCSTR, wLanguage: WORD, + ) -> HRSRC; + pub fn FindResourceExW( + hModule: HMODULE, lpName: LPCWSTR, lpType: LPCWSTR, wLanguage: WORD, + ) -> HRSRC; + pub fn FindResourceW(hModule: HMODULE, lpName: LPCWSTR, lpType: LPCWSTR) -> HRSRC; + pub fn FindStringOrdinal( + dwFindStringOrdinalFlags: DWORD, lpStringSource: LPCWSTR, cchSource: c_int, + lpStringValue: LPCWSTR, cchValue: c_int, bIgnoreCase: BOOL, + ) -> c_int; + pub fn FindVolumeClose(hFindVolume: HANDLE) -> BOOL; + pub fn FindVolumeMountPointClose(hFindVolumeMountPoint: HANDLE) -> BOOL; + pub fn FlsAlloc(lpCallback: PFLS_CALLBACK_FUNCTION) -> DWORD; + pub fn FlsFree(dwFlsIndex: DWORD) -> BOOL; + pub fn FlsGetValue(dwFlsIndex: DWORD) -> PVOID; + pub fn FlsSetValue(dwFlsIndex: DWORD, lpFlsData: PVOID) -> BOOL; + pub fn FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL; + pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL; + pub fn FlushInstructionCache(hProcess: HANDLE, lpBaseAddress: LPCVOID, dwSize: SIZE_T) -> BOOL; + pub fn FlushProcessWriteBuffers(); + pub fn FlushViewOfFile(lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T) -> BOOL; + pub fn FoldStringA( + dwMapFlags: DWORD, lpSrcStr: LPCSTR, cchSrc: c_int, lpDestStr: LPSTR, cchDest: c_int, + ) -> c_int; + pub fn FoldStringW( + dwMapFlags: DWORD, lpSrcStr: LPCWCH, cchSrc: c_int, lpDestStr: LPWSTR, cchDest: c_int, + ) -> c_int; + // pub fn FormatApplicationUserModelId(); + pub fn FormatMessageA( + dwFlags: DWORD, lpSource: LPCVOID, dwMessageId: DWORD, dwLanguageId: DWORD, + lpBuffer: LPSTR, nSize: DWORD, Arguments: *mut va_list, + ) -> DWORD; + pub fn FormatMessageW( + dwFlags: DWORD, lpSource: LPCVOID, dwMessageId: DWORD, dwLanguageId: DWORD, + lpBuffer: LPWSTR, nSize: DWORD, Arguments: *mut va_list, + ) -> DWORD; + pub fn FreeConsole() -> BOOL; + pub fn FreeEnvironmentStringsA(penv: LPCH) -> BOOL; + pub fn FreeEnvironmentStringsW(penv: LPWCH) -> BOOL; + pub fn FreeLibrary(hLibModule: HMODULE) -> BOOL; + pub fn FreeLibraryAndExitThread(hLibModule: HMODULE, dwExitCode: DWORD); + pub fn FreeLibraryWhenCallbackReturns(pci: PTP_CALLBACK_INSTANCE, module: HMODULE); + pub fn FreeResource(hResData: HGLOBAL) -> BOOL; + pub fn FreeUserPhysicalPages( + hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, + ) -> BOOL; + pub fn GenerateConsoleCtrlEvent(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL; + pub fn GetACP() -> UINT; + pub fn GetActiveProcessorCount(GroupNumber: WORD) -> DWORD; + pub fn GetActiveProcessorGroupCount() -> WORD; + pub fn GetAppContainerAce( + Acl: PACL, StartingAceIndex: DWORD, AppContainerAce: *mut PVOID, + AppContainerAceIndex: *mut DWORD, + ) -> BOOL; + pub fn GetAppContainerNamedObjectPath( + Token: HANDLE, AppContainerSid: PSID, ObjectPathLength: ULONG, ObjectPath: LPWSTR, + ReturnLength: PULONG, + ) -> BOOL; + pub fn GetApplicationRecoveryCallback( + hProcess: HANDLE, pRecoveryCallback: *mut APPLICATION_RECOVERY_CALLBACK, + ppvParameter: *mut PVOID, pdwPingInterval: PDWORD, pdwFlags: PDWORD, + ) -> HRESULT; + pub fn GetApplicationRestartSettings( + hProcess: HANDLE, pwzCommandline: PWSTR, pcchSize: PDWORD, pdwFlags: PDWORD, + ) -> HRESULT; + // pub fn GetApplicationUserModelId(); + pub fn GetAtomNameA(nAtom: ATOM, lpBuffer: LPSTR, nSize: c_int) -> UINT; + pub fn GetAtomNameW(nAtom: ATOM, lpBuffer: LPWSTR, nSize: c_int) -> UINT; + pub fn GetBinaryTypeA(lpApplicationName: LPCSTR, lpBinaryType: LPDWORD) -> BOOL; + pub fn GetBinaryTypeW(lpApplicationName: LPCWSTR, lpBinaryType: LPDWORD) -> BOOL; + pub fn GetCPInfo(CodePage: UINT, lpCPInfo: LPCPINFO) -> BOOL; + pub fn GetCPInfoExA(CodePage: UINT, dwFlags: DWORD, lpCPInfoEx: LPCPINFOEXA) -> BOOL; + pub fn GetCPInfoExW(CodePage: UINT, dwFlags: DWORD, lpCPInfoEx: LPCPINFOEXW) -> BOOL; + pub fn GetCachedSigningLevel( + File: HANDLE, Flags: PULONG, SigningLevel: PULONG, Thumbprint: PUCHAR, + ThumbprintSize: PULONG, ThumbprintAlgorithm: PULONG, + ) -> BOOL; + pub fn GetCalendarInfoA( + Locale: LCID, Calendar: CALID, CalType: CALTYPE, lpCalData: LPSTR, cchData: c_int, + lpValue: LPDWORD, + ) -> c_int; + pub fn GetCalendarInfoEx( + lpLocaleName: LPCWSTR, Calendar: CALID, lpReserved: LPCWSTR, CalType: CALTYPE, + lpCalData: LPWSTR, cchData: c_int, lpValue: LPDWORD, + ) -> c_int; + pub fn GetCalendarInfoW( + Locale: LCID, Calendar: CALID, CalType: CALTYPE, lpCalData: LPWSTR, cchData: c_int, + lpValue: LPDWORD, + ) -> c_int; + pub fn GetCommConfig(hCommDev: HANDLE, lpCC: LPCOMMCONFIG, lpdwSize: LPDWORD) -> BOOL; + pub fn GetCommMask(hFile: HANDLE, lpEvtMask: LPDWORD) -> BOOL; + pub fn GetCommModemStatus(hFile: HANDLE, lpModemStat: LPDWORD) -> BOOL; + pub fn GetCommProperties(hFile: HANDLE, lpCommProp: LPCOMMPROP) -> BOOL; + pub fn GetCommState(hFile: HANDLE, lpDCB: LPDCB) -> BOOL; + pub fn GetCommTimeouts(hFile: HANDLE, lpCommTimeouts: LPCOMMTIMEOUTS) -> BOOL; + pub fn GetCommandLineA() -> LPSTR; + pub fn GetCommandLineW() -> LPWSTR; + pub fn GetCompressedFileSizeA(lpFileName: LPCSTR, lpFileSizeHigh: LPDWORD) -> DWORD; + pub fn GetCompressedFileSizeTransactedA( + lpFileName: LPCSTR, lpFileSizeHigh: LPDWORD, hTransaction: HANDLE, + ) -> DWORD; + pub fn GetCompressedFileSizeTransactedW( + lpFileName: LPCWSTR, lpFileSizeHigh: LPDWORD, hTransaction: HANDLE, + ); + pub fn GetCompressedFileSizeW(lpFileName: LPCWSTR, lpFileSizeHigh: LPDWORD) -> DWORD; + pub fn GetComputerNameA(lpBuffer: LPSTR, nSize: LPDWORD) -> BOOL; + pub fn GetComputerNameExA( + NameType: COMPUTER_NAME_FORMAT, lpBuffer: LPSTR, nSize: LPDWORD, + ) -> BOOL; + pub fn GetComputerNameExW( + NameType: COMPUTER_NAME_FORMAT, lpBuffer: LPWSTR, nSize: LPDWORD, + ) -> BOOL; + pub fn GetComputerNameW(lpBuffer: LPWSTR, nSize: LPDWORD) -> BOOL; + pub fn GetConsoleAliasA( + Source: LPSTR, TargetBuffer: LPSTR, TargetBufferLength: DWORD, ExeName: LPSTR, + ) -> DWORD; + pub fn GetConsoleAliasExesA(ExeNameBuffer: LPSTR, ExeNameBufferLength: DWORD) -> DWORD; + pub fn GetConsoleAliasExesLengthA() -> DWORD; + pub fn GetConsoleAliasExesLengthW() -> DWORD; + pub fn GetConsoleAliasExesW(ExeNameBuffer: LPWSTR, ExeNameBufferLength: DWORD) -> DWORD; + pub fn GetConsoleAliasW( + Source: LPWSTR, TargetBuffer: LPWSTR, TargetBufferLength: DWORD, ExeName: LPWSTR, + ) -> DWORD; + pub fn GetConsoleAliasesA( + AliasBuffer: LPSTR, AliasBufferLength: DWORD, ExeName: LPSTR, + ) -> DWORD; + pub fn GetConsoleAliasesLengthA(ExeName: LPSTR) -> DWORD; + pub fn GetConsoleAliasesLengthW(ExeName: LPWSTR) -> DWORD; + pub fn GetConsoleAliasesW( + AliasBuffer: LPWSTR, AliasBufferLength: DWORD, ExeName: LPWSTR, + ) -> DWORD; + pub fn GetConsoleCP() -> UINT; + pub fn GetConsoleCursorInfo( + hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO, + ) -> BOOL; + pub fn GetConsoleDisplayMode(lpModeFlags: LPDWORD) -> BOOL; + pub fn GetConsoleFontSize(hConsoleOutput: HANDLE, nFont: DWORD) -> COORD; + pub fn GetConsoleHistoryInfo(lpConsoleHistoryInfo: PCONSOLE_HISTORY_INFO) -> BOOL; + pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + pub fn GetConsoleOriginalTitleA(lpConsoleTitle: LPSTR, nSize: DWORD) -> DWORD; + pub fn GetConsoleOriginalTitleW(lpConsoleTitle: LPWSTR, nSize: DWORD) -> DWORD; + pub fn GetConsoleOutputCP() -> UINT; + pub fn GetConsoleProcessList(lpdwProcessList: LPDWORD, dwProcessCount: DWORD) -> DWORD; + pub fn GetConsoleScreenBufferInfo( + hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO, + ) -> BOOL; + pub fn GetConsoleScreenBufferInfoEx( + hConsoleOutput: HANDLE, lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX, + ) -> BOOL; + pub fn GetConsoleSelectionInfo(lpConsoleSelectionInfo: PCONSOLE_SELECTION_INFO) -> BOOL; + pub fn GetConsoleTitleA(lpConsoleTitle: LPSTR, nSize: DWORD) -> DWORD; + pub fn GetConsoleTitleW(lpConsoleTitle: LPWSTR, nSize: DWORD) -> DWORD; + pub fn GetConsoleWindow() -> HWND; + pub fn GetCurrencyFormatA( + Locale: LCID, dwFlags: DWORD, lpValue: LPCSTR, lpFormat: *const CURRENCYFMTA, + lpCurrencyStr: LPSTR, cchCurrency: c_int, + ) -> c_int; + pub fn GetCurrencyFormatEx( + lpLocaleName: LPCWSTR, dwFlags: DWORD, lpValue: LPCWSTR, lpFormat: *const CURRENCYFMTW, + lpCurrencyStr: LPWSTR, cchCurrency: c_int, + ) -> c_int; + pub fn GetCurrencyFormatW( + Locale: LCID, dwFlags: DWORD, lpValue: LPCWSTR, lpFormat: *const CURRENCYFMTW, + lpCurrencyStr: LPWSTR, cchCurrency: c_int, + ) -> c_int; + pub fn GetCurrentActCtx(lphActCtx: *mut HANDLE) -> BOOL; + // pub fn GetCurrentApplicationUserModelId(); + pub fn GetCurrentConsoleFont( + hConsoleOutput: HANDLE, bMaximumWindow: BOOL, lpConsoleCurrentFont: PCONSOLE_FONT_INFO, + ) -> BOOL; + pub fn GetCurrentConsoleFontEx( + hConsoleOutput: HANDLE, bMaximumWindow: BOOL, lpConsoleCurrentFontEx: PCONSOLE_FONT_INFOEX, + ) -> BOOL; + pub fn GetCurrentDirectoryA(nBufferLength: DWORD, lpBuffer: LPSTR) -> DWORD; + pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; + // pub fn GetCurrentPackageFamilyName(); + // pub fn GetCurrentPackageFullName(); + // pub fn GetCurrentPackageId(); + // pub fn GetCurrentPackageInfo(); + // pub fn GetCurrentPackagePath(); + pub fn GetCurrentProcess() -> HANDLE; + pub fn GetCurrentProcessId() -> DWORD; + pub fn GetCurrentProcessorNumber() -> DWORD; + pub fn GetCurrentProcessorNumberEx(ProcNumber: PPROCESSOR_NUMBER); + pub fn GetCurrentThread() -> HANDLE; + pub fn GetCurrentThreadId() -> DWORD; + pub fn GetCurrentThreadStackLimits(LowLimit: PULONG_PTR, HighLimit: PULONG_PTR); + #[cfg(target_arch = "x86_64")] + pub fn GetCurrentUmsThread() -> PUMS_CONTEXT; + pub fn GetDateFormatA( + Locale: LCID, dwFlags: DWORD, lpDate: *const SYSTEMTIME, lpFormat: LPCSTR, lpDateStr: LPSTR, + cchDate: c_int, + ) -> c_int; + pub fn GetDateFormatEx( + lpLocaleName: LPCWSTR, dwFlags: DWORD, lpDate: *const SYSTEMTIME, lpFormat: LPCWSTR, + lpDateStr: LPWSTR, cchDate: c_int, lpCalendar: LPCWSTR, + ) -> c_int; + pub fn GetDateFormatW( + Locale: LCID, dwFlags: DWORD, lpDate: *const SYSTEMTIME, lpFormat: LPCWSTR, + lpDateStr: LPWSTR, cchDate: c_int, + ) -> c_int; + pub fn GetDefaultCommConfigA(lpszName: LPCSTR, lpCC: LPCOMMCONFIG, lpdwSize: LPDWORD) -> BOOL; + pub fn GetDefaultCommConfigW(lpszName: LPCWSTR, lpCC: LPCOMMCONFIG, lpdwSize: LPDWORD) -> BOOL; + pub fn GetDevicePowerState(hDevice: HANDLE, pfOn: *mut BOOL) -> BOOL; + pub fn GetDiskFreeSpaceA( + lpRootPathName: LPCSTR, lpSectorsPerCluster: LPDWORD, lpBytesPerSector: LPDWORD, + lpNumberOfFreeClusters: LPDWORD, lpTotalNumberOfClusters: LPDWORD, + ) -> BOOL; + pub fn GetDiskFreeSpaceExA( + lpDirectoryName: LPCSTR, lpFreeBytesAvailableToCaller: PULARGE_INTEGER, + lpTotalNumberOfBytes: PULARGE_INTEGER, lpTotalNumberOfFreeBytes: PULARGE_INTEGER, + ) -> BOOL; + pub fn GetDiskFreeSpaceExW( + lpDirectoryName: LPCWSTR, lpFreeBytesAvailableToCaller: PULARGE_INTEGER, + lpTotalNumberOfBytes: PULARGE_INTEGER, lpTotalNumberOfFreeBytes: PULARGE_INTEGER, + ) -> BOOL; + pub fn GetDiskFreeSpaceW( + lpRootPathName: LPCWSTR, lpSectorsPerCluster: LPDWORD, lpBytesPerSector: LPDWORD, + lpNumberOfFreeClusters: LPDWORD, lpTotalNumberOfClusters: LPDWORD, + ) -> BOOL; + pub fn GetDllDirectoryA(nBufferLength: DWORD, lpBuffer: LPSTR) -> DWORD; + pub fn GetDllDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; + pub fn GetDriveTypeA(lpRootPathName: LPCSTR) -> UINT; + pub fn GetDriveTypeW(lpRootPathName: LPCWSTR) -> UINT; + pub fn GetDurationFormat( + Locale: LCID, dwFlags: DWORD, lpDuration: *const SYSTEMTIME, ullDuration: ULONGLONG, + lpFormat: LPCWSTR, lpDurationStr: LPWSTR, cchDuration: c_int, + ) -> c_int; + pub fn GetDurationFormatEx( + lpLocaleName: LPCWSTR, dwFlags: DWORD, lpDuration: *const SYSTEMTIME, + ullDuration: ULONGLONG, lpFormat: LPCWSTR, lpDurationStr: LPWSTR, cchDuration: c_int, + ) -> c_int; + pub fn GetDynamicTimeZoneInformation( + pTimeZoneInformation: PDYNAMIC_TIME_ZONE_INFORMATION, + ) -> DWORD; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn GetEnabledXStateFeatures() -> DWORD64; + pub fn GetEnvironmentStrings() -> LPCH; + pub fn GetEnvironmentStringsW() -> LPWCH; + pub fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) -> DWORD; + pub fn GetEnvironmentVariableW(lpName: LPCWSTR, lpBuffer: LPWSTR, nSize: DWORD) -> DWORD; + // pub fn GetEraNameCountedString(); + pub fn GetErrorMode() -> UINT; + pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL; + pub fn GetExitCodeThread(hThread: HANDLE, lpExitCode: LPDWORD) -> BOOL; + pub fn GetFileAttributesA(lpFileName: LPCSTR) -> DWORD; + pub fn GetFileAttributesExA( + lpFileName: LPCSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID, + ) -> BOOL; + pub fn GetFileAttributesExW( + lpFileName: LPCWSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID, + ) -> BOOL; + pub fn GetFileAttributesTransactedA( + lpFileName: LPCSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID, + hTransaction: HANDLE, + ) -> BOOL; + pub fn GetFileAttributesTransactedW( + lpFileName: LPCWSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID, + hTransaction: HANDLE, + ) -> BOOL; + pub fn GetFileAttributesW(lpFileName: LPCWSTR) -> DWORD; + pub fn GetFileBandwidthReservation( + hFile: HANDLE, lpPeriodMilliseconds: LPDWORD, lpBytesPerPeriod: LPDWORD, + pDiscardable: LPBOOL, lpTransferSize: LPDWORD, lpNumOutstandingRequests: LPDWORD, + ) -> BOOL; + pub fn GetFileInformationByHandle( + hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION, + ) -> BOOL; + pub fn GetFileInformationByHandleEx( + hFile: HANDLE, FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, lpFileInformation: LPVOID, + dwBufferSize: DWORD, + ) -> BOOL; + pub fn GetFileMUIInfo( + dwFlags: DWORD, pcwszFilePath: PCWSTR, pFileMUIInfo: PFILEMUIINFO, + pcbFileMUIInfo: *mut DWORD, + ) -> BOOL; + pub fn GetFileMUIPath( + dwFlags: DWORD, pcwszFilePath: PCWSTR, pwszLanguage: PWSTR, pcchLanguage: PULONG, + pwszFileMUIPath: PWSTR, pcchFileMUIPath: PULONG, pululEnumerator: PULONGLONG, + ) -> BOOL; + pub fn GetFileSize(hFile: HANDLE, lpFileSizeHigh: LPDWORD) -> DWORD; + pub fn GetFileSizeEx(hFile: HANDLE, lpFileSize: PLARGE_INTEGER) -> BOOL; + pub fn GetFileTime( + hFile: HANDLE, lpCreationTime: LPFILETIME, lpLastAccessTime: LPFILETIME, + lpLastWriteTime: LPFILETIME, + ) -> BOOL; + pub fn GetFileType(hFile: HANDLE) -> DWORD; + pub fn GetFinalPathNameByHandleA( + hFile: HANDLE, lpszFilePath: LPSTR, cchFilePath: DWORD, dwFlags: DWORD, + ) -> DWORD; + pub fn GetFinalPathNameByHandleW( + hFile: HANDLE, lpszFilePath: LPWSTR, cchFilePath: DWORD, dwFlags: DWORD, + ) -> DWORD; + pub fn GetFirmwareEnvironmentVariableA( + lpName: LPCSTR, lpGuid: LPCSTR, pBuffer: PVOID, nSize: DWORD, + ) -> DWORD; + pub fn GetFirmwareEnvironmentVariableExA( + lpName: LPCSTR, lpGuid: LPCSTR, pBuffer: PVOID, nSize: DWORD, pdwAttribubutes: PDWORD, + ) -> DWORD; + pub fn GetFirmwareEnvironmentVariableExW( + lpName: LPCWSTR, lpGuid: LPCWSTR, pBuffer: PVOID, nSize: DWORD, pdwAttribubutes: PDWORD, + ) -> DWORD; + pub fn GetFirmwareEnvironmentVariableW( + lpName: LPCWSTR, lpGuid: LPCWSTR, pBuffer: PVOID, nSize: DWORD, + ) -> DWORD; + pub fn GetFirmwareType(FirmwareType: PFIRMWARE_TYPE) -> BOOL; + pub fn GetFullPathNameA( + lpFileName: LPCSTR, nBufferLength: DWORD, lpBuffer: LPSTR, lpFilePart: *mut LPSTR, + ) -> DWORD; + pub fn GetFullPathNameTransactedA( + lpFileName: LPCSTR, nBufferLength: DWORD, lpBuffer: LPSTR, lpFilePart: *mut LPSTR, + hTransaction: HANDLE, + ) -> DWORD; + pub fn GetFullPathNameTransactedW( + lpFileName: LPCWSTR, nBufferLength: DWORD, lpBuffer: LPWSTR, lpFilePart: *mut LPWSTR, + hTransaction: HANDLE, + ); + pub fn GetFullPathNameW( + lpFileName: LPCWSTR, nBufferLength: DWORD, lpBuffer: LPWSTR, lpFilePart: *mut LPWSTR, + ) -> DWORD; + pub fn GetGeoInfoA( + Location: GEOID, GeoType: GEOTYPE, lpGeoData: LPSTR, cchData: c_int, LangId: LANGID, + ) -> c_int; + pub fn GetGeoInfoW( + Location: GEOID, GeoType: GEOTYPE, lpGeoData: LPWSTR, cchData: c_int, LangId: LANGID, + ) -> c_int; + pub fn GetHandleInformation(hObject: HANDLE, lpdwFlags: LPDWORD) -> BOOL; + pub fn GetLargePageMinimum() -> SIZE_T; + pub fn GetLargestConsoleWindowSize(hConsoleOutput: HANDLE) -> COORD; + pub fn GetLastError() -> DWORD; + pub fn GetLocalTime(lpSystemTime: LPSYSTEMTIME); + pub fn GetLocaleInfoA( + Locale: LCID, LCType: LCTYPE, lpLCData: LPSTR, cchData: c_int, + ) -> c_int; + pub fn GetLocaleInfoEx( + lpLocaleName: LPCWSTR, LCType: LCTYPE, lpLCData: LPWSTR, cchData: c_int, + ) -> c_int; + pub fn GetLocaleInfoW( + Locale: LCID, LCType: LCTYPE, lpLCData: LPWSTR, cchData: c_int, + ) -> c_int; + pub fn GetLogicalDriveStringsA(nBufferLength: DWORD, lpBuffer: LPSTR) -> DWORD; + pub fn GetLogicalDriveStringsW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; + pub fn GetLogicalDrives() -> DWORD; + pub fn GetLogicalProcessorInformation( + Buffer: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, ReturnedLength: PDWORD, + ) -> BOOL; + pub fn GetLogicalProcessorInformationEx( + RelationshipType: LOGICAL_PROCESSOR_RELATIONSHIP, + Buffer: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, + ReturnedLength: PDWORD, + ) -> BOOL; + pub fn GetLongPathNameA(lpszShortPath: LPCSTR, lpszLongPath: LPSTR, cchBuffer: DWORD) -> DWORD; + pub fn GetLongPathNameTransactedA( + lpszShortPath: LPCSTR, lpszLongPath: LPSTR, cchBuffer: DWORD, hTransaction: HANDLE, + ) -> DWORD; + pub fn GetLongPathNameTransactedW( + lpszShortPath: LPCWSTR, lpszLongPath: LPWSTR, cchBuffer: DWORD, hTransaction: HANDLE, + ) -> DWORD; + pub fn GetLongPathNameW( + lpszShortPath: LPCWSTR, lpszLongPath: LPWSTR, cchBuffer: DWORD, + ) -> DWORD; + pub fn GetMailslotInfo( + hMailslot: HANDLE, lpMaxMessageSize: LPDWORD, lpNextSize: LPDWORD, lpMessageCount: LPDWORD, + lpReadTimeout: LPDWORD, + ) -> BOOL; + pub fn GetMaximumProcessorCount(GroupNumber: WORD) -> DWORD; + pub fn GetMaximumProcessorGroupCount() -> WORD; + pub fn GetMemoryErrorHandlingCapabilities(Capabilities: PULONG) -> BOOL; + pub fn GetModuleFileNameA( + hModule: HMODULE, lpFilename: LPSTR, nSize: DWORD, + ) -> DWORD; + pub fn GetModuleFileNameW( + hModule: HMODULE, lpFilename: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn GetModuleHandleA(lpModuleName: LPCSTR) -> HMODULE; + pub fn GetModuleHandleExA( + dwFlags: DWORD, lpModuleName: LPCSTR, phModule: *mut HMODULE, + ) -> BOOL; + pub fn GetModuleHandleExW( + dwFlags: DWORD, lpModuleName: LPCWSTR, phModule: *mut HMODULE, + ) -> BOOL; + pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; + pub fn GetNLSVersion( + Function: NLS_FUNCTION, Locale: LCID, lpVersionInformation: LPNLSVERSIONINFO, + ) -> BOOL; + pub fn GetNLSVersionEx( + function: NLS_FUNCTION, lpLocaleName: LPCWSTR, lpVersionInformation: LPNLSVERSIONINFOEX, + ) -> BOOL; + // pub fn GetNamedPipeAttribute(); + pub fn GetNamedPipeClientComputerNameA( + Pipe: HANDLE, ClientComputerName: LPSTR, ClientComputerNameLength: ULONG, + ) -> BOOL; + pub fn GetNamedPipeClientComputerNameW( + Pipe: HANDLE, ClientComputerName: LPWSTR, ClientComputerNameLength: ULONG, + ) -> BOOL; + pub fn GetNamedPipeClientProcessId(Pipe: HANDLE, ClientProcessId: PULONG) -> BOOL; + pub fn GetNamedPipeClientSessionId(Pipe: HANDLE, ClientSessionId: PULONG) -> BOOL; + pub fn GetNamedPipeHandleStateA( + hNamedPipe: HANDLE, lpState: LPDWORD, lpCurInstances: LPDWORD, + lpMaxCollectionCount: LPDWORD, lpCollectDataTimeout: LPDWORD, lpUserName: LPSTR, + nMaxUserNameSize: DWORD, + ) -> BOOL; + pub fn GetNamedPipeHandleStateW( + hNamedPipe: HANDLE, lpState: LPDWORD, lpCurInstances: LPDWORD, + lpMaxCollectionCount: LPDWORD, lpCollectDataTimeout: LPDWORD, lpUserName: LPWSTR, + nMaxUserNameSize: DWORD, + ) -> BOOL; + pub fn GetNamedPipeInfo( + hNamedPipe: HANDLE, lpFlags: LPDWORD, lpOutBufferSize: LPDWORD, lpInBufferSize: LPDWORD, + lpMaxInstances: LPDWORD, + ) -> BOOL; + pub fn GetNamedPipeServerProcessId(Pipe: HANDLE, ServerProcessId: PULONG) -> BOOL; + pub fn GetNamedPipeServerSessionId(Pipe: HANDLE, ServerSessionId: PULONG) -> BOOL; + pub fn GetNativeSystemInfo(lpSystemInfo: LPSYSTEM_INFO); + #[cfg(target_arch = "x86_64")] + pub fn GetNextUmsListItem(UmsContext: PUMS_CONTEXT) -> PUMS_CONTEXT; + pub fn GetNumaAvailableMemoryNode(Node: UCHAR, AvailableBytes: PULONGLONG) -> BOOL; + pub fn GetNumaAvailableMemoryNodeEx(Node: USHORT, AvailableBytes: PULONGLONG) -> BOOL; + pub fn GetNumaHighestNodeNumber(HighestNodeNumber: PULONG) -> BOOL; + pub fn GetNumaNodeNumberFromHandle(hFile: HANDLE, NodeNumber: PUSHORT) -> BOOL; + pub fn GetNumaNodeProcessorMask(Node: UCHAR, ProcessorMask: PULONGLONG) -> BOOL; + pub fn GetNumaNodeProcessorMaskEx(Node: USHORT, ProcessorMask: PGROUP_AFFINITY) -> BOOL; + pub fn GetNumaProcessorNode(Processor: UCHAR, NodeNumber: PUCHAR) -> BOOL; + pub fn GetNumaProcessorNodeEx(Processor: PPROCESSOR_NUMBER, NodeNumber: PUSHORT) -> BOOL; + pub fn GetNumaProximityNode(ProximityId: ULONG, NodeNumber: PUCHAR) -> BOOL; + pub fn GetNumaProximityNodeEx(ProximityId: ULONG, NodeNumber: PUSHORT) -> BOOL; + pub fn GetNumberFormatA( + Locale: LCID, dwFlags: DWORD, lpValue: LPCSTR, lpFormat: *const NUMBERFMTA, + lpNumberStr: LPSTR, cchNumber: c_int, + ) -> c_int; + pub fn GetNumberFormatEx( + lpLocaleName: LPCWSTR, dwFlags: DWORD, lpValue: LPCWSTR, lpFormat: *const NUMBERFMTW, + lpNumberStr: LPWSTR, cchNumber: c_int, + ) -> c_int; + pub fn GetNumberFormatW( + Locale: LCID, dwFlags: DWORD, lpValue: LPCWSTR, lpFormat: *const NUMBERFMTW, + lpNumberStr: LPWSTR, cchNumber: c_int, + ) -> c_int; + pub fn GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: LPDWORD) -> BOOL; + pub fn GetNumberOfConsoleMouseButtons(lpNumberOfMouseButtons: LPDWORD) -> BOOL; + pub fn GetOEMCP() -> UINT; + pub fn GetOverlappedResult( + hFile: HANDLE, lpOverlapped: LPOVERLAPPED, lpNumberOfBytesTransferred: LPDWORD, bWait: BOOL, + ) -> BOOL; + pub fn GetOverlappedResultEx( + hFile: HANDLE, lpOverlapped: LPOVERLAPPED, lpNumberOfBytesTransferred: LPDWORD, + dwMilliseconds: DWORD, bAlertable: BOOL, + ) -> BOOL; + // pub fn GetPackageApplicationIds(); + // pub fn GetPackageFamilyName(); + // pub fn GetPackageFullName(); + // pub fn GetPackageId(); + // pub fn GetPackageInfo(); + // pub fn GetPackagePath(); + // pub fn GetPackagePathByFullName(); + // pub fn GetPackagesByPackageFamily(); + pub fn GetPhysicallyInstalledSystemMemory(TotalMemoryInKilobytes: PULONGLONG) -> BOOL; + pub fn GetPriorityClass(hProcess: HANDLE) -> DWORD; + pub fn GetPrivateProfileIntA( + lpAppName: LPCSTR, lpKeyName: LPCSTR, nDefault: INT, lpFileName: LPCSTR, + ) -> UINT; + pub fn GetPrivateProfileIntW( + lpAppName: LPCWSTR, lpKeyName: LPCWSTR, nDefault: INT, lpFileName: LPCWSTR, + ) -> UINT; + pub fn GetPrivateProfileSectionA( + lpAppName: LPCSTR, lpReturnedString: LPSTR, nSize: DWORD, lpFileName: LPCSTR, + ) -> DWORD; + pub fn GetPrivateProfileSectionNamesA( + lpszReturnBuffer: LPSTR, nSize: DWORD, lpFileName: LPCSTR, + ) -> DWORD; + pub fn GetPrivateProfileSectionNamesW( + lpszReturnBuffer: LPWSTR, nSize: DWORD, lpFileName: LPCWSTR, + ) -> DWORD; + pub fn GetPrivateProfileSectionW( + lpAppName: LPCWSTR, lpReturnedString: LPWSTR, nSize: DWORD, lpFileName: LPCWSTR, + ) -> DWORD; + pub fn GetPrivateProfileStringA( + lpAppName: LPCSTR, lpKeyName: LPCSTR, lpDefault: LPCSTR, lpReturnedString: LPSTR, + nSize: DWORD, lpFileName: LPCSTR, + ) -> DWORD; + pub fn GetPrivateProfileStringW( + lpAppName: LPCWSTR, lpKeyName: LPCWSTR, lpDefault: LPCWSTR, lpReturnedString: LPWSTR, + nSize: DWORD, lpFileName: LPCWSTR, + ) -> DWORD; + pub fn GetPrivateProfileStructA( + lpszSection: LPCSTR, lpszKey: LPCSTR, lpStruct: LPVOID, uSizeStruct: UINT, szFile: LPCSTR, + ) -> BOOL; + pub fn GetPrivateProfileStructW( + lpszSection: LPCWSTR, lpszKey: LPCWSTR, lpStruct: LPVOID, uSizeStruct: UINT, + szFile: LPCWSTR, + ) -> BOOL; + pub fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> FARPROC; + pub fn GetProcessAffinityMask( + hProcess: HANDLE, lpProcessAffinityMask: PDWORD_PTR, lpSystemAffinityMask: PDWORD_PTR, + ) -> BOOL; + pub fn GetProcessDEPPolicy(hProcess: HANDLE, lpFlags: LPDWORD, lpPermanent: PBOOL) -> BOOL; + pub fn GetProcessGroupAffinity( + hProcess: HANDLE, GroupCount: PUSHORT, GroupArray: PUSHORT, + ) -> BOOL; + pub fn GetProcessHandleCount(hProcess: HANDLE, pdwHandleCount: PDWORD) -> BOOL; + pub fn GetProcessHeap() -> HANDLE; + pub fn GetProcessHeaps(NumberOfHeaps: DWORD, ProcessHeaps: PHANDLE) -> DWORD; + pub fn GetProcessId(Process: HANDLE) -> DWORD; + pub fn GetProcessIdOfThread(Thread: HANDLE) -> DWORD; + pub fn GetProcessInformation( + hProcess: HANDLE, ProcessInformationClass: PROCESS_INFORMATION_CLASS, + ProcessInformation: LPVOID, ProcessInformationSize: DWORD, + ) -> BOOL; + pub fn GetProcessIoCounters(hProcess: HANDLE, lpIoCounters: PIO_COUNTERS) -> BOOL; + pub fn GetProcessMitigationPolicy( + hProcess: HANDLE, MitigationPolicy: PROCESS_MITIGATION_POLICY, lpBuffer: PVOID, + dwLength: SIZE_T, + ) -> BOOL; + pub fn GetProcessPreferredUILanguages( + dwFlags: DWORD, pulNumLanguages: PULONG, pwszLanguagesBuffer: PZZWSTR, + pcchLanguagesBuffer: PULONG, + ) -> BOOL; + pub fn GetProcessPriorityBoost(hProcess: HANDLE, pDisablePriorityBoost: PBOOL) -> BOOL; + pub fn GetProcessShutdownParameters(lpdwLevel: LPDWORD, lpdwFlags: LPDWORD) -> BOOL; + pub fn GetProcessTimes( + hProcess: HANDLE, lpCreationTime: LPFILETIME, lpExitTime: LPFILETIME, + lpKernelTime: LPFILETIME, lpUserTime: LPFILETIME, + ) -> BOOL; + pub fn GetProcessVersion(ProcessId: DWORD) -> DWORD; + pub fn GetProcessWorkingSetSize( + hProcess: HANDLE, lpMinimumWorkingSetSize: PSIZE_T, lpMaximumWorkingSetSize: PSIZE_T, + ) -> BOOL; + pub fn GetProcessWorkingSetSizeEx( + hProcess: HANDLE, lpMinimumWorkingSetSize: PSIZE_T, lpMaximumWorkingSetSize: PSIZE_T, + Flags: PDWORD, + ) -> BOOL; + pub fn GetProcessorSystemCycleTime( + Group: USHORT, Buffer: PSYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION, ReturnedLength: PDWORD, + ) -> BOOL; + pub fn GetProductInfo( + dwOSMajorVersion: DWORD, dwOSMinorVersion: DWORD, dwSpMajorVersion: DWORD, + dwSpMinorVersion: DWORD, pdwReturnedProductType: PDWORD, + ) -> BOOL; + pub fn GetProfileIntA(lpAppName: LPCSTR, lpKeyName: LPCSTR, nDefault: INT) -> UINT; + pub fn GetProfileIntW(lpAppName: LPCWSTR, lpKeyName: LPCWSTR, nDefault: INT) -> UINT; + pub fn GetProfileSectionA(lpAppName: LPCSTR, lpReturnedString: LPSTR, nSize: DWORD) -> DWORD; + pub fn GetProfileSectionW(lpAppName: LPCWSTR, lpReturnedString: LPWSTR, nSize: DWORD) -> DWORD; + pub fn GetProfileStringA( + lpAppName: LPCSTR, lpKeyName: LPCSTR, lpDefault: LPCSTR, lpReturnedString: LPSTR, + nSize: DWORD, + ) -> DWORD; + pub fn GetProfileStringW( + lpAppName: LPCWSTR, lpKeyName: LPCWSTR, lpDefault: LPCWSTR, lpReturnedString: LPWSTR, + nSize: DWORD, + ) -> DWORD; + pub fn GetQueuedCompletionStatus( + CompletionPort: HANDLE, lpNumberOfBytesTransferred: LPDWORD, lpCompletionKey: PULONG_PTR, + lpOverlapped: *mut LPOVERLAPPED, dwMilliseconds: DWORD, + ) -> BOOL; + pub fn GetQueuedCompletionStatusEx( + CompletionPort: HANDLE, lpCompletionPortEntries: LPOVERLAPPED_ENTRY, ulCount: ULONG, + ulNumEntriesRemoved: PULONG, dwMilliseconds: DWORD, fAlertable: BOOL, + ) -> BOOL; + pub fn GetShortPathNameA( + lpszLongPath: LPCSTR, lpszShortPath: LPSTR, cchBuffer: DWORD, + ) -> DWORD; + pub fn GetShortPathNameW( + lpszLongPath: LPCWSTR, lpszShortPath: LPWSTR, cchBuffer: DWORD, + ) -> DWORD; + // pub fn GetStagedPackagePathByFullName(); + pub fn GetStartupInfoA(lpStartupInfo: LPSTARTUPINFOA); + pub fn GetStartupInfoW(lpStartupInfo: LPSTARTUPINFOW); + // pub fn GetStateFolder(); + pub fn GetStdHandle(nStdHandle: DWORD) -> HANDLE; + pub fn GetStringScripts( + dwFlags: DWORD, lpString: LPCWSTR, cchString: c_int, lpScripts: LPWSTR, cchScripts: c_int, + ) -> c_int; + pub fn GetStringTypeA( + Locale: LCID, dwInfoType: DWORD, lpSrcStr: LPCSTR, cchSrc: c_int, lpCharType: LPWORD, + ) -> BOOL; + pub fn GetStringTypeExA( + Locale: LCID, dwInfoType: DWORD, lpSrcStr: LPCSTR, cchSrc: c_int, lpCharType: LPWORD, + ) -> BOOL; + pub fn GetStringTypeExW( + Locale: LCID, dwInfoType: DWORD, lpSrcStr: LPCWCH, cchSrc: c_int, lpCharType: LPWORD, + ) -> BOOL; + pub fn GetStringTypeW( + dwInfoType: DWORD, lpSrcStr: LPCWCH, cchSrc: c_int, lpCharType: LPWORD, + ) -> BOOL; + // pub fn GetSystemAppDataKey(); + pub fn GetSystemDEPPolicy() -> DEP_SYSTEM_POLICY_TYPE; + pub fn GetSystemDefaultLCID() -> LCID; + pub fn GetSystemDefaultLangID() -> LANGID; + pub fn GetSystemDefaultLocaleName(lpLocaleName: LPWSTR, cchLocaleName: c_int) -> c_int; + pub fn GetSystemDefaultUILanguage() -> LANGID; + pub fn GetSystemDirectoryA(lpBuffer: LPSTR, uSize: UINT) -> UINT; + pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; + pub fn GetSystemFileCacheSize( + lpMinimumFileCacheSize: PSIZE_T, lpMaximumFileCacheSize: PSIZE_T, lpFlags: PDWORD, + ) -> BOOL; + pub fn GetSystemFirmwareTable( + FirmwareTableProviderSignature: DWORD, FirmwareTableID: DWORD, pFirmwareTableBuffer: PVOID, + BufferSize: DWORD, + ) -> UINT; + pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); + pub fn GetSystemPowerStatus(lpSystemPowerStatus: LPSYSTEM_POWER_STATUS) -> BOOL; + pub fn GetSystemPreferredUILanguages( + dwFlags: DWORD, pulNumLanguages: PULONG, pwszLanguagesBuffer: PZZWSTR, + pcchLanguagesBuffer: PULONG, + ) -> BOOL; + pub fn GetSystemRegistryQuota(pdwQuotaAllowed: PDWORD, pdwQuotaUsed: PDWORD) -> BOOL; + pub fn GetSystemTime(lpSystemTime: LPSYSTEMTIME); + pub fn GetSystemTimeAdjustment( + lpTimeAdjustment: PDWORD, lpTimeIncrement: PDWORD, lpTimeAdjustmentDisabled: PBOOL, + ) -> BOOL; + pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); + pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); + pub fn GetSystemTimes( + lpIdleTime: LPFILETIME, lpKernelTime: LPFILETIME, lpUserTime: LPFILETIME, + ) -> BOOL; + pub fn GetSystemWindowsDirectoryA(lpBuffer: LPSTR, uSize: UINT) -> UINT; + pub fn GetSystemWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; + pub fn GetSystemWow64DirectoryA(lpBuffer: LPSTR, uSize: UINT) -> UINT; + pub fn GetSystemWow64DirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; + pub fn GetTapeParameters( + hDevice: HANDLE, dwOperation: DWORD, lpdwSize: LPDWORD, lpTapeInformation: LPVOID + ) -> DWORD; + pub fn GetTapePosition( + hDevice: HANDLE, dwPositionType: DWORD, lpdwPartition: LPDWORD, + lpdwOffsetLow: LPDWORD, lpdwOffsetHigh: LPDWORD + ) -> DWORD; + pub fn GetTapeStatus(hDevice: HANDLE) -> DWORD; + pub fn GetTempFileNameA( + lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: LPSTR, + ) -> UINT; + pub fn GetTempFileNameW( + lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: LPWSTR, + ) -> UINT; + pub fn GetTempPathA(nBufferLength: DWORD, lpBuffer: LPSTR) -> DWORD; + pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; + pub fn GetThreadContext(hThread: HANDLE, lpContext: LPCONTEXT) -> BOOL; + pub fn GetThreadErrorMode() -> DWORD; + pub fn GetThreadGroupAffinity(hThread: HANDLE, GroupAffinity: PGROUP_AFFINITY) -> BOOL; + pub fn GetThreadIOPendingFlag(hThread: HANDLE, lpIOIsPending: PBOOL) -> BOOL; + pub fn GetThreadId(Thread: HANDLE) -> DWORD; + pub fn GetThreadIdealProcessorEx(hThread: HANDLE, lpIdealProcessor: PPROCESSOR_NUMBER) -> BOOL; + pub fn GetThreadInformation( + hThread: HANDLE, ThreadInformationClass: THREAD_INFORMATION_CLASS, + ThreadInformation: LPVOID, ThreadInformationSize: DWORD, + ) -> BOOL; + pub fn GetThreadLocale() -> LCID; + pub fn GetThreadPreferredUILanguages( + dwFlags: DWORD, pulNumLanguages: PULONG, pwszLanguagesBuffer: PZZWSTR, + pcchLanguagesBuffer: PULONG, + ) -> BOOL; + pub fn GetThreadPriority(hThread: HANDLE) -> c_int; + pub fn GetThreadPriorityBoost(hThread: HANDLE, pDisablePriorityBoost: PBOOL) -> BOOL; + pub fn GetThreadSelectorEntry( + hThread: HANDLE, dwSelector: DWORD, lpSelectorEntry: LPLDT_ENTRY, + ) -> BOOL; + pub fn GetThreadTimes( + hThread: HANDLE, lpCreationTime: LPFILETIME, lpExitTime: LPFILETIME, + lpKernelTime: LPFILETIME, lpUserTime: LPFILETIME, + ) -> BOOL; + pub fn GetThreadUILanguage() -> LANGID; + pub fn GetTickCount() -> DWORD; + pub fn GetTickCount64() -> ULONGLONG; + pub fn GetTimeFormatA( + Locale: LCID, dwFlags: DWORD, lpTime: *const SYSTEMTIME, lpFormat: LPCSTR, + lpTimeStr: LPSTR, cchTime: c_int, + ) -> c_int; + pub fn GetTimeFormatEx( + lpLocaleName: LPCWSTR, dwFlags: DWORD, lpTime: *const SYSTEMTIME, lpFormat: LPCWSTR, + lpTimeStr: LPWSTR, cchTime: c_int, + ) -> c_int; + pub fn GetTimeFormatW( + Locale: LCID, dwFlags: DWORD, lpTime: *const SYSTEMTIME, lpFormat: LPCWSTR, + lpTimeStr: LPWSTR, cchTime: c_int, + ) -> c_int; + pub fn GetTimeZoneInformation(lpTimeZoneInformation: LPTIME_ZONE_INFORMATION) -> DWORD; + pub fn GetTimeZoneInformationForYear( + wYear: USHORT, pdtzi: PDYNAMIC_TIME_ZONE_INFORMATION, ptzi: LPTIME_ZONE_INFORMATION, + ) -> BOOL; + pub fn GetUILanguageInfo( + dwFlags: DWORD, pwmszLanguage: PCZZWSTR, pwszFallbackLanguages: PZZWSTR, + pcchFallbackLanguages: PDWORD, pAttributes: PDWORD, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn GetUmsCompletionListEvent( + UmsCompletionList: PUMS_COMPLETION_LIST, UmsCompletionEvent: PHANDLE, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn GetUmsSystemThreadInformation( + ThreadHandle: HANDLE, SystemThreadInfo: PUMS_SYSTEM_THREAD_INFORMATION, + ) -> BOOL; + pub fn GetUserDefaultLCID() -> LCID; + pub fn GetUserDefaultLangID() -> LANGID; + pub fn GetUserDefaultLocaleName(lpLocaleName: LPWSTR, cchLocaleName: c_int) -> c_int; + pub fn GetUserDefaultUILanguage() -> LANGID; + pub fn GetUserGeoID(GeoClass: GEOCLASS) -> GEOID; + pub fn GetUserPreferredUILanguages( + dwFlags: DWORD, pulNumLanguages: PULONG, pwszLanguagesBuffer: PZZWSTR, + pcchLanguagesBuffer: PULONG, + ) -> BOOL; + pub fn GetVersion() -> DWORD; + pub fn GetVersionExA(lpVersionInformation: LPOSVERSIONINFOA) -> BOOL; + pub fn GetVersionExW(lpVersionInformation: LPOSVERSIONINFOW) -> BOOL; + pub fn GetVolumeInformationA( + lpRootPathName: LPCSTR, lpVolumeNameBuffer: LPSTR, nVolumeNameSize: DWORD, + lpVolumeSerialNumber: LPDWORD, lpMaximumComponentLength: LPDWORD, + lpFileSystemFlags: LPDWORD, lpFileSystemNameBuffer: LPSTR, nFileSystemNameSize: DWORD, + ) -> BOOL; + pub fn GetVolumeInformationByHandleW( + hFile: HANDLE, lpVolumeNameBuffer: LPWSTR, nVolumeNameSize: DWORD, + lpVolumeSerialNumber: LPDWORD, lpMaximumComponentLength: LPDWORD, + lpFileSystemFlags: LPDWORD, lpFileSystemNameBuffer: LPWSTR, nFileSystemNameSize: DWORD, + ) -> BOOL; + pub fn GetVolumeInformationW( + lpRootPathName: LPCWSTR, lpVolumeNameBuffer: LPWSTR, nVolumeNameSize: DWORD, + lpVolumeSerialNumber: LPDWORD, lpMaximumComponentLength: LPDWORD, + lpFileSystemFlags: LPDWORD, lpFileSystemNameBuffer: LPWSTR, nFileSystemNameSize: DWORD, + ) -> BOOL; + pub fn GetVolumeNameForVolumeMountPointA( + lpszVolumeMountPoint: LPCSTR, lpszVolumeName: LPSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn GetVolumeNameForVolumeMountPointW( + lpszVolumeMountPoint: LPCWSTR, lpszVolumeName: LPWSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn GetVolumePathNameA( + lpszFileName: LPCSTR, lpszVolumePathName: LPSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn GetVolumePathNameW( + lpszFileName: LPCWSTR, lpszVolumePathName: LPWSTR, cchBufferLength: DWORD, + ) -> BOOL; + pub fn GetVolumePathNamesForVolumeNameA( + lpszVolumeName: LPCSTR, lpszVolumePathNames: LPCH, cchBufferLength: DWORD, + lpcchReturnLength: PDWORD, + ) -> BOOL; + pub fn GetVolumePathNamesForVolumeNameW( + lpszVolumeName: LPCWSTR, lpszVolumePathNames: LPWCH, cchBufferLength: DWORD, + lpcchReturnLength: PDWORD, + ) -> BOOL; + pub fn GetWindowsDirectoryA(lpBuffer: LPSTR, uSize: UINT) -> UINT; + pub fn GetWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; + pub fn GetWriteWatch( + dwFlags: DWORD, lpBaseAddress: PVOID, dwRegionSize: SIZE_T, lpAddresses: *mut PVOID, + lpdwCount: *mut ULONG_PTR, lpdwGranularity: LPDWORD, + ) -> UINT; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn GetXStateFeaturesMask(Context: PCONTEXT, FeatureMask: PDWORD64) -> BOOL; + pub fn GlobalAddAtomA(lpString: LPCSTR) -> ATOM; + pub fn GlobalAddAtomExA(lpString: LPCSTR, Flags: DWORD) -> ATOM; + pub fn GlobalAddAtomExW(lpString: LPCWSTR, Flags: DWORD) -> ATOM; + pub fn GlobalAddAtomW(lpString: LPCWSTR) -> ATOM; + pub fn GlobalAlloc(uFlags: UINT, dwBytes: SIZE_T) -> HGLOBAL; + pub fn GlobalCompact(dwMinFree: DWORD) -> SIZE_T; + pub fn GlobalDeleteAtom(nAtom: ATOM) -> ATOM; + pub fn GlobalFindAtomA(lpString: LPCSTR) -> ATOM; + pub fn GlobalFindAtomW(lpString: LPCWSTR) -> ATOM; + pub fn GlobalFix(hMem: HGLOBAL); + pub fn GlobalFlags(hMem: HGLOBAL) -> UINT; + pub fn GlobalFree(hMem: HGLOBAL) -> HGLOBAL; + pub fn GlobalGetAtomNameA(nAtom: ATOM, lpBuffer: LPSTR, nSize: c_int) -> UINT; + pub fn GlobalGetAtomNameW(nAtom: ATOM, lpBuffer: LPWSTR, nSize: c_int) -> UINT; + pub fn GlobalHandle(pMem: LPCVOID) -> HGLOBAL; + pub fn GlobalLock(hMem: HGLOBAL) -> LPVOID; + pub fn GlobalMemoryStatus(lpBuffer: LPMEMORYSTATUS); + pub fn GlobalMemoryStatusEx(lpBuffer: LPMEMORYSTATUSEX) -> BOOL; + pub fn GlobalReAlloc(hMem: HGLOBAL, dwBytes: SIZE_T, uFlags: UINT) -> HGLOBAL; + pub fn GlobalSize(hMem: HGLOBAL) -> SIZE_T; + pub fn GlobalUnWire(hMem: HGLOBAL) -> BOOL; + pub fn GlobalUnfix(hMem: HGLOBAL); + pub fn GlobalUnlock(hMem: HGLOBAL) -> BOOL; + pub fn GlobalWire(hMem: HGLOBAL) -> LPVOID; + pub fn Heap32First(lphe: LPHEAPENTRY32, th32ProcessID: DWORD, th32HeapID: ULONG_PTR) -> BOOL; + pub fn Heap32ListFirst(hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL; + pub fn Heap32ListNext(hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL; + pub fn Heap32Next(lphe: LPHEAPENTRY32) -> BOOL; + pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + pub fn HeapCompact(hHeap: HANDLE, dwFlags: DWORD) -> SIZE_T; + pub fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) -> HANDLE; + pub fn HeapDestroy(hHeap: HANDLE) -> BOOL; + pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + pub fn HeapLock(hHeap: HANDLE) -> BOOL; + pub fn HeapQueryInformation( + HeapHandle: HANDLE, HeapInformationClass: HEAP_INFORMATION_CLASS, HeapInformation: PVOID, + HeapInformationLength: SIZE_T, ReturnLength: PSIZE_T, + ) -> BOOL; + pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; + pub fn HeapSetInformation( + HeapHandle: HANDLE, HeapInformationClass: HEAP_INFORMATION_CLASS, HeapInformation: PVOID, + HeapInformationLength: SIZE_T, + ) -> BOOL; + pub fn HeapSize(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPCVOID) -> SIZE_T; + pub fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) -> BOOL; + pub fn HeapUnlock(hHeap: HANDLE) -> BOOL; + pub fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPCVOID) -> BOOL; + pub fn HeapWalk(hHeap: HANDLE, lpEntry: LPPROCESS_HEAP_ENTRY) -> BOOL; + pub fn InitAtomTable(nSize: DWORD) -> BOOL; + pub fn InitOnceBeginInitialize( + lpInitOnce: LPINIT_ONCE, dwFlags: DWORD, fPending: PBOOL, lpContext: *mut LPVOID, + ) -> BOOL; + pub fn InitOnceComplete( + lpInitOnce: LPINIT_ONCE, dwFlags: DWORD, lpContext: LPVOID, + ) -> BOOL; + pub fn InitOnceExecuteOnce( + InitOnce: PINIT_ONCE, InitFn: PINIT_ONCE_FN, Parameter: PVOID, Context: *mut LPVOID, + ) -> BOOL; + pub fn InitOnceInitialize(InitOnce: PINIT_ONCE); + pub fn InitializeConditionVariable(ConditionVariable: PCONDITION_VARIABLE); + pub fn InitializeContext( + Buffer: PVOID, ContextFlags: DWORD, Context: *mut PCONTEXT, ContextLength: PDWORD, + ) -> BOOL; + pub fn InitializeCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + pub fn InitializeCriticalSectionAndSpinCount( + lpCriticalSection: LPCRITICAL_SECTION, dwSpinCount: DWORD, + ) -> BOOL; + pub fn InitializeCriticalSectionEx( + lpCriticalSection: LPCRITICAL_SECTION, dwSpinCount: DWORD, Flags: DWORD, + ) -> BOOL; + pub fn InitializeProcThreadAttributeList( + lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, dwAttributeCount: DWORD, dwFlags: DWORD, + lpSize: PSIZE_T, + ) -> BOOL; + pub fn InitializeSListHead(ListHead: PSLIST_HEADER); + pub fn InitializeSRWLock(SRWLock: PSRWLOCK); + pub fn InitializeSynchronizationBarrier( + lpBarrier: LPSYNCHRONIZATION_BARRIER, lTotalThreads: LONG, lSpinCount: LONG, + ) -> BOOL; + pub fn InstallELAMCertificateInfo(ELAMFile: HANDLE) -> BOOL; + #[cfg(target_arch = "x86")] + pub fn InterlockedCompareExchange( + Destination: *mut LONG, ExChange: LONG, Comperand: LONG, + ) -> LONG; + #[cfg(target_arch = "x86")] + pub fn InterlockedCompareExchange64( + Destination: *mut LONG64, ExChange: LONG64, Comperand: LONG64, + ) -> LONG64; + #[cfg(target_arch = "x86")] + pub fn InterlockedDecrement(Addend: *mut LONG) -> LONG; + #[cfg(target_arch = "x86")] + pub fn InterlockedExchange(Target: *mut LONG, Value: LONG) -> LONG; + #[cfg(target_arch = "x86")] + pub fn InterlockedExchangeAdd(Addend: *mut LONG, Value: LONG) -> LONG; + pub fn InterlockedFlushSList(ListHead: PSLIST_HEADER) -> PSLIST_ENTRY; + #[cfg(target_arch = "x86")] + pub fn InterlockedIncrement(Addend: *mut LONG) -> LONG; + pub fn InterlockedPopEntrySList(ListHead: PSLIST_HEADER) -> PSLIST_ENTRY; + pub fn InterlockedPushEntrySList( + ListHead: PSLIST_HEADER, ListEntry: PSLIST_ENTRY, + ) -> PSLIST_ENTRY; + pub fn InterlockedPushListSListEx( + ListHead: PSLIST_HEADER, List: PSLIST_ENTRY, ListEnd: PSLIST_ENTRY, Count: ULONG, + ) -> PSLIST_ENTRY; + pub fn IsBadCodePtr(lpfn: FARPROC) -> BOOL; + pub fn IsBadHugeReadPtr(lp: *const VOID, ucb: UINT_PTR) -> BOOL; + pub fn IsBadHugeWritePtr(lp: LPVOID, ucb: UINT_PTR) -> BOOL; + pub fn IsBadReadPtr(lp: *const VOID, ucb: UINT_PTR) -> BOOL; + pub fn IsBadStringPtrA(lpsz: LPCSTR, ucchMax: UINT_PTR) -> BOOL; + pub fn IsBadStringPtrW(lpsz: LPCWSTR, ucchMax: UINT_PTR) -> BOOL; + pub fn IsBadWritePtr(lp: LPVOID, ucb: UINT_PTR) -> BOOL; + pub fn IsDBCSLeadByte(TestChar: BYTE) -> BOOL; + pub fn IsDBCSLeadByteEx(CodePage: UINT, TestChar: BYTE) -> BOOL; + pub fn IsDebuggerPresent() -> BOOL; + pub fn IsNLSDefinedString( + Function: NLS_FUNCTION, dwFlags: DWORD, lpVersionInformation: LPNLSVERSIONINFO, + lpString: LPCWSTR, cchStr: INT, + ) -> BOOL; + pub fn IsNativeVhdBoot(NativeVhdBoot: PBOOL) -> BOOL; + pub fn IsNormalizedString(NormForm: NORM_FORM, lpString: LPCWSTR, cwLength: c_int) -> BOOL; + pub fn IsProcessCritical(hProcess: HANDLE, Critical: PBOOL) -> BOOL; + pub fn IsProcessInJob(ProcessHandle: HANDLE, JobHandle: HANDLE, Result: PBOOL) -> BOOL; + pub fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL; + pub fn IsSystemResumeAutomatic() -> BOOL; + pub fn IsThreadAFiber() -> BOOL; + pub fn IsThreadpoolTimerSet(pti: PTP_TIMER) -> BOOL; + pub fn IsValidCodePage(CodePage: UINT) -> BOOL; + pub fn IsValidLanguageGroup(LanguageGroup: LGRPID, dwFlags: DWORD) -> BOOL; + pub fn IsValidLocale(Locale: LCID, dwFlags: DWORD) -> BOOL; + pub fn IsValidLocaleName(lpLocaleName: LPCWSTR) -> BOOL; + pub fn IsValidNLSVersion( + function: NLS_FUNCTION, lpLocaleName: LPCWSTR, lpVersionInformation: LPNLSVERSIONINFOEX, + ) -> BOOL; + pub fn IsWow64Process(hProcess: HANDLE, Wow64Process: PBOOL) -> BOOL; + pub fn K32EmptyWorkingSet(hProcess: HANDLE) -> BOOL; + pub fn K32EnumDeviceDrivers(lpImageBase: *mut LPVOID, cb: DWORD, lpcbNeeded: LPDWORD) -> BOOL; + pub fn K32EnumPageFilesA( + pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKA, pContext: LPVOID, + ) -> BOOL; + pub fn K32EnumPageFilesW( + pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKW, pContext: LPVOID, + ) -> BOOL; + pub fn K32EnumProcessModules( + hProcess: HANDLE, lphModule: *mut HMODULE, cb: DWORD, lpcbNeeded: LPDWORD, + ) -> BOOL; + pub fn K32EnumProcessModulesEx( + hProcess: HANDLE, lphModule: *mut HMODULE, cb: DWORD, lpcbNeeded: LPDWORD, + dwFilterFlag: DWORD, + ) -> BOOL; + pub fn K32EnumProcesses( + lpidProcess: *mut DWORD, cb: DWORD, lpcbNeeded: LPDWORD, + ) -> BOOL; + pub fn K32GetDeviceDriverBaseNameA(ImageBase: LPVOID, lpFilename: LPSTR, nSize: DWORD) -> DWORD; + pub fn K32GetDeviceDriverBaseNameW( + ImageBase: LPVOID, lpFilename: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetDeviceDriverFileNameA(ImageBase: LPVOID, lpFilename: LPSTR, nSize: DWORD) -> DWORD; + pub fn K32GetDeviceDriverFileNameW( + ImageBase: LPVOID, lpFilename: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetMappedFileNameA( + hProcess: HANDLE, lpv: LPVOID, lpFilename: LPSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetMappedFileNameW( + hProcess: HANDLE, lpv: LPVOID, lpFilename: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetModuleBaseNameA( + hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetModuleBaseNameW( + hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetModuleFileNameExA( + hProcess: HANDLE, hModule: HMODULE, lpFilename: LPSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetModuleFileNameExW( + hProcess: HANDLE, hModule: HMODULE, lpFilename: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetModuleInformation( + hProcess: HANDLE, hModule: HMODULE, lpmodinfo: LPMODULEINFO, cb: DWORD, + ) -> BOOL; + pub fn K32GetPerformanceInfo( + pPerformanceInformation: PPERFORMANCE_INFORMATION, cb: DWORD, + ) -> BOOL; + pub fn K32GetProcessImageFileNameA( + hProcess: HANDLE, lpImageFileName: LPSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetProcessImageFileNameW( + hProcess: HANDLE, lpImageFileName: LPWSTR, nSize: DWORD, + ) -> DWORD; + pub fn K32GetProcessMemoryInfo( + Process: HANDLE, ppsmemCounters: PPROCESS_MEMORY_COUNTERS, cb: DWORD, + ) -> BOOL; + pub fn K32GetWsChanges( + hProcess: HANDLE, lpWatchInfo: PPSAPI_WS_WATCH_INFORMATION, cb: DWORD, + ) -> BOOL; + pub fn K32GetWsChangesEx( + hProcess: HANDLE, lpWatchInfoEx: PPSAPI_WS_WATCH_INFORMATION_EX, cb: PDWORD, + ) -> BOOL; + pub fn K32InitializeProcessForWsWatch(hProcess: HANDLE) -> BOOL; + pub fn K32QueryWorkingSet(hProcess: HANDLE, pv: PVOID, cb: DWORD) -> BOOL; + pub fn K32QueryWorkingSetEx(hProcess: HANDLE, pv: PVOID, cb: DWORD) -> BOOL; + pub fn LCIDToLocaleName(Locale: LCID, lpName: LPWSTR, cchName: c_int, dwFlags: DWORD) -> c_int; + pub fn LCMapStringA( + Locale: LCID, dwMapFlags: DWORD, lpSrcStr: LPCSTR, cchSrc: c_int, lpDestStr: LPSTR, + cchDest: c_int, + ) -> c_int; + pub fn LCMapStringEx( + lpLocaleName: LPCWSTR, dwMapFlags: DWORD, lpSrcStr: LPCWSTR, cchSrc: c_int, + lpDestStr: LPWSTR, cchDest: c_int, lpVersionInformation: LPNLSVERSIONINFO, + lpReserved: LPVOID, sortHandle: LPARAM, + ) -> c_int; + pub fn LCMapStringW( + Locale: LCID, dwMapFlags: DWORD, lpSrcStr: LPCWSTR, cchSrc: c_int, lpDestStr: LPWSTR, + cchDest: c_int, + ) -> c_int; + pub fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + pub fn LeaveCriticalSectionWhenCallbackReturns( + pci: PTP_CALLBACK_INSTANCE, pcs: PCRITICAL_SECTION, + ); + // pub fn LoadAppInitDlls(); + pub fn LoadLibraryA(lpFileName: LPCSTR) -> HMODULE; + pub fn LoadLibraryExA(lpLibFileName: LPCSTR, hFile: HANDLE, dwFlags: DWORD) -> HMODULE; + pub fn LoadLibraryExW(lpLibFileName: LPCWSTR, hFile: HANDLE, dwFlags: DWORD) -> HMODULE; + pub fn LoadLibraryW(lpFileName: LPCWSTR) -> HMODULE; + pub fn LoadModule(lpModuleName: LPCSTR, lpParameterBlock: LPVOID) -> DWORD; + pub fn LoadPackagedLibrary(lpwLibFileName: LPCWSTR, Reserved: DWORD) -> HMODULE; + pub fn LoadResource(hModule: HMODULE, hResInfo: HRSRC) -> HGLOBAL; + // pub fn LoadStringBaseExW(); + // pub fn LoadStringBaseW(); + pub fn LocalAlloc(uFlags: UINT, uBytes: SIZE_T) -> HLOCAL; + pub fn LocalCompact(uMinFree: UINT) -> SIZE_T; + pub fn LocalFileTimeToFileTime( + lpLocalFileTime: *const FILETIME, lpFileTime: LPFILETIME, + ) -> BOOL; + pub fn LocalFlags(hMem: HLOCAL) -> UINT; + pub fn LocalFree(hMem: HLOCAL) -> HLOCAL; + pub fn LocalHandle(pMem: LPCVOID) -> HLOCAL; + pub fn LocalLock(hMem: HLOCAL) -> LPVOID; + pub fn LocalReAlloc(hMem: HLOCAL, uBytes: SIZE_T, uFlags: UINT) -> HLOCAL; + pub fn LocalShrink(hMem: HLOCAL, cbNewSize: UINT) -> SIZE_T; + pub fn LocalSize(hMem: HLOCAL) -> SIZE_T; + pub fn LocalUnlock(hMem: HLOCAL) -> BOOL; + pub fn LocaleNameToLCID(lpName: LPCWSTR, dwFlags: DWORD) -> LCID; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn LocateXStateFeature(Context: PCONTEXT, FeatureId: DWORD, Length: PDWORD) -> PVOID; + pub fn LockFile( + hFile: HANDLE, dwFileOffsetLow: DWORD, dwFileOffsetHigh: DWORD, + nNumberOfBytesToLockLow: DWORD, nNumberOfBytesToLockHigh: DWORD, + ) -> BOOL; + pub fn LockFileEx( + hFile: HANDLE, dwFlags: DWORD, dwReserved: DWORD, nNumberOfBytesToLockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn LockResource(hResData: HGLOBAL) -> LPVOID; + pub fn MapUserPhysicalPages( + VirtualAddress: PVOID, NumberOfPages: ULONG_PTR, PageArray: PULONG_PTR, + ) -> BOOL; + pub fn MapUserPhysicalPagesScatter( + VirtualAddresses: *mut PVOID, NumberOfPages: ULONG_PTR, PageArray: PULONG_PTR, + ) -> BOOL; + pub fn MapViewOfFile( + hFileMappingObject: HANDLE, dwDesiredAccess: DWORD, dwFileOffsetHigh: DWORD, + dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, + ) -> LPVOID; + pub fn MapViewOfFileEx( + hFileMappingObject: HANDLE, dwDesiredAccess: DWORD, dwFileOffsetHigh: DWORD, + dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, lpBaseAddress: LPVOID, + ) -> LPVOID; + pub fn MapViewOfFileExNuma( + hFileMappingObject: HANDLE, dwDesiredAccess: DWORD, dwFileOffsetHigh: DWORD, + dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, lpBaseAddress: LPVOID, + nndPreferred: DWORD, + ) -> LPVOID; + pub fn MapViewOfFileFromApp( + hFileMappingObject: HANDLE, DesiredAccess: ULONG, FileOffset: ULONG64, + NumberOfBytesToMap: SIZE_T, + ) -> PVOID; + pub fn Module32First(hSnapshot: HANDLE, lpme: LPMODULEENTRY32) -> BOOL; + pub fn Module32FirstW(hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL; + pub fn Module32Next(hSnapshot: HANDLE, lpme: LPMODULEENTRY32) -> BOOL; + pub fn Module32NextW(hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL; + pub fn MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL; + pub fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: DWORD) -> BOOL; + pub fn MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: DWORD) -> BOOL; + pub fn MoveFileTransactedA( + lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, dwFlags: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn MoveFileTransactedW( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, dwFlags: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL; + pub fn MoveFileWithProgressA( + lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, dwFlags: DWORD, + ) -> BOOL; + pub fn MoveFileWithProgressW( + lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, + lpData: LPVOID, dwFlags: DWORD, + ) -> BOOL; + pub fn MulDiv(nNumber: c_int, nNumerator: c_int, nDenominator: c_int) -> c_int; + pub fn MultiByteToWideChar( + CodePage: UINT, dwFlags: DWORD, lpMultiByteStr: LPCSTR, cbMultiByte: c_int, + lpWideCharStr: LPWSTR, cchWideChar: c_int, + ) -> c_int; + pub fn NeedCurrentDirectoryForExePathA(ExeName: LPCSTR) -> BOOL; + pub fn NeedCurrentDirectoryForExePathW(ExeName: LPCWSTR) -> BOOL; + pub fn NormalizeString( + NormForm: NORM_FORM, lpSrcString: LPCWSTR, cwSrcLength: c_int, lpDstString: LPWSTR, + cwDstLength: c_int, + ) -> c_int; + // pub fn NotifyMountMgr(); + pub fn NotifyUILanguageChange( + dwFlags: DWORD, pcwstrNewLanguage: PCWSTR, pcwstrPreviousLanguage: PCWSTR, + dwReserved: DWORD, pdwStatusRtrn: PDWORD, + ) -> BOOL; + // pub fn OOBEComplete(); + pub fn OpenEventA(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE; + pub fn OpenEventW(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE; + pub fn OpenFile(lpFileName: LPCSTR, lpReOpenBuff: LPOFSTRUCT, uStyle: UINT) -> HFILE; + pub fn OpenFileById( + hVolumeHint: HANDLE, lpFileId: LPFILE_ID_DESCRIPTOR, dwDesiredAccess: DWORD, + dwShareMode: DWORD, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + dwFlagsAndAttributes: DWORD, + ) -> HANDLE; + pub fn OpenFileMappingA( + dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCSTR, + ) -> HANDLE; + pub fn OpenFileMappingW( + dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR, + ) -> HANDLE; + pub fn OpenJobObjectA(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE; + pub fn OpenJobObjectW(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE; + pub fn OpenMutexA(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE; + pub fn OpenMutexW(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE; + // pub fn OpenPackageInfoByFullName(); + pub fn OpenPrivateNamespaceA(lpBoundaryDescriptor: LPVOID, lpAliasPrefix: LPCSTR) -> HANDLE; + pub fn OpenPrivateNamespaceW(lpBoundaryDescriptor: LPVOID, lpAliasPrefix: LPCWSTR) -> HANDLE; + pub fn OpenProcess(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE; + pub fn OpenSemaphoreA(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE; + pub fn OpenSemaphoreW(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE; + // pub fn OpenState(); + // pub fn OpenStateExplicit(); + pub fn OpenThread(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwThreadId: DWORD) -> HANDLE; + pub fn OpenWaitableTimerA( + dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpTimerName: LPCSTR, + ) -> HANDLE; + pub fn OpenWaitableTimerW( + dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpTimerName: LPCWSTR, + ) -> HANDLE; + pub fn OutputDebugStringA(lpOutputString: LPCSTR); + pub fn OutputDebugStringW(lpOutputString: LPCWSTR); + // pub fn PackageFamilyNameFromFullName(); + // pub fn PackageFamilyNameFromId(); + // pub fn PackageFullNameFromId(); + // pub fn PackageIdFromFullName(); + // pub fn PackageNameAndPublisherIdFromFamilyName(); + // pub fn ParseApplicationUserModelId(); + pub fn PeekConsoleInputA( + hConsoleInput: HANDLE, lpBuffer: PINPUT_RECORD, nLength: DWORD, + lpNumberOfEventsRead: LPDWORD, + ) -> BOOL; + pub fn PeekConsoleInputW( + hConsoleInput: HANDLE, lpBuffer: PINPUT_RECORD, nLength: DWORD, + lpNumberOfEventsRead: LPDWORD, + ) -> BOOL; + pub fn PeekNamedPipe( + hNamedPipe: HANDLE, lpBuffer: LPVOID, nBufferSize: DWORD, lpBytesRead: LPDWORD, + lpTotalBytesAvail: LPDWORD, lpBytesLeftThisMessage: LPDWORD, + ) -> BOOL; + pub fn PostQueuedCompletionStatus( + CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: ULONG_PTR, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn PowerClearRequest(PowerRequest: HANDLE, RequestType: POWER_REQUEST_TYPE) -> BOOL; + pub fn PowerCreateRequest(Context: PREASON_CONTEXT) -> HANDLE; + pub fn PowerSetRequest(PowerRequest: HANDLE, RequestType: POWER_REQUEST_TYPE) -> BOOL; + pub fn PrefetchVirtualMemory( + hProcess: HANDLE, NumberOfEntries: ULONG_PTR, VirtualAddresses: PWIN32_MEMORY_RANGE_ENTRY, + Flags: ULONG, + ) -> BOOL; + pub fn PrepareTape(hDevice: HANDLE, dwOperation: DWORD, bImmediate: BOOL) -> DWORD; + pub fn Process32First(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32) -> BOOL; + pub fn Process32FirstW(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL; + pub fn Process32Next(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32) -> BOOL; + pub fn Process32NextW(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL; + pub fn ProcessIdToSessionId(dwProcessId: DWORD, pSessionId: *mut DWORD) -> BOOL; + pub fn PssCaptureSnapshot( + ProcessHandle: HANDLE, CaptureFlags: PSS_CAPTURE_FLAGS, ThreadContextFlags: DWORD, + SnapshotHandle: *mut HPSS, + ) -> DWORD; + pub fn PssDuplicateSnapshot( + SourceProcessHandle: HANDLE, SnapshotHandle: HPSS, TargetProcessHandle: HANDLE, + TargetSnapshotHandle: *mut HPSS, Flags: PSS_DUPLICATE_FLAGS, + ) -> DWORD; + pub fn PssFreeSnapshot(ProcessHandle: HANDLE, SnapshotHandle: HPSS) -> DWORD; + pub fn PssQuerySnapshot( + SnapshotHandle: HPSS, InformationClass: PSS_QUERY_INFORMATION_CLASS, Buffer: *mut c_void, + BufferLength: DWORD, + ) -> DWORD; + pub fn PssWalkMarkerCreate( + Allocator: *const PSS_ALLOCATOR, WalkMarkerHandle: *mut HPSSWALK, + ) -> DWORD; + pub fn PssWalkMarkerFree(WalkMarkerHandle: HPSSWALK) -> DWORD; + pub fn PssWalkMarkerGetPosition(WalkMarkerHandle: HPSSWALK, Position: *mut ULONG_PTR) -> DWORD; + // pub fn PssWalkMarkerRewind(); + // pub fn PssWalkMarkerSeek(); + pub fn PssWalkMarkerSeekToBeginning(WalkMarkerHandle: HPSS) -> DWORD; + pub fn PssWalkMarkerSetPosition(WalkMarkerHandle: HPSSWALK, Position: ULONG_PTR) -> DWORD; + // pub fn PssWalkMarkerTell(); + pub fn PssWalkSnapshot( + SnapshotHandle: HPSS, InformationClass: PSS_WALK_INFORMATION_CLASS, + WalkMarkerHandle: HPSSWALK, Buffer: *mut c_void, BufferLength: DWORD, + ) -> DWORD; + pub fn PulseEvent(hEvent: HANDLE) -> BOOL; + pub fn PurgeComm(hFile: HANDLE, dwFlags: DWORD) -> BOOL; + pub fn QueryActCtxSettingsW( + dwFlags: DWORD, hActCtx: HANDLE, settingsNameSpace: PCWSTR, settingName: PCWSTR, + pvBuffer: PWSTR, dwBuffer: SIZE_T, pdwWrittenOrRequired: *mut SIZE_T, + ) -> BOOL; + pub fn QueryActCtxW( + dwFlags: DWORD, hActCtx: HANDLE, pvSubInstance: PVOID, ulInfoClass: ULONG, pvBuffer: PVOID, + cbBuffer: SIZE_T, pcbWrittenOrRequired: *mut SIZE_T, + ) -> BOOL; + pub fn QueryDepthSList(ListHead: PSLIST_HEADER) -> USHORT; + pub fn QueryDosDeviceA(lpDeviceName: LPCSTR, lpTargetPath: LPSTR, ucchMax: DWORD) -> DWORD; + pub fn QueryDosDeviceW(lpDeviceName: LPCWSTR, lpTargetPath: LPWSTR, ucchMax: DWORD) -> DWORD; + pub fn QueryFullProcessImageNameA( + hProcess: HANDLE, dwFlags: DWORD, lpExeName: LPSTR, lpdwSize: PDWORD, + ) -> BOOL; + pub fn QueryFullProcessImageNameW( + hProcess: HANDLE, dwFlags: DWORD, lpExeName: LPWSTR, lpdwSize: PDWORD, + ) -> BOOL; + pub fn QueryIdleProcessorCycleTime( + BufferLength: PULONG, ProcessorIdleCycleTime: PULONG64, + ) -> BOOL; + pub fn QueryIdleProcessorCycleTimeEx( + Group: USHORT, BufferLength: PULONG, ProcessorIdleCycleTime: PULONG64, + ) -> BOOL; + pub fn QueryInformationJobObject( + hJob: HANDLE, JobObjectInformationClass: JOBOBJECTINFOCLASS, + lpJobObjectInformation: LPVOID, cbJobObjectInformationLength: DWORD, + lpReturnLength: LPDWORD, + ) -> BOOL; + pub fn QueryMemoryResourceNotification( + ResourceNotificationHandle: HANDLE, ResourceState: PBOOL, + ) -> BOOL; + pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL; + pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL; + pub fn QueryProcessAffinityUpdateMode(hProcess: HANDLE, lpdwFlags: LPDWORD) -> BOOL; + pub fn QueryProcessCycleTime(ProcessHandle: HANDLE, CycleTime: PULONG64) -> BOOL; + pub fn QueryProtectedPolicy(PolicyGuid: LPCGUID, PolicyValue: PULONG_PTR) -> BOOL; + pub fn QueryThreadCycleTime(ThreadHandle: HANDLE, CycleTime: PULONG64) -> BOOL; + pub fn QueryThreadProfiling(ThreadHandle: HANDLE, Enabled: PBOOLEAN) -> DWORD; + pub fn QueryThreadpoolStackInformation( + ptpp: PTP_POOL, ptpsi: PTP_POOL_STACK_INFORMATION, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn QueryUmsThreadInformation( + UmsThread: PUMS_CONTEXT, UmsThreadInfoClass: UMS_THREAD_INFO_CLASS, + UmsThreadInformation: PVOID, UmsThreadInformationLength: ULONG, ReturnLength: PULONG, + ) -> BOOL; + pub fn QueryUnbiasedInterruptTime(UnbiasedTime: PULONGLONG) -> BOOL; + pub fn QueueUserAPC(pfnAPC: PAPCFUNC, hThread: HANDLE, dwData: ULONG_PTR) -> DWORD; + pub fn QueueUserWorkItem( + Function: LPTHREAD_START_ROUTINE, Context: PVOID, Flags: ULONG, + ) -> BOOL; + pub fn RaiseException( + dwExceptionCode: DWORD, dwExceptionFlags: DWORD, nNumberOfArguments: DWORD, + lpArguments: *const ULONG_PTR, + ); + pub fn RaiseFailFastException( + pExceptionRecord: PEXCEPTION_RECORD, pContextRecord: PCONTEXT, dwFlags: DWORD, + ); + pub fn ReOpenFile( + hOriginalFile: HANDLE, dwDesiredAccess: DWORD, dwShareMode: DWORD, dwFlags: DWORD, + ) -> HANDLE; + pub fn ReadConsoleA( + hConsoleInput: HANDLE, lpBuffer: LPVOID, nNumberOfCharsToRead: DWORD, + lpNumberOfCharsRead: LPDWORD, pInputControl: PCONSOLE_READCONSOLE_CONTROL, + ) -> BOOL; + pub fn ReadConsoleInputA( + hConsoleInput: HANDLE, lpBuffer: PINPUT_RECORD, nLength: DWORD, + lpNumberOfEventsRead: LPDWORD, + ) -> BOOL; + pub fn ReadConsoleInputW( + hConsoleInput: HANDLE, lpBuffer: PINPUT_RECORD, nLength: DWORD, + lpNumberOfEventsRead: LPDWORD, + ) -> BOOL; + pub fn ReadConsoleOutputA( + hConsoleOutput: HANDLE, lpBuffer: PCHAR_INFO, dwBufferSize: COORD, dwBufferCoord: COORD, + lpReadRegion: PSMALL_RECT, + ) -> BOOL; + pub fn ReadConsoleOutputAttribute( + hConsoleOutput: HANDLE, lpAttribute: LPWORD, nLength: DWORD, dwReadCoord: COORD, + lpNumberOfAttrsRead: LPDWORD, + ) -> BOOL; + pub fn ReadConsoleOutputCharacterA( + hConsoleOutput: HANDLE, lpCharacter: LPSTR, nLength: DWORD, dwReadCoord: COORD, + lpNumberOfCharsRead: LPDWORD, + ) -> BOOL; + pub fn ReadConsoleOutputCharacterW( + hConsoleOutput: HANDLE, lpCharacter: LPWSTR, nLength: DWORD, dwReadCoord: COORD, + lpNumberOfCharsRead: LPDWORD, + ) -> BOOL; + pub fn ReadConsoleOutputW( + hConsoleOutput: HANDLE, lpBuffer: PCHAR_INFO, dwBufferSize: COORD, dwBufferCoord: COORD, + lpReadRegion: PSMALL_RECT, + ) -> BOOL; + pub fn ReadConsoleW( + hConsoleInput: HANDLE, lpBuffer: LPVOID, nNumberOfCharsToRead: DWORD, + lpNumberOfCharsRead: LPDWORD, pInputControl: PCONSOLE_READCONSOLE_CONTROL, + ) -> BOOL; + pub fn ReadDirectoryChangesW( + hDirectory: HANDLE, lpBuffer: LPVOID, nBufferLength: DWORD, bWatchSubtree: BOOL, + dwNotifyFilter: DWORD, lpBytesReturned: LPDWORD, lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; + pub fn ReadFile( + hFile: HANDLE, lpBuffer: LPVOID, nNumberOfBytesToRead: DWORD, lpNumberOfBytesRead: LPDWORD, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn ReadFileEx( + hFile: HANDLE, lpBuffer: LPVOID, nNumberOfBytesToRead: DWORD, lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; + pub fn ReadFileScatter( + hFile: HANDLE, aSegmentArray: *mut FILE_SEGMENT_ELEMENT, nNumberOfBytesToRead: DWORD, + lpReserved: LPDWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn ReadProcessMemory( + hProcess: HANDLE, lpBaseAddress: LPCVOID, lpBuffer: LPVOID, nSize: SIZE_T, + lpNumberOfBytesRead: *mut SIZE_T, + ) -> BOOL; + pub fn ReadThreadProfilingData( + PerformanceDataHandle: HANDLE, Flags: DWORD, PerformanceData: PPERFORMANCE_DATA, + ) -> DWORD; + pub fn RegisterApplicationRecoveryCallback( + pRecoveyCallback: APPLICATION_RECOVERY_CALLBACK, pvParameter: PVOID, dwPingInterval: DWORD, + dwFlags: DWORD, + ) -> HRESULT; + pub fn RegisterApplicationRestart(pwzCommandline: PCWSTR, dwFlags: DWORD) -> HRESULT; + pub fn RegisterBadMemoryNotification(Callback: PBAD_MEMORY_CALLBACK_ROUTINE) -> PVOID; + // pub fn RegisterWaitForInputIdle(); + pub fn RegisterWaitForSingleObject( + phNewWaitObject: PHANDLE, hObject: HANDLE, Callback: WAITORTIMERCALLBACK, Context: PVOID, + dwMilliseconds: ULONG, dwFlags: ULONG, + ) -> BOOL; + pub fn RegisterWaitForSingleObjectEx( + hObject: HANDLE, Callback: WAITORTIMERCALLBACK, Context: PVOID, dwMilliseconds: ULONG, + dwFlags: ULONG, + ) -> HANDLE; + // pub fn RegisterWaitUntilOOBECompleted(); + pub fn ReleaseActCtx(hActCtx: HANDLE); + pub fn ReleaseMutex(hMutex: HANDLE) -> BOOL; + pub fn ReleaseMutexWhenCallbackReturns(pci: PTP_CALLBACK_INSTANCE, mutex: HANDLE); + pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK); + pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK); + pub fn ReleaseSemaphore( + hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LPLONG, + ) -> BOOL; + pub fn ReleaseSemaphoreWhenCallbackReturns( + pci: PTP_CALLBACK_INSTANCE, sem: HANDLE, crel: DWORD, + ); + pub fn RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL; + pub fn RemoveDirectoryTransactedA(lpPathName: LPCSTR, hTransaction: HANDLE) -> BOOL; + pub fn RemoveDirectoryTransactedW(lpPathName: LPCWSTR, hTransaction: HANDLE) -> BOOL; + pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; + pub fn RemoveDllDirectory(Cookie: DLL_DIRECTORY_COOKIE) -> BOOL; + // pub fn RemoveLocalAlternateComputerNameA(); + // pub fn RemoveLocalAlternateComputerNameW(); + pub fn RemoveSecureMemoryCacheCallback(pfnCallBack: PSECURE_MEMORY_CACHE_CALLBACK) -> BOOL; + pub fn RemoveVectoredContinueHandler(Handle: PVOID) -> ULONG; + pub fn RemoveVectoredExceptionHandler(Handle: PVOID) -> ULONG; + pub fn ReplaceFileA( + lpReplacedFileName: LPCSTR, lpReplacementFileName: LPCSTR, lpBackupFileName: LPCSTR, + dwReplaceFlags: DWORD, lpExclude: LPVOID, lpReserved: LPVOID, + ); + pub fn ReplaceFileW( + lpReplacedFileName: LPCWSTR, lpReplacementFileName: LPCWSTR, lpBackupFileName: LPCWSTR, + dwReplaceFlags: DWORD, lpExclude: LPVOID, lpReserved: LPVOID, + ); + pub fn ReplacePartitionUnit( + TargetPartition: PWSTR, SparePartition: PWSTR, Flags: ULONG, + ) -> BOOL; + pub fn RequestDeviceWakeup(hDevice: HANDLE) -> BOOL; + pub fn RequestWakeupLatency(latency: LATENCY_TIME) -> BOOL; + pub fn ResetEvent(hEvent: HANDLE) -> BOOL; + pub fn ResetWriteWatch(lpBaseAddress: LPVOID, dwRegionSize: SIZE_T) -> UINT; + // pub fn ResolveDelayLoadedAPI(); + // pub fn ResolveDelayLoadsFromDll(); + pub fn ResolveLocaleName( + lpNameToResolve: LPCWSTR, lpLocaleName: LPWSTR, cchLocaleName: c_int, + ) -> c_int; + pub fn RestoreLastError(dwErrCode: DWORD); + pub fn ResumeThread(hThread: HANDLE) -> DWORD; + #[cfg(target_arch = "arm")] + pub fn RtlAddFunctionTable( + FunctionTable: PRUNTIME_FUNCTION, EntryCount: DWORD, BaseAddress: DWORD, + ) -> BOOLEAN; + #[cfg(target_arch = "x86_64")] + pub fn RtlAddFunctionTable( + FunctionTable: PRUNTIME_FUNCTION, EntryCount: DWORD, BaseAddress: DWORD64, + ) -> BOOLEAN; + pub fn RtlCaptureContext(ContextRecord: PCONTEXT); + pub fn RtlCaptureStackBackTrace( + FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: *mut PVOID, BackTraceHash: PDWORD, + ) -> WORD; + // #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlCompareMemory(Source1: *const VOID, Source2: *const VOID, Length: SIZE_T) -> SIZE_T; + // #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlCopyMemory(Destination: PVOID, Source: *const VOID, Length: SIZE_T); + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlDeleteFunctionTable(FunctionTable: PRUNTIME_FUNCTION) -> BOOLEAN; + // pub fn RtlFillMemory(); + #[cfg(target_arch = "arm")] + pub fn RtlInstallFunctionTableCallback( + TableIdentifier: DWORD, BaseAddress: DWORD, Length: DWORD, + Callback: PGET_RUNTIME_FUNCTION_CALLBACK, Context: PVOID, OutOfProcessCallbackDll: PCWSTR, + ) -> BOOLEAN; + #[cfg(target_arch = "x86_64")] + pub fn RtlInstallFunctionTableCallback( + TableIdentifier: DWORD64, BaseAddress: DWORD64, Length: DWORD, + Callback: PGET_RUNTIME_FUNCTION_CALLBACK, Context: PVOID, OutOfProcessCallbackDll: PCWSTR, + ) -> BOOLEAN; + #[cfg(target_arch = "arm")] + pub fn RtlLookupFunctionEntry( + ControlPc: ULONG_PTR, ImageBase: PDWORD, HistoryTable: PUNWIND_HISTORY_TABLE, + ) -> PRUNTIME_FUNCTION; + #[cfg(target_arch = "x86_64")] + pub fn RtlLookupFunctionEntry( + ControlPc: DWORD64, ImageBase: PDWORD64, HistoryTable: PUNWIND_HISTORY_TABLE, + ) -> PRUNTIME_FUNCTION; + // pub fn RtlMoveMemory(); + // #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlPcToFileHeader(PcValue: PVOID, BaseOfImage: *mut PVOID) -> PVOID; + // #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + // pub fn RtlRaiseException(); + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlRestoreContext(ContextRecord: PCONTEXT, ExceptionRecord: *mut EXCEPTION_RECORD); + pub fn RtlUnwind( + TargetFrame: PVOID, TargetIp: PVOID, ExceptionRecord: PEXCEPTION_RECORD, ReturnValue: PVOID, + ); + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn RtlUnwindEx( + TargetFrame: PVOID, TargetIp: PVOID, ExceptionRecord: PEXCEPTION_RECORD, ReturnValue: PVOID, + ContextRecord: PCONTEXT, HistoryTable: PUNWIND_HISTORY_TABLE, + ); + #[cfg(target_arch = "arm")] + pub fn RtlVirtualUnwind( + HandlerType: DWORD, ImageBase: DWORD, ControlPc: DWORD, FunctionEntry: PRUNTIME_FUNCTION, + ContextRecord: PCONTEXT, HandlerData: *mut PVOID, EstablisherFrame: PDWORD, + ContextPointers: PKNONVOLATILE_CONTEXT_POINTERS, + ) -> PEXCEPTION_ROUTINE; + #[cfg(target_arch = "x86_64")] + pub fn RtlVirtualUnwind( + HandlerType: DWORD, ImageBase: DWORD64, ControlPc: DWORD64, + FunctionEntry: PRUNTIME_FUNCTION, ContextRecord: PCONTEXT, HandlerData: *mut PVOID, + EstablisherFrame: PDWORD64, ContextPointers: PKNONVOLATILE_CONTEXT_POINTERS, + ) -> PEXCEPTION_ROUTINE; + // pub fn RtlZeroMemory(); + pub fn ScrollConsoleScreenBufferA( + hConsoleOutput: HANDLE, lpScrollRectangle: *const SMALL_RECT, + lpClipRectangle: *const SMALL_RECT, dwDestinationOrigin: COORD, lpFill: *const CHAR_INFO, + ) -> BOOL; + pub fn ScrollConsoleScreenBufferW( + hConsoleOutput: HANDLE, lpScrollRectangle: *const SMALL_RECT, + lpClipRectangle: *const SMALL_RECT, dwDestinationOrigin: COORD, lpFill: *const CHAR_INFO, + ) -> BOOL; + pub fn SearchPathA( + lpPath: LPCSTR, lpFileName: LPCSTR, lpExtension: LPCSTR, nBufferLength: DWORD, + lpBuffer: LPSTR, lpFilePart: *mut LPSTR, + ) -> DWORD; + pub fn SearchPathW( + lpPath: LPCWSTR, lpFileName: LPCWSTR, lpExtension: LPCWSTR, nBufferLength: DWORD, + lpBuffer: LPWSTR, lpFilePart: *mut LPWSTR, + ) -> DWORD; + pub fn SetCachedSigningLevel( + SourceFiles: PHANDLE, SourceFileCount: ULONG, Flags: ULONG, TargetFile: HANDLE, + ) -> BOOL; + pub fn SetCalendarInfoA( + Locale: LCID, Calendar: CALID, CalType: CALTYPE, lpCalData: LPCSTR, + ) -> BOOL; + pub fn SetCalendarInfoW( + Locale: LCID, Calendar: CALID, CalType: CALTYPE, lpCalData: LPCWSTR, + ) -> BOOL; + pub fn SetCommBreak(hFile: HANDLE) -> BOOL; + pub fn SetCommConfig(hCommDev: HANDLE, lpCC: LPCOMMCONFIG, dwSize: DWORD) -> BOOL; + pub fn SetCommMask(hFile: HANDLE, dwEvtMask: DWORD) -> BOOL; + pub fn SetCommState(hFile: HANDLE, lpDCB: LPDCB) -> BOOL; + pub fn SetCommTimeouts(hFile: HANDLE, lpCommTimeouts: LPCOMMTIMEOUTS) -> BOOL; + pub fn SetComputerNameA(lpComputerName: LPCSTR) -> BOOL; + pub fn SetComputerNameEx2W( + NameType: COMPUTER_NAME_FORMAT, Flags: DWORD, lpBuffer: LPCWSTR, + ) -> BOOL; + pub fn SetComputerNameExA(NameType: COMPUTER_NAME_FORMAT, lpBuffer: LPCSTR) -> BOOL; + pub fn SetComputerNameExW(NameType: COMPUTER_NAME_FORMAT, lpBuffer: LPCWSTR) -> BOOL; + pub fn SetComputerNameW(lpComputerName: LPCWSTR) -> BOOL; + pub fn SetConsoleActiveScreenBuffer(hConsoleOutput: HANDLE) -> BOOL; + pub fn SetConsoleCP(wCodePageID: UINT) -> BOOL; + pub fn SetConsoleCtrlHandler(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL; + // pub fn SetConsoleCursor(); + pub fn SetConsoleCursorInfo( + hConsoleOutput: HANDLE, lpConsoleCursorInfo: *const CONSOLE_CURSOR_INFO, + ) -> BOOL; + pub fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL; + pub fn SetConsoleDisplayMode( + hConsoleOutput: HANDLE, dwFlags: DWORD, lpNewScreenBufferDimensions: PCOORD, + ) -> BOOL; + pub fn SetConsoleHistoryInfo(lpConsoleHistoryInfo: PCONSOLE_HISTORY_INFO) -> BOOL; + pub fn SetConsoleMode(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL; + pub fn SetConsoleOutputCP(wCodePageID: UINT) -> BOOL; + pub fn SetConsoleScreenBufferInfoEx( + hConsoleOutput: HANDLE, lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX, + ) -> BOOL; + pub fn SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL; + pub fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL; + pub fn SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL; + pub fn SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL; + pub fn SetConsoleWindowInfo( + hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: *const SMALL_RECT, + ) -> BOOL; + pub fn SetCriticalSectionSpinCount( + lpCriticalSection: LPCRITICAL_SECTION, dwSpinCount: DWORD, + ) -> DWORD; + pub fn SetCurrentConsoleFontEx( + hConsoleOutput: HANDLE, bMaximumWindow: BOOL, lpConsoleCurrentFontEx: PCONSOLE_FONT_INFOEX, + ) -> BOOL; + pub fn SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL; + pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; + pub fn SetDefaultCommConfigA(lpszName: LPCSTR, lpCC: LPCOMMCONFIG, dwSize: DWORD) -> BOOL; + pub fn SetDefaultCommConfigW(lpszName: LPCWSTR, lpCC: LPCOMMCONFIG, dwSize: DWORD) -> BOOL; + pub fn SetDefaultDllDirectories(DirectoryFlags: DWORD) -> BOOL; + pub fn SetDllDirectoryA(lpPathName: LPCSTR) -> BOOL; + pub fn SetDllDirectoryW(lpPathName: LPCWSTR) -> BOOL; + pub fn SetDynamicTimeZoneInformation( + lpTimeZoneInformation: *const DYNAMIC_TIME_ZONE_INFORMATION, + ) -> BOOL; + pub fn SetEndOfFile(hFile: HANDLE) -> BOOL; + pub fn SetEnvironmentStringsA(NewEnvironment: LPCH) -> BOOL; + pub fn SetEnvironmentStringsW(NewEnvironment: LPWCH) -> BOOL; + pub fn SetEnvironmentVariableA(lpName: LPCSTR, lpValue: LPCSTR) -> BOOL; + pub fn SetEnvironmentVariableW(lpName: LPCWSTR, lpValue: LPCWSTR) -> BOOL; + pub fn SetErrorMode(uMode: UINT) -> UINT; + pub fn SetEvent(hEvent: HANDLE) -> BOOL; + pub fn SetEventWhenCallbackReturns(pci: PTP_CALLBACK_INSTANCE, evt: HANDLE); + pub fn SetFileApisToANSI(); + pub fn SetFileApisToOEM(); + pub fn SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: DWORD) -> BOOL; + pub fn SetFileAttributesTransactedA( + lpFileName: LPCSTR, dwFileAttributes: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn SetFileAttributesTransactedW( + lpFileName: LPCWSTR, dwFileAttributes: DWORD, hTransaction: HANDLE, + ) -> BOOL; + pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; + pub fn SetFileBandwidthReservation( + hFile: HANDLE, nPeriodMilliseconds: DWORD, nBytesPerPeriod: DWORD, bDiscardable: BOOL, + lpTransferSize: LPDWORD, lpNumOutstandingRequests: LPDWORD, + ) -> BOOL; + pub fn SetFileCompletionNotificationModes(FileHandle: HANDLE, Flags: UCHAR) -> BOOL; + pub fn SetFileInformationByHandle( + hFile: HANDLE, FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, lpFileInformation: LPVOID, + dwBufferSize: DWORD, + ) -> BOOL; + pub fn SetFileIoOverlappedRange( + FileHandle: HANDLE, OverlappedRangeStart: PUCHAR, Length: ULONG, + ) -> BOOL; + pub fn SetFilePointer( + hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: PLONG, dwMoveMethod: DWORD, + ) -> DWORD; + pub fn SetFilePointerEx( + hFile: HANDLE, liDistanceToMove: LARGE_INTEGER, lpNewFilePointer: PLARGE_INTEGER, + dwMoveMethod: DWORD, + ) -> BOOL; + pub fn SetFileShortNameA(hFile: HANDLE, lpShortName: LPCSTR) -> BOOL; + pub fn SetFileShortNameW(hFile: HANDLE, lpShortName: LPCWSTR) -> BOOL; + pub fn SetFileTime( + hFile: HANDLE, lpCreationTime: *const FILETIME, lpLastAccessTime: *const FILETIME, + lpLastWriteTime: *const FILETIME, + ) -> BOOL; + pub fn SetFileValidData(hFile: HANDLE, ValidDataLength: LONGLONG) -> BOOL; + pub fn SetFirmwareEnvironmentVariableA( + lpName: LPCSTR, lpGuid: LPCSTR, pValue: PVOID, nSize: DWORD, + ) -> BOOL; + pub fn SetFirmwareEnvironmentVariableExA( + lpName: LPCSTR, lpGuid: LPCSTR, pValue: PVOID, nSize: DWORD, dwAttributes: DWORD, + ) -> BOOL; + pub fn SetFirmwareEnvironmentVariableExW( + lpName: LPCWSTR, lpGuid: LPCWSTR, pValue: PVOID, nSize: DWORD, dwAttributes: DWORD, + ) -> BOOL; + pub fn SetFirmwareEnvironmentVariableW( + lpName: LPCWSTR, lpGuid: LPCWSTR, pValue: PVOID, nSize: DWORD, + ) -> BOOL; + pub fn SetHandleCount(uNumber: UINT) -> UINT; + pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; + pub fn SetInformationJobObject( + hJob: HANDLE, JobObjectInformationClass: JOBOBJECTINFOCLASS, + lpJobObjectInformation: LPVOID, cbJobObjectInformationLength: DWORD, + ) -> BOOL; + pub fn SetLastError(dwErrCode: DWORD); + // pub fn SetLocalPrimaryComputerNameA(); + // pub fn SetLocalPrimaryComputerNameW(); + pub fn SetLocalTime(lpSystemTime: *const SYSTEMTIME) -> BOOL; + pub fn SetLocaleInfoA(Locale: LCID, LCType: LCTYPE, lpLCData: LPCSTR) -> BOOL; + pub fn SetLocaleInfoW(Locale: LCID, LCType: LCTYPE, lpLCData: LPCWSTR) -> BOOL; + pub fn SetMailslotInfo(hMailslot: HANDLE, lReadTimeout: DWORD) -> BOOL; + pub fn SetMessageWaitingIndicator(hMsgIndicator: HANDLE, ulMsgCount: ULONG) -> BOOL; + pub fn SetNamedPipeAttribute( + Pipe: HANDLE, AttributeType: PIPE_ATTRIBUTE_TYPE, AttributeName: PSTR, + AttributeValue: PVOID, AttributeValueLength: SIZE_T, + ) -> BOOL; + pub fn SetNamedPipeHandleState( + hNamedPipe: HANDLE, lpMode: LPDWORD, lpMaxCollectionCount: LPDWORD, + lpCollectDataTimeout: LPDWORD, + ) -> BOOL; + pub fn SetPriorityClass(hProcess: HANDLE, dwPriorityClass: DWORD) -> BOOL; + pub fn SetProcessAffinityMask(hProcess: HANDLE, dwProcessAffinityMask: DWORD) -> BOOL; + pub fn SetProcessAffinityUpdateMode(hProcess: HANDLE, dwFlags: DWORD) -> BOOL; + pub fn SetProcessDEPPolicy(dwFlags: DWORD) -> BOOL; + pub fn SetProcessInformation( + hProcess: HANDLE, ProcessInformationClass: PROCESS_INFORMATION_CLASS, + ProcessInformation: LPVOID, ProcessInformationSize: DWORD, + ) -> BOOL; + pub fn SetProcessMitigationPolicy( + MitigationPolicy: PROCESS_MITIGATION_POLICY, lpBuffer: PVOID, dwLength: SIZE_T, + ) -> BOOL; + pub fn SetProcessPreferredUILanguages( + dwFlags: DWORD, pwszLanguagesBuffer: PCZZWSTR, pulNumLanguages: PULONG, + ) -> BOOL; + pub fn SetProcessPriorityBoost(hProcess: HANDLE, bDisablePriorityBoost: BOOL) -> BOOL; + pub fn SetProcessShutdownParameters(dwLevel: DWORD, dwFlags: DWORD) -> BOOL; + pub fn SetProcessWorkingSetSize( + hProcess: HANDLE, dwMinimumWorkingSetSize: SIZE_T, dwMaximumWorkingSetSize: SIZE_T, + ) -> BOOL; + pub fn SetProcessWorkingSetSizeEx( + hProcess: HANDLE, dwMinimumWorkingSetSize: SIZE_T, dwMaximumWorkingSetSize: SIZE_T, + Flags: DWORD, + ) -> BOOL; + pub fn SetProtectedPolicy( + PolicyGuid: LPCGUID, PolicyValue: ULONG_PTR, OldPolicyValue: PULONG_PTR, + ) -> BOOL; + pub fn SetSearchPathMode(Flags: DWORD) -> BOOL; + pub fn SetStdHandle(nStdHandle: DWORD, hHandle: HANDLE) -> BOOL; + pub fn SetStdHandleEx(nStdHandle: DWORD, hHandle: HANDLE, phPrevValue: PHANDLE) -> BOOL; + pub fn SetSystemFileCacheSize( + MinimumFileCacheSize: SIZE_T, MaximumFileCacheSize: SIZE_T, Flags: DWORD, + ) -> BOOL; + pub fn SetSystemPowerState(fSuspend: BOOL, fForce: BOOL) -> BOOL; + pub fn SetSystemTime(lpSystemTime: *const SYSTEMTIME) -> BOOL; + pub fn SetSystemTimeAdjustment(dwTimeAdjustment: DWORD, bTimeAdjustmentDisabled: BOOL) -> BOOL; + pub fn SetTapeParameters( + hDevice: HANDLE, dwOperation: DWORD, lpTapeInformation: LPVOID, + ) -> DWORD; + pub fn SetTapePosition( + hDevice: HANDLE, dwPositionMethod: DWORD, dwPartition: DWORD, + dwOffsetLow: DWORD, dwOffsetHigh: DWORD, bImmediate: BOOL + ) -> DWORD; + pub fn SetThreadAffinityMask(hThread: HANDLE, dwThreadAffinityMask: DWORD_PTR) -> DWORD_PTR; + pub fn SetThreadContext(hThread: HANDLE, lpContext: *const CONTEXT) -> BOOL; + pub fn SetThreadErrorMode(dwNewMode: DWORD, lpOldMode: LPDWORD) -> BOOL; + pub fn SetThreadExecutionState(esFlags: EXECUTION_STATE) -> EXECUTION_STATE; + pub fn SetThreadGroupAffinity( + hThread: HANDLE, GroupAffinity: *const GROUP_AFFINITY, + PreviousGroupAffinity: PGROUP_AFFINITY, + ) -> BOOL; + pub fn SetThreadIdealProcessor(hThread: HANDLE, dwIdealProcessor: DWORD) -> DWORD; + pub fn SetThreadIdealProcessorEx( + hThread: HANDLE, lpIdealProcessor: PPROCESSOR_NUMBER, + lpPreviousIdealProcessor: PPROCESSOR_NUMBER, + ) -> BOOL; + pub fn SetThreadInformation( + hThread: HANDLE, ThreadInformationClass: THREAD_INFORMATION_CLASS, + ThreadInformation: LPVOID, ThreadInformationSize: DWORD, + ); + pub fn SetThreadLocale(Locale: LCID) -> BOOL; + pub fn SetThreadPreferredUILanguages( + dwFlags: DWORD, pwszLanguagesBuffer: PCZZWSTR, pulNumLanguages: PULONG, + ) -> BOOL; + pub fn SetThreadPriority(hThread: HANDLE, nPriority: c_int) -> BOOL; + pub fn SetThreadPriorityBoost(hThread: HANDLE, bDisablePriorityBoost: BOOL) -> BOOL; + pub fn SetThreadStackGuarantee(StackSizeInBytes: PULONG) -> BOOL; + pub fn SetThreadUILanguage(LangId: LANGID) -> LANGID; + pub fn SetThreadpoolStackInformation( + ptpp: PTP_POOL, ptpsi: PTP_POOL_STACK_INFORMATION, + ) -> BOOL; + pub fn SetThreadpoolThreadMaximum(ptpp: PTP_POOL, cthrdMost: DWORD); + pub fn SetThreadpoolThreadMinimum(ptpp: PTP_POOL, cthrdMic: DWORD) -> BOOL; + pub fn SetThreadpoolTimer( + pti: PTP_TIMER, pftDueTime: PFILETIME, msPeriod: DWORD, msWindowLength: DWORD, + ); + pub fn SetThreadpoolTimerEx( + pti: PTP_TIMER, pftDueTime: PFILETIME, msPeriod: DWORD, msWindowLength: DWORD, + ) -> BOOL; + pub fn SetThreadpoolWait(pwa: PTP_WAIT, h: HANDLE, pftTimeout: PFILETIME); + pub fn SetThreadpoolWaitEx( + pwa: PTP_WAIT, h: HANDLE, pftTimeout: PFILETIME, Reserved: PVOID, + ) -> BOOL; + pub fn SetTimeZoneInformation(lpTimeZoneInformation: *const TIME_ZONE_INFORMATION) -> BOOL; + pub fn SetTimerQueueTimer( + TimerQueue: HANDLE, Callback: WAITORTIMERCALLBACK, Parameter: PVOID, DueTime: DWORD, + Period: DWORD, PreferIo: BOOL, + ) -> HANDLE; + #[cfg(target_arch = "x86_64")] + pub fn SetUmsThreadInformation( + UmsThread: PUMS_CONTEXT, UmsThreadInfoClass: UMS_THREAD_INFO_CLASS, + UmsThreadInformation: PVOID, UmsThreadInformationLength: ULONG, + ) -> BOOL; + pub fn SetUnhandledExceptionFilter( + lpTopLevelExceptionFilter: LPTOP_LEVEL_EXCEPTION_FILTER, + ) -> LPTOP_LEVEL_EXCEPTION_FILTER; + pub fn SetUserGeoID(GeoId: GEOID) -> BOOL; + pub fn SetVolumeLabelA(lpRootPathName: LPCSTR, lpVolumeName: LPCSTR) -> BOOL; + pub fn SetVolumeLabelW(lpRootPathName: LPCWSTR, lpVolumeName: LPCWSTR) -> BOOL; + pub fn SetVolumeMountPointA(lpszVolumeMountPoint: LPCSTR, lpszVolumeName: LPCSTR) -> BOOL; + pub fn SetVolumeMountPointW(lpszVolumeMountPoint: LPCWSTR, lpszVolumeName: LPCWSTR) -> BOOL; + pub fn SetWaitableTimer( + hTimer: HANDLE, lpDueTime: *const LARGE_INTEGER, lPeriod: LONG, + pfnCompletionRoutine: PTIMERAPCROUTINE, lpArgToCompletionRoutine: LPVOID, fResume: BOOL, + ) -> BOOL; + pub fn SetWaitableTimerEx( + hTimer: HANDLE, lpDueTime: *const LARGE_INTEGER, lPeriod: LONG, + pfnCompletionRoutine: PTIMERAPCROUTINE, lpArgToCompletionRoutine: LPVOID, + WakeContext: PREASON_CONTEXT, TolerableDelay: ULONG, + ) -> BOOL; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn SetXStateFeaturesMask(Context: PCONTEXT, FeatureMask: DWORD64) -> BOOL; + pub fn SetupComm(hFile: HANDLE, dwInQueue: DWORD, dwOutQueue: DWORD) -> BOOL; + pub fn SignalObjectAndWait( + hObjectToSignal: HANDLE, hObjectToWaitOn: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL, + ) -> DWORD; + pub fn SizeofResource(hModule: HMODULE, hResInfo: HRSRC) -> DWORD; + pub fn Sleep(dwMilliseconds: DWORD); + pub fn SleepConditionVariableCS( + ConditionVariable: PCONDITION_VARIABLE, CriticalSection: PCRITICAL_SECTION, + dwMilliseconds: DWORD, + ) -> BOOL; + pub fn SleepConditionVariableSRW( + ConditionVariable: PCONDITION_VARIABLE, SRWLock: PSRWLOCK, dwMilliseconds: DWORD, + Flags: ULONG, + ) -> BOOL; + pub fn SleepEx(dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD; + pub fn StartThreadpoolIo(pio: PTP_IO); + pub fn SubmitThreadpoolWork(pwk: PTP_WORK); + pub fn SuspendThread(hThread: HANDLE) -> DWORD; + pub fn SwitchToFiber(lpFiber: LPVOID); + pub fn SwitchToThread() -> BOOL; + pub fn SystemTimeToFileTime(lpSystemTime: *const SYSTEMTIME, lpFileTime: LPFILETIME) -> BOOL; + pub fn SystemTimeToTzSpecificLocalTime( + lpTimeZoneInformation: *const TIME_ZONE_INFORMATION, lpUniversalTime: *const SYSTEMTIME, + lpLocalTime: LPSYSTEMTIME, + ) -> BOOL; + pub fn SystemTimeToTzSpecificLocalTimeEx( + lpTimeZoneInformation: *const DYNAMIC_TIME_ZONE_INFORMATION, + lpUniversalTime: *const SYSTEMTIME, lpLocalTime: LPSYSTEMTIME, + ) -> BOOL; + pub fn TerminateJobObject(hJob: HANDLE, uExitCode: UINT) -> BOOL; + pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL; + pub fn TerminateThread(hThread: HANDLE, dwExitCode: DWORD) -> BOOL; + pub fn Thread32First(hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL; + pub fn Thread32Next(hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL; + pub fn TlsAlloc() -> DWORD; + pub fn TlsFree(dwTlsIndex: DWORD) -> BOOL; + pub fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID; + pub fn TlsSetValue(dwTlsIndex: DWORD, lpTlsValue: LPVOID) -> BOOL; + pub fn Toolhelp32ReadProcessMemory(th32ProcessID: DWORD, lpBaseAddress: LPCVOID, + lpBuffer: LPVOID, cbRead: SIZE_T, lpNumberOfBytesRead: *mut SIZE_T + ) -> BOOL; + pub fn TransactNamedPipe( + hNamedPipe: HANDLE, lpInBuffer: LPVOID, nInBufferSize: DWORD, lpOutBuffer: LPVOID, + nOutBufferSize: DWORD, lpBytesRead: LPDWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn TransmitCommChar(hFile: HANDLE, cChar: c_char) -> BOOL; + pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN; + pub fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL; + pub fn TrySubmitThreadpoolCallback( + pfns: PTP_SIMPLE_CALLBACK, pv: PVOID, pcbe: PTP_CALLBACK_ENVIRON, + ) -> BOOL; + pub fn TzSpecificLocalTimeToSystemTime( + lpTimeZoneInformation: *const TIME_ZONE_INFORMATION, lpLocalTime: *const SYSTEMTIME, + lpUniversalTime: LPSYSTEMTIME, + ) -> BOOL; + pub fn TzSpecificLocalTimeToSystemTimeEx( + lpTimeZoneInformation: *const DYNAMIC_TIME_ZONE_INFORMATION, + lpLocalTime: *const SYSTEMTIME, lpUniversalTime: LPSYSTEMTIME, + ) -> BOOL; + #[cfg(target_arch = "x86_64")] + pub fn UmsThreadYield(SchedulerParam: PVOID) -> BOOL; + pub fn UnhandledExceptionFilter(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; + pub fn UnlockFile( + hFile: HANDLE, dwFileOffsetLow: DWORD, dwFileOffsetHigh: DWORD, + nNumberOfBytesToUnlockLow: DWORD, nNumberOfBytesToUnlockHigh: DWORD, + ) -> BOOL; + pub fn UnlockFileEx( + hFile: HANDLE, dwReserved: DWORD, nNumberOfBytesToUnlockLow: DWORD, + nNumberOfBytesToUnlockHigh: DWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL; + pub fn UnregisterApplicationRecoveryCallback() -> HRESULT; + pub fn UnregisterApplicationRestart() -> HRESULT; + pub fn UnregisterBadMemoryNotification(RegistrationHandle: PVOID) -> BOOL; + pub fn UnregisterWait(WaitHandle: HANDLE) -> BOOL; + pub fn UnregisterWaitEx(WaitHandle: HANDLE, CompletionEvent: HANDLE) -> BOOL; + // pub fn UnregisterWaitUntilOOBECompleted(); + pub fn UpdateProcThreadAttribute( + lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, dwFlags: DWORD, Attribute: DWORD_PTR, + lpValue: PVOID, cbSize: SIZE_T, lpPreviousValue: PVOID, lpReturnSize: PSIZE_T, + ) -> BOOL; + pub fn UpdateResourceA( + hUpdate: HANDLE, lpType: LPCSTR, lpName: LPCSTR, wLanguage: WORD, lpData: LPVOID, cb: DWORD, + ) -> BOOL; + pub fn UpdateResourceW( + hUpdate: HANDLE, lpType: LPCWSTR, lpName: LPCWSTR, wLanguage: WORD, lpData: LPVOID, + cb: DWORD, + ) -> BOOL; + pub fn VerLanguageNameA(wLang: DWORD, szLang: LPSTR, cchLang: DWORD) -> DWORD; + pub fn VerLanguageNameW(wLang: DWORD, szLang: LPWSTR, cchLang: DWORD) -> DWORD; + pub fn VerSetConditionMask( + ConditionMask: ULONGLONG, TypeMask: DWORD, Condition: BYTE, + ) -> ULONGLONG; + pub fn VerifyScripts( + dwFlags: DWORD, lpLocaleScripts: LPCWSTR, cchLocaleScripts: c_int, lpTestScripts: LPCWSTR, + cchTestScripts: c_int, + ) -> BOOL; + pub fn VerifyVersionInfoA( + lpVersionInformation: LPOSVERSIONINFOEXA, dwTypeMask: DWORD, dwlConditionMask: DWORDLONG, + ) -> BOOL; + pub fn VerifyVersionInfoW( + lpVersionInformation: LPOSVERSIONINFOEXW, dwTypeMask: DWORD, dwlConditionMask: DWORDLONG, + ) -> BOOL; + pub fn VirtualAlloc( + lpAddress: LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD, + ) -> LPVOID; + pub fn VirtualAllocEx( + hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, + flProtect: DWORD, + ) -> LPVOID; + pub fn VirtualAllocExNuma( + hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, + flProtect: DWORD, nndPreferred: DWORD, + ) -> LPVOID; + pub fn VirtualFree(lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) -> BOOL; + pub fn VirtualFreeEx( + hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD, + ) -> BOOL; + pub fn VirtualLock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL; + pub fn VirtualProtect( + lpAddress: LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: PDWORD, + ) -> BOOL; + pub fn VirtualProtectEx( + hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, + lpflOldProtect: DWORD, + ) -> BOOL; + pub fn VirtualQuery( + lpAddress: LPCVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T, + ) -> SIZE_T; + pub fn VirtualQueryEx( + hProcess: HANDLE, lpAddress: LPCVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T, + ) -> SIZE_T; + pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL; + pub fn WTSGetActiveConsoleSessionId() -> DWORD; + pub fn WaitCommEvent(hFile: HANDLE, lpEvtMask: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL; + pub fn WaitForDebugEvent(lpDebugEvent: LPDEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL; + pub fn WaitForMultipleObjects( + nCount: DWORD, lpHandles: *const HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD, + ) -> DWORD; + pub fn WaitForMultipleObjectsEx( + nCount: DWORD, lpHandles: *const HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD, + bAlertable: BOOL, + ) -> DWORD; + pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; + pub fn WaitForSingleObjectEx( + hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL, + ) -> DWORD; + pub fn WaitForThreadpoolIoCallbacks(pio: PTP_IO, fCancelPendingCallbacks: BOOL); + pub fn WaitForThreadpoolTimerCallbacks(pti: PTP_TIMER, fCancelPendingCallbacks: BOOL); + pub fn WaitForThreadpoolWaitCallbacks(pwa: PTP_WAIT, fCancelPendingCallbacks: BOOL); + pub fn WaitForThreadpoolWorkCallbacks(pwk: PTP_WORK, fCancelPendingCallbacks: BOOL); + pub fn WaitNamedPipeA(lpNamedPipeName: LPCSTR, nTimeOut: DWORD) -> BOOL; + pub fn WaitNamedPipeW(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL; + pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE); + pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE); + pub fn WerGetFlags(hProcess: HANDLE, pdwFlags: PDWORD) -> HRESULT; + pub fn WerRegisterFile( + pwzFile: PCWSTR, regFileType: WER_REGISTER_FILE_TYPE, dwFlags: DWORD, + ) -> HRESULT; + pub fn WerRegisterMemoryBlock(pvAddress: PVOID, dwSize: DWORD) -> HRESULT; + pub fn WerRegisterRuntimeExceptionModule( + pwszOutOfProcessCallbackDll: PCWSTR, pContext: PVOID, + ) -> HRESULT; + pub fn WerSetFlags(dwFlags: DWORD) -> HRESULT; + pub fn WerUnregisterFile(pwzFilePath: PCWSTR) -> HRESULT; + pub fn WerUnregisterMemoryBlock(pvAddress: PVOID) -> HRESULT; + pub fn WerUnregisterRuntimeExceptionModule( + pwszOutOfProcessCallbackDll: PCWSTR, pContext: PVOID, + ) -> HRESULT; + // pub fn WerpInitiateRemoteRecovery(); + pub fn WideCharToMultiByte( + CodePage: UINT, dwFlags: DWORD, lpWideCharStr: LPCWSTR, cchWideChar: c_int, + lpMultiByteStr: LPSTR, cbMultiByte: c_int, lpDefaultChar: LPCSTR, lpUsedDefaultChar: LPBOOL, + ) -> c_int; + pub fn WinExec(lpCmdLine: LPCSTR, uCmdShow: UINT) -> UINT; + pub fn Wow64DisableWow64FsRedirection(OldValue: *mut PVOID) -> BOOL; + pub fn Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: BOOLEAN) -> BOOLEAN; + pub fn Wow64GetThreadContext(hThread: HANDLE, lpContext: PWOW64_CONTEXT) -> BOOL; + pub fn Wow64GetThreadSelectorEntry( + hThread: HANDLE, dwSelector: DWORD, lpSelectorEntry: PWOW64_LDT_ENTRY, + ) -> BOOL; + pub fn Wow64RevertWow64FsRedirection(OlValue: PVOID) -> BOOL; + pub fn Wow64SetThreadContext(hThread: HANDLE, lpContext: *const WOW64_CONTEXT) -> BOOL; + pub fn Wow64SuspendThread(hThread: HANDLE) -> DWORD; + pub fn WriteConsoleA( + hConsoleOutput: HANDLE, lpBuffer: *const VOID, nNumberOfCharsToWrite: DWORD, + lpNumberOfCharsWritten: LPDWORD, lpReserved: LPVOID, + ) -> BOOL; + pub fn WriteConsoleInputA( + hConsoleInput: HANDLE, lpBuffer: *const INPUT_RECORD, nLength: DWORD, + lpNumberOfEventsWritten: LPDWORD, + ) -> BOOL; + pub fn WriteConsoleInputW( + hConsoleInput: HANDLE, lpBuffer: *const INPUT_RECORD, nLength: DWORD, + lpNumberOfEventsWritten: LPDWORD, + ) -> BOOL; + pub fn WriteConsoleOutputA( + hConsoleOutput: HANDLE, lpBuffer: *const CHAR_INFO, dwBufferSize: COORD, + dwBufferCoord: COORD, lpWriteRegion: PSMALL_RECT, + ) -> BOOL; + pub fn WriteConsoleOutputAttribute( + hConsoleOutput: HANDLE, lpAttribute: *const WORD, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfAttrsWritten: LPDWORD, + ) -> BOOL; + pub fn WriteConsoleOutputCharacterA( + hConsoleOutput: HANDLE, lpCharacter: LPCSTR, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfCharsWritten: LPDWORD, + ) -> BOOL; + pub fn WriteConsoleOutputCharacterW( + hConsoleOutput: HANDLE, lpCharacter: LPCWSTR, nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfCharsWritten: LPDWORD, + ) -> BOOL; + pub fn WriteConsoleOutputW( + hConsoleOutput: HANDLE, lpBuffer: *const CHAR_INFO, dwBufferSize: COORD, + dwBufferCoord: COORD, lpWriteRegion: PSMALL_RECT, + ) -> BOOL; + pub fn WriteConsoleW( + hConsoleOutput: HANDLE, lpBuffer: *const VOID, nNumberOfCharsToWrite: DWORD, + lpNumberOfCharsWritten: LPDWORD, lpReserved: LPVOID, + ) -> BOOL; + pub fn WriteFile( + hFile: HANDLE, lpBuffer: LPCVOID, nNumberOfBytesToWrite: DWORD, + lpNumberOfBytesWritten: LPDWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn WriteFileEx( + hFile: HANDLE, lpBuffer: LPCVOID, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; + pub fn WriteFileGather( + hFile: HANDLE, aSegmentArray: *mut FILE_SEGMENT_ELEMENT, nNumberOfBytesToWrite: DWORD, + lpReserved: LPDWORD, lpOverlapped: LPOVERLAPPED, + ) -> BOOL; + pub fn WritePrivateProfileSectionA( + lpAppName: LPCSTR, lpString: LPCSTR, lpFileName: LPCSTR, + ) -> BOOL; + pub fn WritePrivateProfileSectionW( + lpAppName: LPCWSTR, lpString: LPCWSTR, lpFileName: LPCWSTR, + ) -> BOOL; + pub fn WritePrivateProfileStringA( + lpAppName: LPCSTR, lpKeyName: LPCSTR, lpString: LPCSTR, lpFileName: LPCSTR, + ) -> BOOL; + pub fn WritePrivateProfileStringW( + lpAppName: LPCWSTR, lpKeyName: LPCWSTR, lpString: LPCWSTR, lpFileName: LPCWSTR, + ) -> BOOL; + pub fn WritePrivateProfileStructA( + lpszSection: LPCSTR, lpszKey: LPCSTR, lpStruct: LPVOID, uSizeStruct: UINT, szFile: LPCSTR, + ) -> BOOL; + pub fn WritePrivateProfileStructW( + lpszSection: LPCWSTR, lpszKey: LPCWSTR, lpStruct: LPVOID, uSizeStruct: UINT, + szFile: LPCWSTR, + ) -> BOOL; + pub fn WriteProcessMemory( + hProcess: HANDLE, lpBaseAddress: LPVOID, lpBuffer: LPCVOID, nSize: SIZE_T, + lpNumberOfBytesWritten: *mut SIZE_T, + ) -> BOOL; + pub fn WriteProfileSectionA(lpAppName: LPCSTR, lpString: LPCSTR) -> BOOL; + pub fn WriteProfileSectionW(lpAppName: LPCWSTR, lpString: LPCWSTR) -> BOOL; + pub fn WriteProfileStringA(lpAppName: LPCSTR, lpKeyName: LPCSTR, lpString: LPCSTR) -> BOOL; + pub fn WriteProfileStringW(lpAppName: LPCWSTR, lpKeyName: LPCWSTR, lpString: LPCWSTR) -> BOOL; + pub fn WriteTapemark( + hDevice: HANDLE, dwTapemarkType: DWORD, dwTapemarkCount: DWORD, bImmediate: BOOL, + ) -> DWORD; + pub fn ZombifyActCtx(hActCtx: HANDLE) -> BOOL; + pub fn _hread(hFile: HFILE, lpBuffer: LPVOID, lBytes: c_long) -> c_long; + pub fn _hwrite(hFile: HFILE, lpBuffer: LPCCH, lBytes: c_long) -> c_long; + pub fn _lclose(hFile: HFILE) -> HFILE; + pub fn _lcreat(lpPathName: LPCSTR, iAttrubute: c_int) -> HFILE; + pub fn _llseek(hFile: HFILE, lOffset: LONG, iOrigin: c_int) -> LONG; + pub fn _lopen(lpPathName: LPCSTR, iReadWrite: c_int) -> HFILE; + pub fn _lread(hFile: HFILE, lpBuffer: LPVOID, uBytes: UINT) -> UINT; + pub fn _lwrite(hFile: HFILE, lpBuffer: LPCCH, uBytes: UINT) -> UINT; + pub fn lstrcat(lpString1: LPSTR, lpString2: LPCSTR) -> LPSTR; + pub fn lstrcatA(lpString1: LPSTR, lpString2: LPCSTR) -> LPSTR; + pub fn lstrcatW(lpString1: LPWSTR, lpString2: LPCWSTR) -> LPSTR; + pub fn lstrcmp(lpString1: LPCSTR, lpString2: LPCSTR) -> c_int; + pub fn lstrcmpA(lpString1: LPCSTR, lpString2: LPCSTR) -> c_int; + pub fn lstrcmpW(lpString1: LPCWSTR, lpString2: LPCWSTR) -> c_int; + pub fn lstrcmpi(lpString1: LPCSTR, lpString2: LPCSTR) -> c_int; + pub fn lstrcmpiA(lpString1: LPCSTR, lpString2: LPCSTR) -> c_int; + pub fn lstrcmpiW(lpString1: LPCWSTR, lpString2: LPCWSTR) -> c_int; + pub fn lstrcpy(lpString1: LPSTR, lpString2: LPCSTR) -> LPSTR; + pub fn lstrcpyA(lpString1: LPSTR, lpString2: LPCSTR) -> LPSTR; + pub fn lstrcpyW(lpString1: LPWSTR, lpString2: LPCWSTR) -> LPSTR; + pub fn lstrcpyn(lpString1: LPSTR, lpString2: LPCSTR, iMaxLength: c_int) -> LPSTR; + pub fn lstrcpynA(lpString1: LPSTR, lpString2: LPCSTR, iMaxLength: c_int) -> LPSTR; + pub fn lstrcpynW(lpString1: LPWSTR, lpString2: LPCWSTR, iMaxLength: c_int) -> LPSTR; + pub fn lstrlen(lpString: LPCSTR) -> c_int; + pub fn lstrlenA(lpString: LPCSTR) -> c_int; + pub fn lstrlenW(lpString: LPCWSTR) -> c_int; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_lstrcmpW(String1: PCUWSTR, String2: PCUWSTR) -> c_int; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_lstrcmpiW(String1: PCUWSTR, String2: PCUWSTR) -> c_int; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_lstrlenW(String: LPCUWSTR) -> c_int; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_wcschr(String: PCUWSTR, Character: WCHAR) -> PUWSTR; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_wcscpy(Destination: PUWSTR, Source: PCUWSTR) -> PUWSTR; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_wcsicmp(String1: PCUWSTR, String2: PCUWSTR) -> c_int; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_wcslen(String: PCUWSTR) -> size_t; + #[cfg(any(target_arch = "arm", target_arch = "x86_64"))] + pub fn uaw_wcsrchr(String: PCUWSTR, Character: WCHAR) -> PUWSTR; +} diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json index ccdd4f84df..f66d303a51 100644 --- a/vendor/libc/.cargo-checksum.json +++ b/vendor/libc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"abc79e7f6c3eee37e21baca32847b6709c973f4995b32892e80deb56b73c9ac5","Cargo.toml":"081d553ece666bafa6152dd34b800d373614516db3191b66a0edc56a36172015","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"04d4132d1039c1ad753fecdadd0b863bbc4e22dd7bc896db09acd125812f8b4a","build.rs":"ee4839872f6d0364101b29a7b7e9d5c2421f47cd0d752e1e52533f58ea489af1","rustfmt.toml":"8a654d5787585ca8f2c20580737336fc327f411a07b0dbd4870adf6e9bdf624f","src/cloudabi/aarch64.rs":"b8550bf1fd7344972aa4db29441486f39f31482d0327534981dbb75959c29114","src/cloudabi/arm.rs":"c197e2781c2839808bd6fcef219a29705b27b992d3ef920e9cf6ac96e2022bbf","src/cloudabi/mod.rs":"b3ca0393f66ca803246e9b2dbbf9b6caadef2b7b7135412f3d914588b0630295","src/cloudabi/x86.rs":"33eb97f272d2201f3838ae74d444583c7de8f67856852ca375293b20bbd05636","src/cloudabi/x86_64.rs":"400d85d4fe39e26cf2e6ece9ee31c75fe9e88c4bcf4d836ca9f765c05c9c5be3","src/fixed_width_ints.rs":"782b2b2aa6f471f2ebab220456ed681f76980c572f194ec3755ce76f27c8eab6","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"9ca6271f2cbb0e6ca3b48ff6898ecee31c89b3c8388ae20be63e457aabad13a5","src/fuchsia/mod.rs":"ce85ffc3da5629701331791d01574fdb824d58d36399cee7bf46118d61dcf935","src/fuchsia/no_align.rs":"56868534e4ed3f94a27ed39c42f01210c8ecfdbafd4e27679860fbc65a2ae8de","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"aeda183662787a44c4bd26645cea76f31bf5f7c63d4d59118118c360705fb9eb","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"39d528e87d6165c2cd0d2b3060b1eb458e7ca588c3044f311d6f456c2751c79e","src/macros.rs":"2407f3a2d5e3ae6224457bc793378aa35fc8d57bdc6c3d8024ace0ecbd9782f4","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/switch.rs":"6249b9c891f89c74730f70b9f98f2b2c66676e5f2b2ffaddd13b63781f214f3e","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32.rs":"b2bbdaed9f2006ed6a4a236d5683983307a3c1d229fc8b90dd53afb496ccf422","src/unix/bsd/apple/b64.rs":"dc895aa7d94c9bc6b01a0072708bbf23fceb212fdece0c81ddb73f985d5479e7","src/unix/bsd/apple/mod.rs":"d2a36fa92c1eaa93debfea1fc0a6998881e80d2d1e4cd03759915d8dc275cb9a","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"3ea47ead5855b98267bb931f47d8dad44a0418b262eaa999786deb0d7deb92b2","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"24da2062119597eca17cadcf40d2db93c0c765aeca3eb887c8d2c9534f567d8c","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"e528191e42977fa4c226d8850c47d3e526e951cca46ea9a4a87af40221f79d63","src/unix/bsd/freebsdlike/freebsd/arm.rs":"10fe01bc6269b47da72d1e9f8bdae2fcc7d4f332540e8ce1756e1f58d506bf8c","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"bc9f26d046aa8471228c376fb79afb40936eb0ccf8c5dc2111600f7392ef77b4","src/unix/bsd/freebsdlike/freebsd/freebsd11/x86_64.rs":"deb18ce1991567f02831033cd41aca532277affc2e2d14e2966a9a22eb985679","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"f60c8895fb3e3d656eca41f0ed785b260f15b1c4aa8613a5c2b05e41cde27236","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"06b0355363d14ce7c9e7577b1cefbc12984ca7448f712519f9a29a758934db45","src/unix/bsd/freebsdlike/freebsd/mod.rs":"898a5f20d2c69406744ca5ef73acc13af6b1a07ade8361f659a1eee57eef9442","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"125457305b14309cbad4c46fd2fbd54e2f96d37adfec6c89ae9ed8cedfa015bc","src/unix/bsd/freebsdlike/freebsd/x86.rs":"4e0813f01a017dc148262d7c40dfadb964eb7eb6138dc2b0b83d0b51dbe4d467","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"841c64cda9601ad9b0320f01b2bafbd44cdcdd05ca5b90224f294809adb7d80f","src/unix/bsd/freebsdlike/mod.rs":"fc1a3055db220e816c1b0dcd06fd7d792c9c94d0f441779759fb507d63e4fc8a","src/unix/bsd/mod.rs":"939cd11741b845295b25c5cec3bffd321faa2ac44958a8dfdbf5d4be74331aeb","src/unix/bsd/netbsdlike/mod.rs":"6511a4d2b2a7869fdb55489db126eec89cfc0d8771cab6218319aef3e1be271e","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b29bf6c8c581c6afa21d756803ae245d54ec7bd94777f97f0ecf3f0ad17d5072","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"135509edeaf3fb3f102d89d51ff1a8f82323497336a8dc7e1f0f23b5c2434b73","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"ee0057fb97a5e16e46e0f8e4a215f6141b68ea75dd6cb5d53166bee2431082e2","src/unix/bsd/netbsdlike/openbsd/mod.rs":"df51b11d1e96d44f34b8697b16b1162f582101ce56bfc12329047ca689b249af","src/unix/bsd/netbsdlike/openbsd/x86.rs":"1201371a662cb3515ebb42676cdca9199da7bf4d7c8f90b56f00db03a9fc61f7","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"26ef6f50740fad5bb722e0f30025c369c287b2204489682319f7b24fce6de98d","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"1f2da746cdd9683f62cd908fd3048b06d34277f512b7748ed283c01c4b703ff3","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"0e17a9f2bbde2d1b4e83bde0ef39826a25ef357f78dcd7e4671079faa1204799","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"3625a32c7e58cfe683a53486fbe3d42d4e28f00bea31e19cb46ed2bb0b6a140b","src/unix/linux_like/android/b32/mod.rs":"73c3482a4f3b200a6bc0a6562a281e4fe449488ee9bde1b430f2412ab2e32dc5","src/unix/linux_like/android/b32/x86.rs":"ae2b7f1d6278caddc007749bb1d09ca33f7593478a0fd7fe98b457dae86c7814","src/unix/linux_like/android/b64/aarch64.rs":"37a6ad89617f88f45acbd990281b7557047be9ff4b167c435e9cd5e79859e19f","src/unix/linux_like/android/b64/mod.rs":"07b24a9d22731b44459e0533e6a12ffc72c45e9caee86df5263c44bf32def5ab","src/unix/linux_like/android/b64/x86_64.rs":"a6224d4cb8029eccae1549e602c4fc9847eac09213b4300ca65c6b07e8905397","src/unix/linux_like/android/mod.rs":"92ecca148375342e3a7c2c2e16030a340e2ebe153f89105f26f909da3737669d","src/unix/linux_like/emscripten/align.rs":"dee06bccb5f1a58bd498468f204b8f1d8f2c2a536c595d31e730330a79af7ea5","src/unix/linux_like/emscripten/mod.rs":"573a180c604d95e80cc72e5bca8ab5d8bce9298951a3979e22afd7c4edd7c572","src/unix/linux_like/emscripten/no_align.rs":"f3960b1d6ede1f8f9d51407a3de5337d44dd5d954e1a4c2bf0ea11e76f2629da","src/unix/linux_like/linux/align.rs":"85acc1c7e3701d4b1cad1153798022ad8a3a5c9ae9454fb741237cc15e354ac4","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm.rs":"5848e7e40d63b0f3ed888e479f441a360d5d707498d08237bb2a1c19ae351c4c","src/unix/linux_like/linux/gnu/b32/mips.rs":"172811216a8f2fd0d8b4b8195dbd7f426c02939355d17c9850f592deef701df2","src/unix/linux_like/linux/gnu/b32/mod.rs":"7f358e0a62cee1d375f212db2bf4f24b6f14011d6429be2d2f5e8ca0adcff05b","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"7975df6a52064979d0be2a6f5e216c411994420650972086e8ac4f5c43abdac1","src/unix/linux_like/linux/gnu/b32/x86.rs":"a24ee8115121d087f31191b77986b01c95c585e4a4ba8d934444739deaa9e3d3","src/unix/linux_like/linux/gnu/b64/aarch64.rs":"302307ed471edbf613126b2183788a8d5c5d578631c213de81862d05881e5124","src/unix/linux_like/linux/gnu/b64/mips64.rs":"39e46439f89a41b3ac58247ed5f9b0071b0556a4432b36c91390518d3624e7b5","src/unix/linux_like/linux/gnu/b64/mod.rs":"71d893473ade2c7d6336d735c573430dc53d0f855970504ca5db7b3db203be8d","src/unix/linux_like/linux/gnu/b64/powerpc64.rs":"90f12954a94f85b6f777ae295d4f81ab05627e9a9a660e019876832ee6fbd6b8","src/unix/linux_like/linux/gnu/b64/s390x.rs":"e56e3779f0903ac20e420dfbe8939a1122853fc659b778bb3b8d37842e475132","src/unix/linux_like/linux/gnu/b64/sparc64.rs":"39edd23b8dd140d953a8fb521cf6f2e5313c0fc2f565a1c207ea53ecab7c5f98","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"855c1288837521b3a01b5920409e92b4e444564424f9e77fa871407bcc140fbf","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"9229b6d912bd89f55b258c53ae52b33dfc263b39bfbc34a660d277be57c2c84e","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"30f88d0fa9e7807ee4cbe89fd274061f810099567d5e68fa829277d7d27ba708","src/unix/linux_like/linux/gnu/mod.rs":"99cfa3a1bfa29d595505ab4d80a2090dda3f385ec1f49ed896166a1097cafe56","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"099620d6f239f12b9824ddb23687138053cce5642fa7d63ef4bcc78b7d48fef5","src/unix/linux_like/linux/musl/b32/arm.rs":"91d26fada3f7845b1ab7e97c26dc80cffa25d3ee2be0c5bff9de1e1cd5d73366","src/unix/linux_like/linux/musl/b32/mips.rs":"916a50db36680be4a88f210d34f95ad1f510c7c9cbdaa56b9de4c49b444c5cf7","src/unix/linux_like/linux/musl/b32/mod.rs":"540928f168f145c136f9dd729ffa12b9d1838d9fe664fc642365d17d7fae648f","src/unix/linux_like/linux/musl/b32/powerpc.rs":"a8e651d67f5baa3033a0ce4d7ccf88c7f86208abd33edb57baf50d7358e2836f","src/unix/linux_like/linux/musl/b32/x86.rs":"4b289b27fa4fefe40265dddc6103c3f4eb93459440ab8058d301b3fbac8d8c17","src/unix/linux_like/linux/musl/b64/aarch64.rs":"2738e577ec6898d42d5d929d1d1a9d703442053c4b7e0afa2accc7e426adc710","src/unix/linux_like/linux/musl/b64/mod.rs":"da8c3caff213c322c3aa323b9c7e1b3db1f33e1ee496e789241df6a8a90f975e","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"10dc1809aebd7bde2fcf743153dcbc331257b373e659a9db4e9745cf115e4c7d","src/unix/linux_like/linux/musl/b64/x86_64.rs":"bca197efaa40ac23e7d3fd76c7d33477b70253c6bf5445de0348fd399ffa224e","src/unix/linux_like/linux/musl/mod.rs":"db253049dff6588afa44a6c0a2c4c3a2d4b4d015588e2d4e245585625b5405df","src/unix/linux_like/linux/no_align.rs":"7a1cc536b26c22019d7dab6b6db3a8c9edbb753d3f37a7985c30d8894c2c6b06","src/unix/linux_like/mod.rs":"4a45bcaf295488b972021d91c58443a664fb00284114fc4dd8d885284b1e1faa","src/unix/mod.rs":"6b59a01adfff0f675fedf7c32e718315a67f4ccc1124a9d6a9b05b5f8805931a","src/unix/newlib/aarch64/mod.rs":"c408a990f22fb4292a824f38367e9b517e6e6f8623328397ee631cc88b3d1f7d","src/unix/newlib/align.rs":"04e9b1ac6ca4af24fe5170385249fd64039ebf7f4817c5ceed3a303f3bc8a4aa","src/unix/newlib/arm/mod.rs":"2b6dba2e697ab9b4f4bc4dd5f28057249e9b596d1cb395a9322ec87605c4a5c4","src/unix/newlib/mod.rs":"0fb07669a9bb7849850c4f6507de3b73b34131e3a1cdbac421076c8a60fd11b6","src/unix/newlib/no_align.rs":"7123dcec13604a11b7765c380ff3a4d0da19c39f4b03919de7857723c0cf1502","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"d5ccf1a80b09bcd42a78804a3ad038f3bf90cce9b1b46b88e30f9c0a8dc2352e","src/unix/solarish/compat.rs":"8db2a43eafbd3504e9eb9e8f18416c57d947798871bd45be3e2fb9946e292610","src/unix/solarish/mod.rs":"b715246dd48adf4794e7b6dc2ec166c80561fcae42fa100c62ffca23b624d6fc","src/unix/uclibc/align.rs":"5607180357a9e3d87163e478116b45c7ece391d8366d65ff856cdf3e849452d7","src/unix/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/uclibc/arm/mod.rs":"617f087ce7b6244633f8f80ac61cb2f1f4d793ba77b1edb2bfa24f1af470ab94","src/unix/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/uclibc/mips/mips32/mod.rs":"417a5ab4f9d6fd35bd08396b6e513da7edabf87ac97381f83565bbb1a166f9f6","src/unix/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/uclibc/mips/mips64/mod.rs":"03f3bad1c681e6fde4a8ed999ce1d38313166c17d35eded66bd6b4f8387efeb7","src/unix/uclibc/mips/mips64/no_align.rs":"bf11b59caa173a6d94d86f42a8de9c5682f798647fba3a17169214b59ab467fe","src/unix/uclibc/mips/mod.rs":"1054d0bfeb506b3346b9a4148564beced8a22da0d9c9a612101f6237756795fb","src/unix/uclibc/mod.rs":"c0ab7cd511311e03e73bb76245d87ff85ce47e4526d3d44c5de9b005c33d2284","src/unix/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/uclibc/x86_64/align.rs":"26e48fc79dbdeee4408ae8e071aa90e1be34ccdf0c135689b805aa4abd568e5e","src/unix/uclibc/x86_64/l4re.rs":"bb31053d6403091e11f95ac2203982f279f8b984a19adf30796878c45fdd8c25","src/unix/uclibc/x86_64/mod.rs":"df78de7e0234192c0559b9820c0034a24d72a0820d361f9aad05a9eac36e80ff","src/unix/uclibc/x86_64/no_align.rs":"b308f7b110caf7405b57186882cfc4804caae49a8287f8ab612ec8548467f2f4","src/unix/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/wasi.rs":"b1f529dfacc16810926d144ab317634922739b1aff18b7814feba0fc5c770cd6","src/windows/gnu.rs":"4d9033162cc6f7d245256c7b165c1ec18a741771fd9b99a55b421e8d14978599","src/windows/mod.rs":"16d282c830e7ed56c2cecc6affe88ac0597a94e392f295a707fbdf7951f5a723","src/windows/msvc.rs":"8f46cf66883c794175609a3b2bafaa094d0ba63eb6720ef1b84b175603f1074f"},"package":"d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"} \ No newline at end of file +{"files":{"CONTRIBUTING.md":"08519d470caa336a4a594bec718438073216554fde122cc7c1d723347d558d3a","Cargo.toml":"ad57db39db88e14c0f6b7accc0c74b6729dae6e245624b8dc984e48710e1df29","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"bf27f2aafc020fc8ca130f736fc94f6a76c3a029d68a03476a875623fc048986","build.rs":"ae167510b967a9ef1310e0f6e706fc8a1342eb768ebaec5a067b33072bfb42f8","rustfmt.toml":"8a654d5787585ca8f2c20580737336fc327f411a07b0dbd4870adf6e9bdf624f","src/cloudabi/aarch64.rs":"b8550bf1fd7344972aa4db29441486f39f31482d0327534981dbb75959c29114","src/cloudabi/arm.rs":"c197e2781c2839808bd6fcef219a29705b27b992d3ef920e9cf6ac96e2022bbf","src/cloudabi/mod.rs":"b3ca0393f66ca803246e9b2dbbf9b6caadef2b7b7135412f3d914588b0630295","src/cloudabi/x86.rs":"33eb97f272d2201f3838ae74d444583c7de8f67856852ca375293b20bbd05636","src/cloudabi/x86_64.rs":"400d85d4fe39e26cf2e6ece9ee31c75fe9e88c4bcf4d836ca9f765c05c9c5be3","src/fixed_width_ints.rs":"782b2b2aa6f471f2ebab220456ed681f76980c572f194ec3755ce76f27c8eab6","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"9ca6271f2cbb0e6ca3b48ff6898ecee31c89b3c8388ae20be63e457aabad13a5","src/fuchsia/mod.rs":"ce85ffc3da5629701331791d01574fdb824d58d36399cee7bf46118d61dcf935","src/fuchsia/no_align.rs":"56868534e4ed3f94a27ed39c42f01210c8ecfdbafd4e27679860fbc65a2ae8de","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"aeda183662787a44c4bd26645cea76f31bf5f7c63d4d59118118c360705fb9eb","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"72e8760a6a23bf8f976ee4839a8da5bab05bc3832b094c50e1daabed609386d9","src/macros.rs":"2407f3a2d5e3ae6224457bc793378aa35fc8d57bdc6c3d8024ace0ecbd9782f4","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/switch.rs":"6249b9c891f89c74730f70b9f98f2b2c66676e5f2b2ffaddd13b63781f214f3e","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32.rs":"6662d0881c5bf4d80500932bb10700f81b8c1b3ffcc2c96103c92354794b301d","src/unix/bsd/apple/b64.rs":"ef61930aace85288092685935f1d7057f920990b00c232e7f8daee81c2834562","src/unix/bsd/apple/mod.rs":"1636c07c75345e229b76864f9f2bcdf025dbce5d1089a53e430e925e5ddf976a","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"3ea47ead5855b98267bb931f47d8dad44a0418b262eaa999786deb0d7deb92b2","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"24da2062119597eca17cadcf40d2db93c0c765aeca3eb887c8d2c9534f567d8c","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"e528191e42977fa4c226d8850c47d3e526e951cca46ea9a4a87af40221f79d63","src/unix/bsd/freebsdlike/freebsd/arm.rs":"10fe01bc6269b47da72d1e9f8bdae2fcc7d4f332540e8ce1756e1f58d506bf8c","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"281e6590b61eab56cb74b0aca767e262ebf0eccbb5fb0c18a9ea759d9e9ffe36","src/unix/bsd/freebsdlike/freebsd/freebsd11/x86_64.rs":"deb18ce1991567f02831033cd41aca532277affc2e2d14e2966a9a22eb985679","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"b51c860f07669fc44e55eef9eeee15c6a76ab2a92edd8f4fb527cecdf622864c","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"06b0355363d14ce7c9e7577b1cefbc12984ca7448f712519f9a29a758934db45","src/unix/bsd/freebsdlike/freebsd/mod.rs":"add56018475daf5d347a5b743fff05fbd1aa8d88b20b2e7087ee6cd5d2aab36f","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"125457305b14309cbad4c46fd2fbd54e2f96d37adfec6c89ae9ed8cedfa015bc","src/unix/bsd/freebsdlike/freebsd/x86.rs":"4e0813f01a017dc148262d7c40dfadb964eb7eb6138dc2b0b83d0b51dbe4d467","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"841c64cda9601ad9b0320f01b2bafbd44cdcdd05ca5b90224f294809adb7d80f","src/unix/bsd/freebsdlike/mod.rs":"e5512b011ded45040ec1009a8ceea2fcfd0fe2e46ac693ea762a09d72065ead7","src/unix/bsd/mod.rs":"6c4108ee688b23b6282765995b31c7c85a99b10a8964576660d528e753034c94","src/unix/bsd/netbsdlike/mod.rs":"6511a4d2b2a7869fdb55489db126eec89cfc0d8771cab6218319aef3e1be271e","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b29bf6c8c581c6afa21d756803ae245d54ec7bd94777f97f0ecf3f0ad17d5072","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"135509edeaf3fb3f102d89d51ff1a8f82323497336a8dc7e1f0f23b5c2434b73","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"ee0057fb97a5e16e46e0f8e4a215f6141b68ea75dd6cb5d53166bee2431082e2","src/unix/bsd/netbsdlike/openbsd/mod.rs":"b9f7cde0fce69f9f6c38ab251d877ad3429b6d1169d6b5ecb8c2e9c2854c478f","src/unix/bsd/netbsdlike/openbsd/x86.rs":"1201371a662cb3515ebb42676cdca9199da7bf4d7c8f90b56f00db03a9fc61f7","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"26ef6f50740fad5bb722e0f30025c369c287b2204489682319f7b24fce6de98d","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"1f2da746cdd9683f62cd908fd3048b06d34277f512b7748ed283c01c4b703ff3","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"0e17a9f2bbde2d1b4e83bde0ef39826a25ef357f78dcd7e4671079faa1204799","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"3625a32c7e58cfe683a53486fbe3d42d4e28f00bea31e19cb46ed2bb0b6a140b","src/unix/linux_like/android/b32/mod.rs":"73c3482a4f3b200a6bc0a6562a281e4fe449488ee9bde1b430f2412ab2e32dc5","src/unix/linux_like/android/b32/x86.rs":"ae2b7f1d6278caddc007749bb1d09ca33f7593478a0fd7fe98b457dae86c7814","src/unix/linux_like/android/b64/aarch64.rs":"37a6ad89617f88f45acbd990281b7557047be9ff4b167c435e9cd5e79859e19f","src/unix/linux_like/android/b64/mod.rs":"07b24a9d22731b44459e0533e6a12ffc72c45e9caee86df5263c44bf32def5ab","src/unix/linux_like/android/b64/x86_64.rs":"a6224d4cb8029eccae1549e602c4fc9847eac09213b4300ca65c6b07e8905397","src/unix/linux_like/android/mod.rs":"92ecca148375342e3a7c2c2e16030a340e2ebe153f89105f26f909da3737669d","src/unix/linux_like/emscripten/align.rs":"dee06bccb5f1a58bd498468f204b8f1d8f2c2a536c595d31e730330a79af7ea5","src/unix/linux_like/emscripten/mod.rs":"573a180c604d95e80cc72e5bca8ab5d8bce9298951a3979e22afd7c4edd7c572","src/unix/linux_like/emscripten/no_align.rs":"f3960b1d6ede1f8f9d51407a3de5337d44dd5d954e1a4c2bf0ea11e76f2629da","src/unix/linux_like/linux/align.rs":"657fa2c7b036ee0468522a935cfe510488aa66d64c738dd9fadf932b220e2ad3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm.rs":"5848e7e40d63b0f3ed888e479f441a360d5d707498d08237bb2a1c19ae351c4c","src/unix/linux_like/linux/gnu/b32/mips.rs":"172811216a8f2fd0d8b4b8195dbd7f426c02939355d17c9850f592deef701df2","src/unix/linux_like/linux/gnu/b32/mod.rs":"7f358e0a62cee1d375f212db2bf4f24b6f14011d6429be2d2f5e8ca0adcff05b","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"7975df6a52064979d0be2a6f5e216c411994420650972086e8ac4f5c43abdac1","src/unix/linux_like/linux/gnu/b32/x86.rs":"a24ee8115121d087f31191b77986b01c95c585e4a4ba8d934444739deaa9e3d3","src/unix/linux_like/linux/gnu/b64/aarch64.rs":"302307ed471edbf613126b2183788a8d5c5d578631c213de81862d05881e5124","src/unix/linux_like/linux/gnu/b64/mips64.rs":"39e46439f89a41b3ac58247ed5f9b0071b0556a4432b36c91390518d3624e7b5","src/unix/linux_like/linux/gnu/b64/mod.rs":"71d893473ade2c7d6336d735c573430dc53d0f855970504ca5db7b3db203be8d","src/unix/linux_like/linux/gnu/b64/powerpc64.rs":"90f12954a94f85b6f777ae295d4f81ab05627e9a9a660e019876832ee6fbd6b8","src/unix/linux_like/linux/gnu/b64/s390x.rs":"e56e3779f0903ac20e420dfbe8939a1122853fc659b778bb3b8d37842e475132","src/unix/linux_like/linux/gnu/b64/sparc64.rs":"39edd23b8dd140d953a8fb521cf6f2e5313c0fc2f565a1c207ea53ecab7c5f98","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"855c1288837521b3a01b5920409e92b4e444564424f9e77fa871407bcc140fbf","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"9229b6d912bd89f55b258c53ae52b33dfc263b39bfbc34a660d277be57c2c84e","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"30f88d0fa9e7807ee4cbe89fd274061f810099567d5e68fa829277d7d27ba708","src/unix/linux_like/linux/gnu/mod.rs":"bb5b0695dc6bbfa2218bad40200f96e20a3f01215207c4702cbd0a466bcf108c","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"03b82d8091327e941714b912c0bf3e786073de86b5367a7f194b5a43a3803008","src/unix/linux_like/linux/musl/b32/arm.rs":"91d26fada3f7845b1ab7e97c26dc80cffa25d3ee2be0c5bff9de1e1cd5d73366","src/unix/linux_like/linux/musl/b32/hexagon.rs":"b99c46c6205f68eedcec5d6872d4b56c0b7aa5d35ec1ce78a42a9f19eef0ae9e","src/unix/linux_like/linux/musl/b32/mips.rs":"916a50db36680be4a88f210d34f95ad1f510c7c9cbdaa56b9de4c49b444c5cf7","src/unix/linux_like/linux/musl/b32/mod.rs":"f2fa5aa4ec43976350a601f726089b3b882041ddb9d685d5237b8d2429ae02f9","src/unix/linux_like/linux/musl/b32/powerpc.rs":"a8e651d67f5baa3033a0ce4d7ccf88c7f86208abd33edb57baf50d7358e2836f","src/unix/linux_like/linux/musl/b32/x86.rs":"4b289b27fa4fefe40265dddc6103c3f4eb93459440ab8058d301b3fbac8d8c17","src/unix/linux_like/linux/musl/b64/aarch64.rs":"2738e577ec6898d42d5d929d1d1a9d703442053c4b7e0afa2accc7e426adc710","src/unix/linux_like/linux/musl/b64/mod.rs":"da8c3caff213c322c3aa323b9c7e1b3db1f33e1ee496e789241df6a8a90f975e","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"10dc1809aebd7bde2fcf743153dcbc331257b373e659a9db4e9745cf115e4c7d","src/unix/linux_like/linux/musl/b64/x86_64.rs":"bca197efaa40ac23e7d3fd76c7d33477b70253c6bf5445de0348fd399ffa224e","src/unix/linux_like/linux/musl/mod.rs":"783d140bd1c1604701bb3aa708320f96dfd4e947b7fdd30a6170c6150607950e","src/unix/linux_like/linux/no_align.rs":"7a1cc536b26c22019d7dab6b6db3a8c9edbb753d3f37a7985c30d8894c2c6b06","src/unix/linux_like/mod.rs":"104fbd3924885cf491d67f1eccf5f652048cef7cb5eb57226ad8e30e2ad53c61","src/unix/mod.rs":"1e4ee7aa55ad0611ff039c87328a2003578ab863550d316e6449bcef74792bad","src/unix/newlib/aarch64/mod.rs":"c408a990f22fb4292a824f38367e9b517e6e6f8623328397ee631cc88b3d1f7d","src/unix/newlib/align.rs":"04e9b1ac6ca4af24fe5170385249fd64039ebf7f4817c5ceed3a303f3bc8a4aa","src/unix/newlib/arm/mod.rs":"2b6dba2e697ab9b4f4bc4dd5f28057249e9b596d1cb395a9322ec87605c4a5c4","src/unix/newlib/mod.rs":"0fb07669a9bb7849850c4f6507de3b73b34131e3a1cdbac421076c8a60fd11b6","src/unix/newlib/no_align.rs":"7123dcec13604a11b7765c380ff3a4d0da19c39f4b03919de7857723c0cf1502","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"7c00d3e633b4b7efb512c627ddd16fcde0749bfa9f5fcf61b8434a1f71e215d7","src/unix/solarish/compat.rs":"8db2a43eafbd3504e9eb9e8f18416c57d947798871bd45be3e2fb9946e292610","src/unix/solarish/mod.rs":"b715246dd48adf4794e7b6dc2ec166c80561fcae42fa100c62ffca23b624d6fc","src/unix/uclibc/align.rs":"5607180357a9e3d87163e478116b45c7ece391d8366d65ff856cdf3e849452d7","src/unix/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/uclibc/arm/mod.rs":"617f087ce7b6244633f8f80ac61cb2f1f4d793ba77b1edb2bfa24f1af470ab94","src/unix/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/uclibc/mips/mips32/mod.rs":"417a5ab4f9d6fd35bd08396b6e513da7edabf87ac97381f83565bbb1a166f9f6","src/unix/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/uclibc/mips/mips64/mod.rs":"03f3bad1c681e6fde4a8ed999ce1d38313166c17d35eded66bd6b4f8387efeb7","src/unix/uclibc/mips/mips64/no_align.rs":"bf11b59caa173a6d94d86f42a8de9c5682f798647fba3a17169214b59ab467fe","src/unix/uclibc/mips/mod.rs":"1054d0bfeb506b3346b9a4148564beced8a22da0d9c9a612101f6237756795fb","src/unix/uclibc/mod.rs":"c0ab7cd511311e03e73bb76245d87ff85ce47e4526d3d44c5de9b005c33d2284","src/unix/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/uclibc/x86_64/align.rs":"26e48fc79dbdeee4408ae8e071aa90e1be34ccdf0c135689b805aa4abd568e5e","src/unix/uclibc/x86_64/l4re.rs":"bb31053d6403091e11f95ac2203982f279f8b984a19adf30796878c45fdd8c25","src/unix/uclibc/x86_64/mod.rs":"df78de7e0234192c0559b9820c0034a24d72a0820d361f9aad05a9eac36e80ff","src/unix/uclibc/x86_64/no_align.rs":"b308f7b110caf7405b57186882cfc4804caae49a8287f8ab612ec8548467f2f4","src/unix/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/vxworks/aarch64.rs":"e4432cf8e57c2e1514156b834fad6fa8304867f9d71fc231c678d628859728f0","src/vxworks/arm.rs":"a9520a77d1764ee4d9d44a1454181ec1f814180994c1b4e18af64ad4a4a85150","src/vxworks/armv7.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/vxworks/mod.rs":"cade75b11757c36bc20e03650062d9310354f638c2d643c27a91373953c401fc","src/vxworks/powerpc.rs":"a9520a77d1764ee4d9d44a1454181ec1f814180994c1b4e18af64ad4a4a85150","src/vxworks/powerpc64.rs":"e4432cf8e57c2e1514156b834fad6fa8304867f9d71fc231c678d628859728f0","src/vxworks/x86.rs":"2dd176eaa68e615e7271d017785981594e748153df24eb761e11e5dc14ff2f71","src/vxworks/x86_64.rs":"7c959cdb3415f68a0f948117b9aa87a17463e57ab97cc3235f2567454b706653","src/wasi.rs":"b1f529dfacc16810926d144ab317634922739b1aff18b7814feba0fc5c770cd6","src/windows/gnu.rs":"4d9033162cc6f7d245256c7b165c1ec18a741771fd9b99a55b421e8d14978599","src/windows/mod.rs":"16d282c830e7ed56c2cecc6affe88ac0597a94e392f295a707fbdf7951f5a723","src/windows/msvc.rs":"8f46cf66883c794175609a3b2bafaa094d0ba63eb6720ef1b84b175603f1074f"},"package":"34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"} \ No newline at end of file diff --git a/vendor/libc/CONTRIBUTING.md b/vendor/libc/CONTRIBUTING.md index 0e5d0c68b8..7c22c08622 100644 --- a/vendor/libc/CONTRIBUTING.md +++ b/vendor/libc/CONTRIBUTING.md @@ -38,9 +38,9 @@ With that in mind, the steps for adding a new API are: ### Test before you commit -We have two automated tests running on [Travis](https://travis-ci.org/rust-lang/libc): +We have two automated tests running on [Azure Pipelines](https://dev.azure.com/rust-lang2/libc/_build?definitionId=1&_a=summary): -1. [`libc-test`](https://github.com/alexcrichton/ctest) +1. [`libc-test`](https://github.com/gnzlbg/ctest) - `cd libc-test && cargo test` - Use the `skip_*()` functions in `build.rs` if you really need a workaround. 2. Style checker diff --git a/vendor/libc/Cargo.toml b/vendor/libc/Cargo.toml index 739a6d60d1..451758a676 100644 --- a/vendor/libc/Cargo.toml +++ b/vendor/libc/Cargo.toml @@ -12,10 +12,10 @@ [package] name = "libc" -version = "0.2.60" +version = "0.2.62" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/ci/*", "/.travis.yml", "/appveyor.yml"] +exclude = ["/ci/*", "/azure-pipelines.yml"] description = "Raw FFI bindings to platform libraries like libc.\n" homepage = "https://github.com/rust-lang/libc" documentation = "http://doc.rust-lang.org/libc" diff --git a/vendor/libc/README.md b/vendor/libc/README.md index dc5ff04fcc..4b860238bc 100644 --- a/vendor/libc/README.md +++ b/vendor/libc/README.md @@ -1,4 +1,4 @@ -[![Travis-CI Status]][Travis-CI] [![Appveyor Status]][Appveyor] [![Cirrus-CI Status]][Cirrus-CI] [![Latest Version]][crates.io] [![Documentation]][docs.rs] ![License] +[![Azure Status]][Azure] [![Cirrus-CI Status]][Cirrus-CI] [![Latest Version]][crates.io] [![Documentation]][docs.rs] ![License] libc - Raw FFI bindings to platforms' system libraries ==== @@ -91,10 +91,8 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `libc` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -[Travis-CI]: https://travis-ci.com/rust-lang/libc -[Travis-CI Status]: https://travis-ci.com/rust-lang/libc.svg?branch=master -[Appveyor]: https://ci.appveyor.com/project/rust-lang-libs/libc -[Appveyor Status]: https://ci.appveyor.com/api/projects/status/github/rust-lang/libc?svg=true +[Azure Status]: https://dev.azure.com/rust-lang2/libc/_apis/build/status/rust-lang.libc?branchName=master +[Azure]: https://dev.azure.com/rust-lang2/libc/_build/latest?definitionId=1&branchName=master [Cirrus-CI]: https://cirrus-ci.com/github/rust-lang/libc [Cirrus-CI Status]: https://api.cirrus-ci.com/github/rust-lang/libc.svg [crates.io]: https://crates.io/crates/libc diff --git a/vendor/libc/build.rs b/vendor/libc/build.rs index 76ca0961e4..efc95b6627 100644 --- a/vendor/libc/build.rs +++ b/vendor/libc/build.rs @@ -7,6 +7,8 @@ fn main() { rustc_minor_version().expect("Failed to get rustc version"); let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok(); let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok(); + #[allow(unused)] + let libc_ci = env::var("LIBC_CI").is_ok(); if env::var("CARGO_FEATURE_USE_STD").is_ok() { println!( @@ -15,10 +17,15 @@ fn main() { ); } - if env::var("LIBC_CI").is_ok() { - if let Some(12) = which_freebsd() { - println!("cargo:rustc-cfg=freebsd12"); - } + // The ABI of libc is backward compatible with FreeBSD 11. + // + // On CI, we detect the actual FreeBSD version and match its ABI exactly, + // running tests to ensure that the ABI is correct. + match which_freebsd() { + Some(11) if libc_ci => println!("cargo:rustc-cfg=freebsd11"), + Some(12) if libc_ci => println!("cargo:rustc-cfg=freebsd12"), + Some(13) if libc_ci => println!("cargo:rustc-cfg=freebsd13"), + Some(_) | None => println!("cargo:rustc-cfg=freebsd11"), } // Rust >= 1.15 supports private module use: @@ -100,6 +107,7 @@ fn which_freebsd() -> Option { match &stdout { s if s.starts_with("11") => Some(11), s if s.starts_with("12") => Some(12), + s if s.starts_with("13") => Some(13), _ => None, } } diff --git a/vendor/libc/src/lib.rs b/vendor/libc/src/lib.rs index 0f800cea0a..6c2e6c8b5b 100644 --- a/vendor/libc/src/lib.rs +++ b/vendor/libc/src/lib.rs @@ -114,6 +114,12 @@ cfg_if! { mod switch; pub use switch::*; + } else if #[cfg(target_os = "vxworks")] { + mod fixed_width_ints; + pub use fixed_width_ints::*; + + mod vxworks; + pub use vxworks::*; } else if #[cfg(unix)] { mod fixed_width_ints; pub use fixed_width_ints::*; diff --git a/vendor/libc/src/unix/bsd/apple/b32.rs b/vendor/libc/src/unix/bsd/apple/b32.rs index 859809dc86..c05de30327 100644 --- a/vendor/libc/src/unix/bsd/apple/b32.rs +++ b/vendor/libc/src/unix/bsd/apple/b32.rs @@ -81,6 +81,10 @@ cfg_if! { } } +#[doc(hidden)] +#[deprecated(since = "0.2.55")] +pub const NET_RT_MAXID: ::c_int = 10; + pub const __PTHREAD_MUTEX_SIZE__: usize = 40; pub const __PTHREAD_COND_SIZE__: usize = 24; pub const __PTHREAD_CONDATTR_SIZE__: usize = 4; diff --git a/vendor/libc/src/unix/bsd/apple/b64.rs b/vendor/libc/src/unix/bsd/apple/b64.rs index 7b89fc6ab5..2749260b04 100644 --- a/vendor/libc/src/unix/bsd/apple/b64.rs +++ b/vendor/libc/src/unix/bsd/apple/b64.rs @@ -86,6 +86,10 @@ cfg_if! { } } +#[doc(hidden)] +#[deprecated(since = "0.2.55")] +pub const NET_RT_MAXID: ::c_int = 11; + pub const __PTHREAD_MUTEX_SIZE__: usize = 56; pub const __PTHREAD_COND_SIZE__: usize = 40; pub const __PTHREAD_CONDATTR_SIZE__: usize = 8; diff --git a/vendor/libc/src/unix/bsd/apple/mod.rs b/vendor/libc/src/unix/bsd/apple/mod.rs index 2bc18fb216..24ad12bee5 100644 --- a/vendor/libc/src/unix/bsd/apple/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/mod.rs @@ -2178,9 +2178,6 @@ pub const PF_PPP: ::c_int = AF_PPP; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 3; -#[doc(hidden)] -#[deprecated(since = "0.2.55")] -pub const NET_RT_MAXID: ::c_int = 10; pub const SOMAXCONN: ::c_int = 128; diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs index 7d7dc2c1d4..b71b284e42 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs @@ -189,6 +189,8 @@ cfg_if! { } } +pub const ELAST: ::c_int = 96; + extern { // Return type ::c_int was removed in FreeBSD 12 pub fn setgrent() -> ::c_int; diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs index ab1b8d9835..464744d140 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs @@ -190,6 +190,15 @@ cfg_if! { } } +cfg_if! { + if #[cfg(not(freebsd13))] { + pub const ELAST: ::c_int = 96; + } else { + pub const EINTEGRITY: ::c_int = 97; + pub const ELAST: ::c_int = 97; + } +} + extern { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs index 9f11c202bb..fea680d2af 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -333,7 +333,6 @@ pub const ENOTCAPABLE: ::c_int = 93; pub const ECAPMODE: ::c_int = 94; pub const ENOTRECOVERABLE: ::c_int = 95; pub const EOWNERDEAD: ::c_int = 96; -pub const ELAST: ::c_int = 96; pub const RLIMIT_NPTS: ::c_int = 11; pub const RLIMIT_SWAP: ::c_int = 12; pub const RLIMIT_KQUEUES: ::c_int = 13; @@ -1332,9 +1331,14 @@ cfg_if! { if #[cfg(freebsd12)] { mod freebsd12; pub use self::freebsd12::*; - } else { + } else if #[cfg(freebsd13)] { + mod freebsd12; + pub use self::freebsd12::*; + } else if #[cfg(freebsd11)] { mod freebsd11; pub use self::freebsd11::*; + } else { + // Unknown freebsd version } } diff --git a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs index ce5452062c..f937d772a9 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs @@ -1152,7 +1152,7 @@ extern { pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "kevent@FBSD_1.0" )] pub fn kevent(kq: ::c_int, @@ -1171,7 +1171,7 @@ extern { pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "mknodat@FBSD_1.1" )] pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char, diff --git a/vendor/libc/src/unix/bsd/mod.rs b/vendor/libc/src/unix/bsd/mod.rs index 77f82b182b..ee644114a4 100644 --- a/vendor/libc/src/unix/bsd/mod.rs +++ b/vendor/libc/src/unix/bsd/mod.rs @@ -536,7 +536,7 @@ extern { #[cfg_attr(target_os = "macos", link_name = "glob$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__glob30")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "glob@FBSD_1.0" )] pub fn glob(pattern: *const ::c_char, @@ -546,7 +546,7 @@ extern { pglob: *mut ::glob_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "globfree@FBSD_1.0" )] pub fn globfree(pglob: *mut ::glob_t); diff --git a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs index 710a4fc40c..a397d58c93 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs @@ -1183,7 +1183,8 @@ pub const KERN_CONSBUF: ::c_int = 83; pub const KERN_AUDIO: ::c_int = 84; pub const KERN_CPUSTATS: ::c_int = 85; pub const KERN_PFSTATUS: ::c_int = 86; -pub const KERN_MAXID: ::c_int = 87; +pub const KERN_TIMEOUT_STATS: ::c_int = 87; +pub const KERN_MAXID: ::c_int = 88; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; diff --git a/vendor/libc/src/unix/linux_like/linux/align.rs b/vendor/libc/src/unix/linux_like/linux/align.rs index 0ff4649b8c..be8ac06976 100644 --- a/vendor/libc/src/unix/linux_like/linux/align.rs +++ b/vendor/libc/src/unix/linux_like/linux/align.rs @@ -60,6 +60,7 @@ macro_rules! expand_align { #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", + target_arch = "hexagon", target_arch = "powerpc", target_arch = "x86_64", target_arch = "x86")), @@ -67,6 +68,7 @@ macro_rules! expand_align { #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", + target_arch = "hexagon", target_arch = "powerpc", target_arch = "x86_64", target_arch = "x86"))), @@ -79,6 +81,7 @@ macro_rules! expand_align { #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", + target_arch = "hexagon", target_arch = "powerpc", target_arch = "x86_64", target_arch = "x86")), @@ -86,6 +89,7 @@ macro_rules! expand_align { #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", + target_arch = "hexagon", target_arch = "powerpc", target_arch = "x86_64", target_arch = "x86"))), diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs index 417fed6f27..735eaf24d8 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs @@ -611,65 +611,8 @@ pub const IFA_F_NOPREFIXROUTE: u32 = 0x200; pub const IFA_F_MCAUTOJOIN: u32 = 0x400; pub const IFA_F_STABLE_PRIVACY: u32 = 0x800; -pub const NETLINK_ROUTE: ::c_int = 0; -pub const NETLINK_UNUSED: ::c_int = 1; -pub const NETLINK_USERSOCK: ::c_int = 2; -pub const NETLINK_FIREWALL: ::c_int = 3; -pub const NETLINK_SOCK_DIAG: ::c_int = 4; -pub const NETLINK_NFLOG: ::c_int = 5; -pub const NETLINK_XFRM: ::c_int = 6; -pub const NETLINK_SELINUX: ::c_int = 7; -pub const NETLINK_ISCSI: ::c_int = 8; -pub const NETLINK_AUDIT: ::c_int = 9; -pub const NETLINK_FIB_LOOKUP: ::c_int = 10; -pub const NETLINK_CONNECTOR: ::c_int = 11; -pub const NETLINK_NETFILTER: ::c_int = 12; -pub const NETLINK_IP6_FW: ::c_int = 13; -pub const NETLINK_DNRTMSG: ::c_int = 14; -pub const NETLINK_KOBJECT_UEVENT: ::c_int = 15; -pub const NETLINK_GENERIC: ::c_int = 16; -pub const NETLINK_SCSITRANSPORT: ::c_int = 18; -pub const NETLINK_ECRYPTFS: ::c_int = 19; -pub const NETLINK_RDMA: ::c_int = 20; -pub const NETLINK_CRYPTO: ::c_int = 21; -pub const NETLINK_INET_DIAG: ::c_int = NETLINK_SOCK_DIAG; - pub const MAX_LINKS: ::c_int = 32; -pub const NLM_F_REQUEST: ::c_int = 1; -pub const NLM_F_MULTI: ::c_int = 2; -pub const NLM_F_ACK: ::c_int = 4; -pub const NLM_F_ECHO: ::c_int = 8; -pub const NLM_F_DUMP_INTR: ::c_int = 16; -pub const NLM_F_DUMP_FILTERED: ::c_int = 32; - -pub const NLM_F_ROOT: ::c_int = 0x100; -pub const NLM_F_MATCH: ::c_int = 0x200; -pub const NLM_F_ATOMIC: ::c_int = 0x400; -pub const NLM_F_DUMP: ::c_int = NLM_F_ROOT | NLM_F_MATCH; - -pub const NLM_F_REPLACE: ::c_int = 0x100; -pub const NLM_F_EXCL: ::c_int = 0x200; -pub const NLM_F_CREATE: ::c_int = 0x400; -pub const NLM_F_APPEND: ::c_int = 0x800; - -pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1; -pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2; -pub const NETLINK_PKTINFO: ::c_int = 3; -pub const NETLINK_BROADCAST_ERROR: ::c_int = 4; -pub const NETLINK_NO_ENOBUFS: ::c_int = 5; -pub const NETLINK_RX_RING: ::c_int = 6; -pub const NETLINK_TX_RING: ::c_int = 7; -pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; -pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; -pub const NETLINK_CAP_ACK: ::c_int = 10; - -pub const NLA_F_NESTED: ::c_int = 1 << 15; -pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; -pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); - -pub const NLA_ALIGNTO: ::c_int = 4; - pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10; pub const GENL_ID_VFS_DQUOT: ::c_int = ::NLMSG_MIN_TYPE + 1; @@ -929,12 +872,6 @@ cfg_if! { } pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 3; -f! { - pub fn NLA_ALIGN(len: ::c_int) -> ::c_int { - return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1) - } -} - extern { pub fn sendmmsg(sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int) -> ::c_int; diff --git a/vendor/libc/src/unix/linux_like/linux/mod.rs b/vendor/libc/src/unix/linux_like/linux/mod.rs index 8005395871..0fc7c26f2a 100644 --- a/vendor/libc/src/unix/linux_like/linux/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/mod.rs @@ -1897,6 +1897,64 @@ pub const NDA_PORT: ::c_ushort = 6; pub const NDA_VNI: ::c_ushort = 7; pub const NDA_IFINDEX: ::c_ushort = 8; +// linux/netlink.h +pub const NLA_ALIGNTO: ::c_int = 4; + +pub const NETLINK_ROUTE: ::c_int = 0; +pub const NETLINK_UNUSED: ::c_int = 1; +pub const NETLINK_USERSOCK: ::c_int = 2; +pub const NETLINK_FIREWALL: ::c_int = 3; +pub const NETLINK_SOCK_DIAG: ::c_int = 4; +pub const NETLINK_NFLOG: ::c_int = 5; +pub const NETLINK_XFRM: ::c_int = 6; +pub const NETLINK_SELINUX: ::c_int = 7; +pub const NETLINK_ISCSI: ::c_int = 8; +pub const NETLINK_AUDIT: ::c_int = 9; +pub const NETLINK_FIB_LOOKUP: ::c_int = 10; +pub const NETLINK_CONNECTOR: ::c_int = 11; +pub const NETLINK_NETFILTER: ::c_int = 12; +pub const NETLINK_IP6_FW: ::c_int = 13; +pub const NETLINK_DNRTMSG: ::c_int = 14; +pub const NETLINK_KOBJECT_UEVENT: ::c_int = 15; +pub const NETLINK_GENERIC: ::c_int = 16; +pub const NETLINK_SCSITRANSPORT: ::c_int = 18; +pub const NETLINK_ECRYPTFS: ::c_int = 19; +pub const NETLINK_RDMA: ::c_int = 20; +pub const NETLINK_CRYPTO: ::c_int = 21; +pub const NETLINK_INET_DIAG: ::c_int = NETLINK_SOCK_DIAG; + +pub const NLM_F_REQUEST: ::c_int = 1; +pub const NLM_F_MULTI: ::c_int = 2; +pub const NLM_F_ACK: ::c_int = 4; +pub const NLM_F_ECHO: ::c_int = 8; +pub const NLM_F_DUMP_INTR: ::c_int = 16; +pub const NLM_F_DUMP_FILTERED: ::c_int = 32; + +pub const NLM_F_ROOT: ::c_int = 0x100; +pub const NLM_F_MATCH: ::c_int = 0x200; +pub const NLM_F_ATOMIC: ::c_int = 0x400; +pub const NLM_F_DUMP: ::c_int = NLM_F_ROOT | NLM_F_MATCH; + +pub const NLM_F_REPLACE: ::c_int = 0x100; +pub const NLM_F_EXCL: ::c_int = 0x200; +pub const NLM_F_CREATE: ::c_int = 0x400; +pub const NLM_F_APPEND: ::c_int = 0x800; + +pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1; +pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2; +pub const NETLINK_PKTINFO: ::c_int = 3; +pub const NETLINK_BROADCAST_ERROR: ::c_int = 4; +pub const NETLINK_NO_ENOBUFS: ::c_int = 5; +pub const NETLINK_RX_RING: ::c_int = 6; +pub const NETLINK_TX_RING: ::c_int = 7; +pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; +pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; +pub const NETLINK_CAP_ACK: ::c_int = 10; + +pub const NLA_F_NESTED: ::c_int = 1 << 15; +pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; +pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); + // linux/rtnetlink.h pub const TCA_UNSPEC: ::c_ushort = 0; pub const TCA_KIND: ::c_ushort = 1; @@ -2121,6 +2179,10 @@ pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); f! { + pub fn NLA_ALIGN(len: ::c_int) -> ::c_int { + return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1) + } + pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < ::mem::size_of::() { diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs new file mode 100644 index 0000000000..c866692531 --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs @@ -0,0 +1,795 @@ +pub type c_char = u8; +pub type wchar_t = u32; +pub type stat64 = ::stat; + +s! { + + pub struct stat { + pub st_dev: ::dev_t, + pub st_ino: ::c_ulonglong, + pub st_mode: ::c_uint, + pub st_nlink: ::c_uint, + pub st_uid: ::c_uint, + pub st_gid: ::c_uint, + pub st_rdev: ::c_ulonglong, + __st_rdev_padding: ::c_ulong, + pub st_size: ::c_longlong, + pub st_blksize: ::blksize_t, + __st_blksize_padding: ::c_int, + pub st_blocks: ::blkcnt_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + + __unused: [::c_int;2], + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_flags: ::c_int, + pub ss_size: ::size_t + } + + pub struct ipc_perm { + pub __ipc_perm_key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + pub __seq: ::c_ushort, + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_atime: ::time_t, + __unused1: ::c_int, + pub shm_dtime: ::time_t, + __unused2: ::c_int, + pub shm_ctime: ::time_t, + __unused3: ::c_int, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::c_ulong, + __pad1: ::c_ulong, + __pad2: ::c_ulong, + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + pub msg_stime: ::time_t, + __unused1: ::c_int, + pub msg_rtime: ::time_t, + __unused2: ::c_int, + pub msg_ctime: ::time_t, + __unused3: ::c_int, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __pad1: ::c_ulong, + __pad2: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_ulong, + pub f_bsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_flags: ::c_ulong, + pub f_spare: [::c_ulong; 4], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_errno: ::c_int, + pub si_code: ::c_int, + pub _pad: [::c_int; 29], + _align: [usize; 0], + } + + pub struct statfs64 { + pub f_type: ::c_ulong, + pub f_bsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_flags: ::c_ulong, + pub f_spare: [::c_ulong; 4], + } + + pub struct statvfs64 { + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: u64, + pub f_bfree: u64, + pub f_bavail: u64, + pub f_files: u64, + pub f_ffree: u64, + pub f_favail: u64, + pub f_fsid: ::c_ulong, + __f_unused: ::c_int, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct termios2 { + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; 19], + pub c_ispeed: ::speed_t, + pub c_ospeed: ::speed_t, + } +} + +pub const AF_FILE: ::c_int = 1; +pub const AF_KCM: ::c_int = 41; +pub const AF_MAX: ::c_int = 43; +pub const AF_QIPCRTR: ::c_int = 42; +pub const EADDRINUSE: ::c_int = 98; +pub const EADDRNOTAVAIL: ::c_int = 99; +pub const EAFNOSUPPORT: ::c_int = 97; +pub const EALREADY: ::c_int = 114; +pub const EBADE: ::c_int = 52; +pub const EBADMSG: ::c_int = 74; +pub const EBADR: ::c_int = 53; +pub const EBADRQC: ::c_int = 56; +pub const EBADSLT: ::c_int = 57; +pub const ECANCELED: ::c_int = 125; +pub const ECHRNG: ::c_int = 44; +pub const ECONNABORTED: ::c_int = 103; +pub const ECONNREFUSED: ::c_int = 111; +pub const ECONNRESET: ::c_int = 104; +pub const EDEADLK: ::c_int = 35; +pub const EDEADLOCK: ::c_int = 35; +pub const EDESTADDRREQ: ::c_int = 89; +pub const EDQUOT: ::c_int = 122; +pub const EHOSTDOWN: ::c_int = 112; +pub const EHOSTUNREACH: ::c_int = 113; +pub const EHWPOISON: ::c_int = 133; +pub const EIDRM: ::c_int = 43; +pub const EILSEQ: ::c_int = 84; +pub const EINPROGRESS: ::c_int = 115; +pub const EISCONN: ::c_int = 106; +pub const EISNAM: ::c_int = 120; +pub const EKEYEXPIRED: ::c_int = 127; +pub const EKEYREJECTED: ::c_int = 129; +pub const EKEYREVOKED: ::c_int = 128; +pub const EL2HLT: ::c_int = 51; +pub const EL2NSYNC: ::c_int = 45; +pub const EL3HLT: ::c_int = 46; +pub const EL3RST: ::c_int = 47; +pub const ELIBACC: ::c_int = 79; +pub const ELIBBAD: ::c_int = 80; +pub const ELIBEXEC: ::c_int = 83; +pub const ELIBMAX: ::c_int = 82; +pub const ELIBSCN: ::c_int = 81; +pub const ELNRNG: ::c_int = 48; +pub const ELOOP: ::c_int = 40; +pub const EMEDIUMTYPE: ::c_int = 124; +pub const EMSGSIZE: ::c_int = 90; +pub const EMULTIHOP: ::c_int = 72; +pub const ENAMETOOLONG: ::c_int = 36; +pub const ENAVAIL: ::c_int = 119; +pub const ENETDOWN: ::c_int = 100; +pub const ENETRESET: ::c_int = 102; +pub const ENETUNREACH: ::c_int = 101; +pub const ENOANO: ::c_int = 55; +pub const ENOBUFS: ::c_int = 105; +pub const ENOCSI: ::c_int = 50; +pub const ENOKEY: ::c_int = 126; +pub const ENOLCK: ::c_int = 37; +pub const ENOMEDIUM: ::c_int = 123; +pub const ENOMSG: ::c_int = 42; +pub const ENOPROTOOPT: ::c_int = 92; +pub const ENOSYS: ::c_int = 38; +pub const ENOTCONN: ::c_int = 107; +pub const ENOTEMPTY: ::c_int = 39; +pub const ENOTNAM: ::c_int = 118; +pub const ENOTRECOVERABLE: ::c_int = 131; +pub const ENOTSOCK: ::c_int = 88; +pub const ENOTSUP: ::c_int = 95; +pub const ENOTUNIQ: ::c_int = 76; +pub const EOPNOTSUPP: ::c_int = 95; +pub const EOVERFLOW: ::c_int = 75; +pub const EOWNERDEAD: ::c_int = 130; +pub const EPFNOSUPPORT: ::c_int = 96; +pub const EREMCHG: ::c_int = 78; +pub const ERESTART: ::c_int = 85; +pub const ERFKILL: ::c_int = 132; +pub const ESHUTDOWN: ::c_int = 108; +pub const ESOCKTNOSUPPORT: ::c_int = 94; +pub const ESTALE: ::c_int = 116; +pub const ESTRPIPE: ::c_int = 86; +pub const ETOOMANYREFS: ::c_int = 109; +pub const EUCLEAN: ::c_int = 117; +pub const EUNATCH: ::c_int = 49; +pub const EUSERS: ::c_int = 87; +pub const EXFULL: ::c_int = 54; +pub const EXTPROC: ::c_int = 65536; +pub const F_EXLCK: ::c_int = 4; +pub const F_GETLK: ::c_int = 12; +pub const F_GETOWN: ::c_int = 9; +pub const F_GETOWNER_UIDS: ::c_int = 17; +pub const F_GETOWN_EX: ::c_int = 16; +pub const F_GETSIG: ::c_int = 11; +pub const FIOASYNC: ::c_int = 21586; +pub const FIOCLEX: ::c_int = 21585; +pub const FIONBIO: ::c_int = 21537; +pub const FIONCLEX: ::c_int = 21584; +pub const FIONREAD: ::c_int = 21531; +pub const FIOQSIZE: ::c_int = 21600; +pub const F_LINUX_SPECIFIC_BASE: ::c_int = 1024; +pub const FLUSHO: ::c_int = 4096; +pub const F_OFD_GETLK: ::c_int = 36; +pub const F_OFD_SETLK: ::c_int = 37; +pub const F_OFD_SETLKW: ::c_int = 38; +pub const F_OWNER_PGRP: ::c_int = 2; +pub const F_OWNER_PID: ::c_int = 1; +pub const F_OWNER_TID: ::c_int = 0; +pub const F_SETLK: ::c_int = 13; +pub const F_SETLKW: ::c_int = 14; +pub const F_SETOWN: ::c_int = 8; +pub const F_SETOWN_EX: ::c_int = 15; +pub const F_SETSIG: ::c_int = 10; +pub const F_SHLCK: ::c_int = 8; +pub const IEXTEN: ::c_int = 32768; +pub const MAP_ANON: ::c_int = 32; +pub const MAP_DENYWRITE: ::c_int = 2048; +pub const MAP_EXECUTABLE: ::c_int = 4096; +pub const MAP_GROWSDOWN: ::c_int = 256; +pub const MAP_HUGE_MASK: ::c_int = 63; +pub const MAP_HUGE_SHIFT: ::c_int = 26; +pub const MAP_HUGETLB: ::c_int = 262144; +pub const MAP_LOCKED: ::c_int = 8192; +pub const MAP_NONBLOCK: ::c_int = 65536; +pub const MAP_NORESERVE: ::c_int = 16384; +pub const MAP_POPULATE: ::c_int = 32768; +pub const MAP_STACK: ::c_int = 131072; +pub const MAP_UNINITIALIZED: ::c_int = 0; +pub const O_APPEND: ::c_int = 1024; +pub const O_ASYNC: ::c_int = 8192; +pub const O_CREAT: ::c_int = 64; +pub const O_DIRECT: ::c_int = 16384; +pub const O_DIRECTORY: ::c_int = 65536; +pub const O_DSYNC: ::c_int = 4096; +pub const O_EXCL: ::c_int = 128; +pub const O_LARGEFILE: ::c_int = 32768; +pub const O_NOCTTY: ::c_int = 256; +pub const O_NOFOLLOW: ::c_int = 131072; +pub const O_NONBLOCK: ::c_int = 2048; +pub const O_SYNC: ::c_int = 1052672; +pub const PF_FILE: ::c_int = 1; +pub const PF_KCM: ::c_int = 41; +pub const PF_MAX: ::c_int = 43; +pub const PF_QIPCRTR: ::c_int = 42; +pub const RLIMIT_AS: ::c_int = 9; +pub const RLIMIT_MEMLOCK: ::c_int = 8; +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 6; +pub const RLIMIT_RSS: ::c_int = 5; +pub const RLIM_NLIMITS: ::c_int = 16; +pub const SA_ONSTACK: ::c_int = 0x08000000; +pub const SA_SIGINFO: ::c_int = 0x00000004; +pub const SA_NOCLDWAIT: ::c_int = 0x00000002; +pub const SIGBUS: ::c_int = 7; +pub const SIGCHLD: ::c_int = 17; +pub const SIGCONT: ::c_int = 18; +pub const SIGIO: ::c_int = 29; +pub const SIGPOLL: ::c_int = 29; +pub const SIGPROF: ::c_int = 27; +pub const SIGPWR: ::c_int = 30; +pub const SIGSTKFLT: ::c_int = 16; +pub const SIGSTOP: ::c_int = 19; +pub const SIGSYS: ::c_int = 31; +pub const SIGTSTP: ::c_int = 20; +pub const SIGTTIN: ::c_int = 21; +pub const SIGTTOU: ::c_int = 22; +pub const SIGURG: ::c_int = 23; +pub const SIGUSR1: ::c_int = 10; +pub const SIGUSR2: ::c_int = 12; +pub const SIGVTALRM: ::c_int = 26; +pub const SIGWINCH: ::c_int = 28; +pub const SIGXCPU: ::c_int = 24; +pub const SIGXFSZ: ::c_int = 25; +pub const SIG_SETMASK: ::c_int = 2; // FIXME check these +pub const SIG_BLOCK: ::c_int = 0x000000; +pub const SIG_UNBLOCK: ::c_int = 0x01; +pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_ATTACH_BPF: ::c_int = 50; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; +pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; +pub const SO_BROADCAST: ::c_int = 6; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SOCK_DGRAM: ::c_int = 2; +pub const SOCK_NONBLOCK: ::c_int = 2048; +pub const SOCK_SEQPACKET: ::c_int = 5; +pub const SOCK_STREAM: ::c_int = 1; +pub const SO_CNX_ADVICE: ::c_int = 53; +pub const SO_DETACH_BPF: ::c_int = 27; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_DONTROUTE: ::c_int = 5; +pub const SO_ERROR: ::c_int = 4; +pub const SO_GET_FILTER: ::c_int = 26; +pub const SO_INCOMING_CPU: ::c_int = 49; +pub const SO_KEEPALIVE: ::c_int = 9; +pub const SOL_CAIF: ::c_int = 278; +pub const SO_LINGER: ::c_int = 13; +pub const SOL_IUCV: ::c_int = 277; +pub const SOL_KCM: ::c_int = 281; +pub const SOL_NFC: ::c_int = 280; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SOL_PNPIPE: ::c_int = 275; +pub const SOL_PPPOL2TP: ::c_int = 273; +pub const SOL_RDS: ::c_int = 276; +pub const SOL_RXRPC: ::c_int = 272; +pub const SOL_SOCKET: ::c_int = 1; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_OOBINLINE: ::c_int = 10; +pub const SO_PASSCRED: ::c_int = 16; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_PEERCRED: ::c_int = 17; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_PEERSEC: ::c_int = 31; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_RCVBUF: ::c_int = 8; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_RCVLOWAT: ::c_int = 18; +pub const SO_RCVTIMEO: ::c_int = 20; +pub const SO_REUSEADDR: ::c_int = 2; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_SNDBUF: ::c_int = 7; +pub const SO_SNDBUFFORCE: ::c_int = 32; +pub const SO_SNDLOWAT: ::c_int = 19; +pub const SO_SNDTIMEO: ::c_int = 21; +pub const SO_TYPE: ::c_int = 3; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SYS3264_fadvise64: ::c_int = 223; +pub const SYS3264_fcntl: ::c_int = 25; +pub const SYS3264_fstatat: ::c_int = 79; +pub const SYS3264_fstat: ::c_int = 80; +pub const SYS3264_fstatfs: ::c_int = 44; +pub const SYS3264_ftruncate: ::c_int = 46; +pub const SYS3264_lseek: ::c_int = 62; +pub const SYS3264_lstat: ::c_int = 1039; +pub const SYS3264_mmap: ::c_int = 222; +pub const SYS3264_sendfile: ::c_int = 71; +pub const SYS3264_stat: ::c_int = 1038; +pub const SYS3264_statfs: ::c_int = 43; +pub const SYS3264_truncate: ::c_int = 45; +pub const SYS_accept4: ::c_int = 242; +pub const SYS_accept: ::c_int = 202; +pub const SYS_access: ::c_int = 1033; +pub const SYS_acct: ::c_int = 89; +pub const SYS_add_key: ::c_int = 217; +pub const SYS_adjtimex: ::c_int = 171; +pub const SYS_alarm: ::c_int = 1059; +pub const SYS_arch_specific_syscall: ::c_int = 244; +pub const SYS_bdflush: ::c_int = 1075; +pub const SYS_bind: ::c_int = 200; +pub const SYS_bpf: ::c_int = 280; +pub const SYS_brk: ::c_int = 214; +pub const SYS_capget: ::c_int = 90; +pub const SYS_capset: ::c_int = 91; +pub const SYS_chdir: ::c_int = 49; +pub const SYS_chmod: ::c_int = 1028; +pub const SYS_chown: ::c_int = 1029; +pub const SYS_chroot: ::c_int = 51; +pub const SYS_clock_adjtime: ::c_int = 266; +pub const SYS_clock_getres: ::c_int = 114; +pub const SYS_clock_gettime: ::c_int = 113; +pub const SYS_clock_nanosleep: ::c_int = 115; +pub const SYS_clock_settime: ::c_int = 112; +pub const SYS_clone: ::c_int = 220; +pub const SYS_close: ::c_int = 57; +pub const SYS_connect: ::c_int = 203; +pub const SYS_copy_file_range: ::c_int = -1; // FIXME +pub const SYS_creat: ::c_int = 1064; +pub const SYS_delete_module: ::c_int = 106; +pub const SYS_dup2: ::c_int = 1041; +pub const SYS_dup3: ::c_int = 24; +pub const SYS_dup: ::c_int = 23; +pub const SYS_epoll_create1: ::c_int = 20; +pub const SYS_epoll_create: ::c_int = 1042; +pub const SYS_epoll_ctl: ::c_int = 21; +pub const SYS_epoll_pwait: ::c_int = 22; +pub const SYS_epoll_wait: ::c_int = 1069; +pub const SYS_eventfd2: ::c_int = 19; +pub const SYS_eventfd: ::c_int = 1044; +pub const SYS_execveat: ::c_int = 281; +pub const SYS_execve: ::c_int = 221; +pub const SYS_exit: ::c_int = 93; +pub const SYS_exit_group: ::c_int = 94; +pub const SYS_faccessat: ::c_int = 48; +pub const SYS_fadvise64_64: ::c_int = 223; +pub const SYS_fallocate: ::c_int = 47; +pub const SYS_fanotify_init: ::c_int = 262; +pub const SYS_fanotify_mark: ::c_int = 263; +pub const SYS_fchdir: ::c_int = 50; +pub const SYS_fchmodat: ::c_int = 53; +pub const SYS_fchmod: ::c_int = 52; +pub const SYS_fchownat: ::c_int = 54; +pub const SYS_fchown: ::c_int = 55; +pub const SYS_fcntl64: ::c_int = 25; +pub const SYS_fcntl: ::c_int = 25; +pub const SYS_fdatasync: ::c_int = 83; +pub const SYS_fgetxattr: ::c_int = 10; +pub const SYS_finit_module: ::c_int = 273; +pub const SYS_flistxattr: ::c_int = 13; +pub const SYS_flock: ::c_int = 32; +pub const SYS_fork: ::c_int = 1079; +pub const SYS_fremovexattr: ::c_int = 16; +pub const SYS_fsetxattr: ::c_int = 7; +pub const SYS_fstat64: ::c_int = 80; +pub const SYS_fstatat64: ::c_int = 79; +pub const SYS_fstatfs64: ::c_int = 44; +pub const SYS_fstatfs: ::c_int = 44; +pub const SYS_fsync: ::c_int = 82; +pub const SYS_ftruncate64: ::c_int = 46; +pub const SYS_ftruncate: ::c_int = 46; +pub const SYS_futex: ::c_int = 98; +pub const SYS_futimesat: ::c_int = 1066; +pub const SYS_getcpu: ::c_int = 168; +pub const SYS_getcwd: ::c_int = 17; +pub const SYS_getdents64: ::c_int = 61; +pub const SYS_getdents: ::c_int = 1065; +pub const SYS_getegid: ::c_int = 177; +pub const SYS_geteuid: ::c_int = 175; +pub const SYS_getgid: ::c_int = 176; +pub const SYS_getgroups: ::c_int = 158; +pub const SYS_getitimer: ::c_int = 102; +pub const SYS_get_mempolicy: ::c_int = 236; +pub const SYS_getpeername: ::c_int = 205; +pub const SYS_getpgid: ::c_int = 155; +pub const SYS_getpgrp: ::c_int = 1060; +pub const SYS_getpid: ::c_int = 172; +pub const SYS_getppid: ::c_int = 173; +pub const SYS_getpriority: ::c_int = 141; +pub const SYS_getrandom: ::c_int = 278; +pub const SYS_getresgid: ::c_int = 150; +pub const SYS_getresuid: ::c_int = 148; +pub const SYS_getrlimit: ::c_int = 163; +pub const SYS_get_robust_list: ::c_int = 100; +pub const SYS_getrusage: ::c_int = 165; +pub const SYS_getsid: ::c_int = 156; +pub const SYS_getsockname: ::c_int = 204; +pub const SYS_getsockopt: ::c_int = 209; +pub const SYS_gettid: ::c_int = 178; +pub const SYS_gettimeofday: ::c_int = 169; +pub const SYS_getuid: ::c_int = 174; +pub const SYS_getxattr: ::c_int = 8; +pub const SYS_init_module: ::c_int = 105; +pub const SYS_inotify_add_watch: ::c_int = 27; +pub const SYS_inotify_init1: ::c_int = 26; +pub const SYS_inotify_init: ::c_int = 1043; +pub const SYS_inotify_rm_watch: ::c_int = 28; +pub const SYS_io_cancel: ::c_int = 3; +pub const SYS_ioctl: ::c_int = 29; +pub const SYS_io_destroy: ::c_int = 1; +pub const SYS_io_getevents: ::c_int = 4; +pub const SYS_ioprio_get: ::c_int = 31; +pub const SYS_ioprio_set: ::c_int = 30; +pub const SYS_io_setup: ::c_int = 0; +pub const SYS_io_submit: ::c_int = 2; +pub const SYS_kcmp: ::c_int = 272; +pub const SYS_kexec_load: ::c_int = 104; +pub const SYS_keyctl: ::c_int = 219; +pub const SYS_kill: ::c_int = 129; +pub const SYS_lchown: ::c_int = 1032; +pub const SYS_lgetxattr: ::c_int = 9; +pub const SYS_linkat: ::c_int = 37; +pub const SYS_link: ::c_int = 1025; +pub const SYS_listen: ::c_int = 201; +pub const SYS_listxattr: ::c_int = 11; +pub const SYS_llistxattr: ::c_int = 12; +pub const SYS__llseek: ::c_int = 62; +pub const SYS_lookup_dcookie: ::c_int = 18; +pub const SYS_lremovexattr: ::c_int = 15; +pub const SYS_lseek: ::c_int = 62; +pub const SYS_lsetxattr: ::c_int = 6; +pub const SYS_lstat64: ::c_int = 1039; +pub const SYS_lstat: ::c_int = 1039; +pub const SYS_madvise: ::c_int = 233; +pub const SYS_mbind: ::c_int = 235; +pub const SYS_memfd_create: ::c_int = 279; +pub const SYS_migrate_pages: ::c_int = 238; +pub const SYS_mincore: ::c_int = 232; +pub const SYS_mkdirat: ::c_int = 34; +pub const SYS_mkdir: ::c_int = 1030; +pub const SYS_mknodat: ::c_int = 33; +pub const SYS_mknod: ::c_int = 1027; +pub const SYS_mlockall: ::c_int = 230; +pub const SYS_mlock: ::c_int = 228; +pub const SYS_mmap2: ::c_int = 222; +pub const SYS_mount: ::c_int = 40; +pub const SYS_move_pages: ::c_int = 239; +pub const SYS_mprotect: ::c_int = 226; +pub const SYS_mq_getsetattr: ::c_int = 185; +pub const SYS_mq_notify: ::c_int = 184; +pub const SYS_mq_open: ::c_int = 180; +pub const SYS_mq_timedreceive: ::c_int = 183; +pub const SYS_mq_timedsend: ::c_int = 182; +pub const SYS_mq_unlink: ::c_int = 181; +pub const SYS_mremap: ::c_int = 216; +pub const SYS_msgctl: ::c_int = 187; +pub const SYS_msgget: ::c_int = 186; +pub const SYS_msgrcv: ::c_int = 188; +pub const SYS_msgsnd: ::c_int = 189; +pub const SYS_msync: ::c_int = 227; +pub const SYS_munlockall: ::c_int = 231; +pub const SYS_munlock: ::c_int = 229; +pub const SYS_munmap: ::c_int = 215; +pub const SYS_name_to_handle_at: ::c_int = 264; +pub const SYS_nanosleep: ::c_int = 101; +pub const SYS_newfstatat: ::c_int = 79; +pub const SYS_nfsservctl: ::c_int = 42; +pub const SYS_oldwait4: ::c_int = 1072; +pub const SYS_openat: ::c_int = 56; +pub const SYS_open_by_handle_at: ::c_int = 265; +pub const SYS_open: ::c_int = 1024; +pub const SYS_pause: ::c_int = 1061; +pub const SYS_perf_event_open: ::c_int = 241; +pub const SYS_personality: ::c_int = 92; +pub const SYS_pipe2: ::c_int = 59; +pub const SYS_pipe: ::c_int = 1040; +pub const SYS_pivot_root: ::c_int = 41; +pub const SYS_poll: ::c_int = 1068; +pub const SYS_ppoll: ::c_int = 73; +pub const SYS_prctl: ::c_int = 167; +pub const SYS_pread64: ::c_int = 67; +pub const SYS_preadv: ::c_int = 69; +pub const SYS_prlimit64: ::c_int = 261; +pub const SYS_process_vm_readv: ::c_int = 270; +pub const SYS_process_vm_writev: ::c_int = 271; +pub const SYS_pselect6: ::c_int = 72; +pub const SYS_ptrace: ::c_int = 117; +pub const SYS_pwrite64: ::c_int = 68; +pub const SYS_pwritev: ::c_int = 70; +pub const SYS_quotactl: ::c_int = 60; +pub const SYS_readahead: ::c_int = 213; +pub const SYS_read: ::c_int = 63; +pub const SYS_readlinkat: ::c_int = 78; +pub const SYS_readlink: ::c_int = 1035; +pub const SYS_readv: ::c_int = 65; +pub const SYS_reboot: ::c_int = 142; +pub const SYS_recv: ::c_int = 1073; +pub const SYS_recvfrom: ::c_int = 207; +pub const SYS_recvmmsg: ::c_int = 243; +pub const SYS_recvmsg: ::c_int = 212; +pub const SYS_remap_file_pages: ::c_int = 234; +pub const SYS_removexattr: ::c_int = 14; +pub const SYS_renameat2: ::c_int = 276; +pub const SYS_renameat: ::c_int = 38; +pub const SYS_rename: ::c_int = 1034; +pub const SYS_request_key: ::c_int = 218; +pub const SYS_restart_syscall: ::c_int = 128; +pub const SYS_rmdir: ::c_int = 1031; +pub const SYS_rt_sigaction: ::c_int = 134; +pub const SYS_rt_sigpending: ::c_int = 136; +pub const SYS_rt_sigprocmask: ::c_int = 135; +pub const SYS_rt_sigqueueinfo: ::c_int = 138; +pub const SYS_rt_sigreturn: ::c_int = 139; +pub const SYS_rt_sigsuspend: ::c_int = 133; +pub const SYS_rt_sigtimedwait: ::c_int = 137; +pub const SYS_rt_tgsigqueueinfo: ::c_int = 240; +pub const SYS_sched_getaffinity: ::c_int = 123; +pub const SYS_sched_getattr: ::c_int = 275; +pub const SYS_sched_getparam: ::c_int = 121; +pub const SYS_sched_get_priority_max: ::c_int = 125; +pub const SYS_sched_get_priority_min: ::c_int = 126; +pub const SYS_sched_getscheduler: ::c_int = 120; +pub const SYS_sched_rr_get_interval: ::c_int = 127; +pub const SYS_sched_setaffinity: ::c_int = 122; +pub const SYS_sched_setattr: ::c_int = 274; +pub const SYS_sched_setparam: ::c_int = 118; +pub const SYS_sched_setscheduler: ::c_int = 119; +pub const SYS_sched_yield: ::c_int = 124; +pub const SYS_seccomp: ::c_int = 277; +pub const SYS_select: ::c_int = 1067; +pub const SYS_semctl: ::c_int = 191; +pub const SYS_semget: ::c_int = 190; +pub const SYS_semop: ::c_int = 193; +pub const SYS_semtimedop: ::c_int = 192; +pub const SYS_send: ::c_int = 1074; +pub const SYS_sendfile64: ::c_int = 71; +pub const SYS_sendfile: ::c_int = 71; +pub const SYS_sendmmsg: ::c_int = 269; +pub const SYS_sendmsg: ::c_int = 211; +pub const SYS_sendto: ::c_int = 206; +pub const SYS_setdomainname: ::c_int = 162; +pub const SYS_setfsgid: ::c_int = 152; +pub const SYS_setfsuid: ::c_int = 151; +pub const SYS_setgid: ::c_int = 144; +pub const SYS_setgroups: ::c_int = 159; +pub const SYS_sethostname: ::c_int = 161; +pub const SYS_setitimer: ::c_int = 103; +pub const SYS_set_mempolicy: ::c_int = 237; +pub const SYS_setns: ::c_int = 268; +pub const SYS_setpgid: ::c_int = 154; +pub const SYS_setpriority: ::c_int = 140; +pub const SYS_setregid: ::c_int = 143; +pub const SYS_setresgid: ::c_int = 149; +pub const SYS_setresuid: ::c_int = 147; +pub const SYS_setreuid: ::c_int = 145; +pub const SYS_setrlimit: ::c_int = 164; +pub const SYS_set_robust_list: ::c_int = 99; +pub const SYS_setsid: ::c_int = 157; +pub const SYS_setsockopt: ::c_int = 208; +pub const SYS_set_tid_address: ::c_int = 96; +pub const SYS_settimeofday: ::c_int = 170; +pub const SYS_setuid: ::c_int = 146; +pub const SYS_setxattr: ::c_int = 5; +pub const SYS_shmat: ::c_int = 196; +pub const SYS_shmctl: ::c_int = 195; +pub const SYS_shmdt: ::c_int = 197; +pub const SYS_shmget: ::c_int = 194; +pub const SYS_shutdown: ::c_int = 210; +pub const SYS_sigaltstack: ::c_int = 132; +pub const SYS_signalfd4: ::c_int = 74; +pub const SYS_signalfd: ::c_int = 1045; +pub const SYS_socket: ::c_int = 198; +pub const SYS_socketpair: ::c_int = 199; +pub const SYS_splice: ::c_int = 76; +pub const SYS_stat64: ::c_int = 1038; +pub const SYS_stat: ::c_int = 1038; +pub const SYS_statfs64: ::c_int = 43; +pub const SYS_swapoff: ::c_int = 225; +pub const SYS_swapon: ::c_int = 224; +pub const SYS_symlinkat: ::c_int = 36; +pub const SYS_symlink: ::c_int = 1036; +pub const SYS_sync: ::c_int = 81; +pub const SYS_sync_file_range2: ::c_int = 84; +pub const SYS_sync_file_range: ::c_int = 84; +pub const SYS_syncfs: ::c_int = 267; +pub const SYS_syscalls: ::c_int = 1080; +pub const SYS__sysctl: ::c_int = 1078; +pub const SYS_sysinfo: ::c_int = 179; +pub const SYS_syslog: ::c_int = 116; +pub const SYS_tee: ::c_int = 77; +pub const SYS_tgkill: ::c_int = 131; +pub const SYS_time: ::c_int = 1062; +pub const SYS_timer_create: ::c_int = 107; +pub const SYS_timer_delete: ::c_int = 111; +pub const SYS_timerfd_create: ::c_int = 85; +pub const SYS_timerfd_gettime: ::c_int = 87; +pub const SYS_timerfd_settime: ::c_int = 86; +pub const SYS_timer_getoverrun: ::c_int = 109; +pub const SYS_timer_gettime: ::c_int = 108; +pub const SYS_timer_settime: ::c_int = 110; +pub const SYS_times: ::c_int = 153; +pub const SYS_tkill: ::c_int = 130; +pub const SYS_truncate64: ::c_int = 45; +pub const SYS_truncate: ::c_int = 45; +pub const SYS_umask: ::c_int = 166; +pub const SYS_umount2: ::c_int = 39; +pub const SYS_umount: ::c_int = 1076; +pub const SYS_uname: ::c_int = 160; +pub const SYS_unlinkat: ::c_int = 35; +pub const SYS_unlink: ::c_int = 1026; +pub const SYS_unshare: ::c_int = 97; +pub const SYS_uselib: ::c_int = 1077; +pub const SYS_ustat: ::c_int = 1070; +pub const SYS_utime: ::c_int = 1063; +pub const SYS_utimensat: ::c_int = 88; +pub const SYS_utimes: ::c_int = 1037; +pub const SYS_vfork: ::c_int = 1071; +pub const SYS_vhangup: ::c_int = 58; +pub const SYS_vmsplice: ::c_int = 75; +pub const SYS_wait4: ::c_int = 260; +pub const SYS_waitid: ::c_int = 95; +pub const SYS_write: ::c_int = 64; +pub const SYS_writev: ::c_int = 66; +pub const TCFLSH: ::c_int = 21515; +pub const TCGETA: ::c_int = 21509; +pub const TCGETS: ::c_int = 21505; +pub const TCGETX: ::c_int = 21554; +pub const TCSBRK: ::c_int = 21513; +pub const TCSBRKP: ::c_int = 21541; +pub const TCSETA: ::c_int = 21510; +pub const TCSETAF: ::c_int = 21512; +pub const TCSETAW: ::c_int = 21511; +pub const TCSETS: ::c_int = 21506; +pub const TCSETSF: ::c_int = 21508; +pub const TCSETSW: ::c_int = 21507; +pub const TCSETX: ::c_int = 21555; +pub const TCSETXF: ::c_int = 21556; +pub const TCSETXW: ::c_int = 21557; +pub const TCXONC: ::c_int = 21514; +pub const TIOCCBRK: ::c_int = 21544; +pub const TIOCCONS: ::c_int = 21533; +pub const TIOCEXCL: ::c_int = 21516; +pub const TIOCGETD: ::c_int = 21540; +pub const TIOCGICOUNT: ::c_int = 21597; +pub const TIOCGLCKTRMIOS: ::c_int = 21590; +pub const TIOCGPGRP: ::c_int = 21519; +pub const TIOCGRS485: ::c_int = 21550; +pub const TIOCGSERIAL: ::c_int = 21534; +pub const TIOCGSID: ::c_int = 21545; +pub const TIOCGSOFTCAR: ::c_int = 21529; +pub const TIOCGWINSZ: ::c_int = 21523; +pub const TIOCLINUX: ::c_int = 21532; +pub const TIOCMBIC: ::c_int = 21527; +pub const TIOCMBIS: ::c_int = 21526; +pub const TIOCM_CAR: ::c_int = 64; +pub const TIOCM_CD: ::c_int = 64; +pub const TIOCM_CTS: ::c_int = 32; +pub const TIOCM_DSR: ::c_int = 256; +pub const TIOCM_DTR: ::c_int = 2; +pub const TIOCMGET: ::c_int = 21525; +pub const TIOCMIWAIT: ::c_int = 21596; +pub const TIOCM_LE: ::c_int = 1; +pub const TIOCM_LOOP: ::c_int = 32768; +pub const TIOCM_OUT1: ::c_int = 8192; +pub const TIOCM_OUT2: ::c_int = 16384; +pub const TIOCM_RI: ::c_int = 128; +pub const TIOCM_RNG: ::c_int = 128; +pub const TIOCM_RTS: ::c_int = 4; +pub const TIOCMSET: ::c_int = 21528; +pub const TIOCM_SR: ::c_int = 16; +pub const TIOCM_ST: ::c_int = 8; +pub const TIOCNOTTY: ::c_int = 21538; +pub const TIOCNXCL: ::c_int = 21517; +pub const TIOCOUTQ: ::c_int = 21521; +pub const TIOCPKT: ::c_int = 21536; +pub const TIOCPKT_DATA: ::c_int = 0; +pub const TIOCPKT_DOSTOP: ::c_int = 32; +pub const TIOCPKT_FLUSHREAD: ::c_int = 1; +pub const TIOCPKT_FLUSHWRITE: ::c_int = 2; +pub const TIOCPKT_IOCTL: ::c_int = 64; +pub const TIOCPKT_NOSTOP: ::c_int = 16; +pub const TIOCPKT_START: ::c_int = 8; +pub const TIOCPKT_STOP: ::c_int = 4; +pub const TIOCSBRK: ::c_int = 21543; +pub const TIOCSCTTY: ::c_int = 21518; +pub const TIOCSERCONFIG: ::c_int = 21587; +pub const TIOCSERGETLSR: ::c_int = 21593; +pub const TIOCSERGETMULTI: ::c_int = 21594; +pub const TIOCSERGSTRUCT: ::c_int = 21592; +pub const TIOCSERGWILD: ::c_int = 21588; +pub const TIOCSERSETMULTI: ::c_int = 21595; +pub const TIOCSERSWILD: ::c_int = 21589; +pub const TIOCSER_TEMT: ::c_int = 1; +pub const TIOCSETD: ::c_int = 21539; +pub const TIOCSLCKTRMIOS: ::c_int = 21591; +pub const TIOCSPGRP: ::c_int = 21520; +pub const TIOCSRS485: ::c_int = 21551; +pub const TIOCSSERIAL: ::c_int = 21535; +pub const TIOCSSOFTCAR: ::c_int = 21530; +pub const TIOCSTI: ::c_int = 21522; +pub const TIOCSWINSZ: ::c_int = 21524; +pub const TIOCVHANGUP: ::c_int = 21559; +pub const TOSTOP: ::c_int = 256; +pub const VEOF: ::c_int = 4; +pub const VEOL2: ::c_int = 16; +pub const VEOL: ::c_int = 11; +pub const VMIN: ::c_int = 6; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs index 4128a8e4da..0de23257a7 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs @@ -56,6 +56,9 @@ cfg_if! { } else if #[cfg(any(target_arch = "powerpc"))] { mod powerpc; pub use self::powerpc::*; + } else if #[cfg(any(target_arch = "hexagon"))] { + mod hexagon; + pub use self::hexagon::*; } else { // Unknown target_arch } diff --git a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs index 46a50e4953..e47af4f280 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs @@ -414,8 +414,9 @@ cfg_if! { pub use self::b64::*; } else if #[cfg(any(target_arch = "x86", target_arch = "mips", - target_arch = "arm", - target_arch = "powerpc"))] { + target_arch = "powerpc", + target_arch = "hexagon", + target_arch = "arm"))] { mod b32; pub use self::b32::*; } else { } diff --git a/vendor/libc/src/unix/linux_like/mod.rs b/vendor/libc/src/unix/linux_like/mod.rs index ad20dbeee8..a6d1d5a33c 100644 --- a/vendor/libc/src/unix/linux_like/mod.rs +++ b/vendor/libc/src/unix/linux_like/mod.rs @@ -805,6 +805,7 @@ pub const IP_TTL: ::c_int = 2; pub const IP_HDRINCL: ::c_int = 3; pub const IP_PKTINFO: ::c_int = 8; pub const IP_RECVTOS: ::c_int = 13; +pub const IP_RECVERR: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 35; pub const IP_DROP_MEMBERSHIP: ::c_int = 36; pub const IP_TRANSPARENT: ::c_int = 19; diff --git a/vendor/libc/src/unix/mod.rs b/vendor/libc/src/unix/mod.rs index 8295dfc020..721d241164 100644 --- a/vendor/libc/src/unix/mod.rs +++ b/vendor/libc/src/unix/mod.rs @@ -567,7 +567,7 @@ extern { #[cfg_attr(target_os = "macos", link_name = "fstat$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "fstat@FBSD_1.0" )] pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; @@ -577,7 +577,7 @@ extern { #[cfg_attr(target_os = "macos", link_name = "stat$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__stat50")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "stat@FBSD_1.0" )] pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; @@ -605,33 +605,13 @@ extern { #[cfg_attr(target_os = "netbsd", link_name = "__opendir30")] pub fn opendir(dirname: *const c_char) -> *mut ::DIR; - #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"), - link_name = "fdopendir$INODE64")] - #[cfg_attr(all(target_os = "macos", target_arch = "x86"), - link_name = "fdopendir$INODE64$UNIX2003")] - pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; - #[cfg_attr(target_os = "macos", link_name = "readdir$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__readdir30")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "readdir@FBSD_1.0" )] pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; - #[cfg_attr(target_os = "macos", link_name = "readdir_r$INODE64")] - #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")] - #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), - link_name = "readdir_r@FBSD_1.0" - )] - /// The 64-bit libc on Solaris and illumos only has readdir_r. If a - /// 32-bit Solaris or illumos target is ever created, it should use - /// __posix_readdir_r. See libc(3LIB) on Solaris or illumos: - /// https://illumos.org/man/3lib/libc - /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html - /// https://www.unix.com/man-page/opensolaris/3LIB/libc/ - pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, - result: *mut *mut ::dirent) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "closedir$UNIX2003")] pub fn closedir(dirp: *mut ::DIR) -> ::c_int; @@ -641,8 +621,6 @@ extern { link_name = "rewinddir$INODE64$UNIX2003")] pub fn rewinddir(dirp: *mut ::DIR); - pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, - flags: ::c_int, ...) -> ::c_int; pub fn fchmodat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, flags: ::c_int) -> ::c_int; pub fn fchown(fd: ::c_int, @@ -653,7 +631,7 @@ extern { flags: ::c_int) -> ::c_int; #[cfg_attr(target_os = "macos", link_name = "fstatat$INODE64")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "fstatat@FBSD_1.1" )] pub fn fstatat(dirfd: ::c_int, pathname: *const ::c_char, @@ -661,10 +639,6 @@ extern { pub fn linkat(olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, - mode: ::mode_t) -> ::c_int; - pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char, - buf: *mut ::c_char, bufsiz: ::size_t) -> ::ssize_t; pub fn renameat(olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char) -> ::c_int; @@ -725,9 +699,6 @@ extern { pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; - #[cfg_attr(all(target_os = "macos", target_arch = "x86"), - link_name = "pause$UNIX2003")] - pub fn pause() -> ::c_int; pub fn pipe(fds: *mut ::c_int) -> ::c_int; pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, @@ -815,7 +786,7 @@ extern { #[cfg_attr(target_os = "macos", link_name = "lstat$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "lstat@FBSD_1.0" )] pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; @@ -836,7 +807,6 @@ extern { pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; - pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t; @@ -992,7 +962,7 @@ extern { #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] #[cfg_attr( - all(target_os = "freebsd", not(freebsd12)), + all(target_os = "freebsd", freebsd11), link_name = "mknod@FBSD_1.0" )] pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, @@ -1071,8 +1041,6 @@ extern { #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")] pub fn timegm(tm: *mut ::tm) -> time_t; - pub fn getsid(pid: pid_t) -> pid_t; - pub fn sysconf(name: ::c_int) -> ::c_long; pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; @@ -1131,6 +1099,48 @@ extern { stream: *mut FILE) -> ssize_t; } +cfg_if! { + if #[cfg(not(target_os = "redox"))] { + extern { + pub fn getsid(pid: pid_t) -> pid_t; + pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "pause$UNIX2003")] + pub fn pause() -> ::c_int; + + pub fn readlinkat(dirfd: ::c_int, + pathname: *const ::c_char, + buf: *mut ::c_char, + bufsiz: ::size_t) -> ::ssize_t; + pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, + mode: ::mode_t) -> ::c_int; + pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, + flags: ::c_int, ...) -> ::c_int; + + #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"), + link_name = "fdopendir$INODE64")] + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "fdopendir$INODE64$UNIX2003")] + pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; + + #[cfg_attr(target_os = "macos", link_name = "readdir_r$INODE64")] + #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")] + #[cfg_attr( + all(target_os = "freebsd", freebsd11), + link_name = "readdir_r@FBSD_1.0" + )] + /// The 64-bit libc on Solaris and illumos only has readdir_r. If a + /// 32-bit Solaris or illumos target is ever created, it should use + /// __posix_readdir_r. See libc(3LIB) on Solaris or illumos: + /// https://illumos.org/man/3lib/libc + /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html + /// https://www.unix.com/man-page/opensolaris/3LIB/libc/ + pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, + result: *mut *mut ::dirent) -> ::c_int; + } + } +} + cfg_if! { if #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] { extern { diff --git a/vendor/libc/src/unix/redox/mod.rs b/vendor/libc/src/unix/redox/mod.rs index 121bb63a66..2591a7938a 100644 --- a/vendor/libc/src/unix/redox/mod.rs +++ b/vendor/libc/src/unix/redox/mod.rs @@ -36,6 +36,49 @@ pub type suseconds_t = ::c_int; pub type tcflag_t = u32; pub type time_t = ::c_long; +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum timezone {} +impl ::Copy for timezone {} +impl ::Clone for timezone { + fn clone(&self) -> timezone { *self } +} + +s_no_extra_traits! { + #[repr(C)] + pub struct utsname { + pub sysname: [::c_char; UTSLENGTH], + pub nodename: [::c_char; UTSLENGTH], + pub release: [::c_char; UTSLENGTH], + pub version: [::c_char; UTSLENGTH], + pub machine: [::c_char; UTSLENGTH], + pub domainname: [::c_char; UTSLENGTH], + } + + pub struct dirent { + pub d_ino: ::ino_t, + pub d_off: ::off_t, + pub d_reclen: ::c_ushort, + pub d_type: ::c_uchar, + pub d_name: [::c_char; 256], + } + + pub struct sockaddr_un { + pub sun_family: ::sa_family_t, + pub sun_path: [::c_char; 108] + } + + pub struct sockaddr_storage { + pub ss_family: ::sa_family_t, + __ss_padding: [ + u8; + 128 - + ::core::mem::size_of::() - + ::core::mem::size_of::() + ], + __ss_align: ::c_ulong, + } +} + s! { pub struct addrinfo { pub ai_flags: ::c_int, @@ -48,14 +91,6 @@ s! { pub ai_next: *mut ::addrinfo, } - pub struct dirent { - pub d_ino: ::ino_t, - pub d_off: ::off_t, - pub d_reclen: ::c_ushort, - pub d_type: ::c_uchar, - pub d_name: [::c_char; 256], - } - pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, @@ -140,22 +175,6 @@ s! { pub sin6_scope_id: u32, } - pub struct sockaddr_storage { - pub ss_family: ::sa_family_t, - __ss_padding: [ - u8; - 128 - - ::core::mem::size_of::() - - ::core::mem::size_of::() - ], - __ss_align: ::c_ulong, - } - - pub struct sockaddr_un { - pub sun_family: ::sa_family_t, - pub sun_path: [::c_char; 108] - } - pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, @@ -216,63 +235,175 @@ s! { } } +pub const UTSLENGTH: usize = 65; + +// intentionally not public, only used for fd_set +cfg_if! { + if #[cfg(target_pointer_width = "32")] { + const ULONG_SIZE: usize = 32; + } else if #[cfg(target_pointer_width = "64")] { + const ULONG_SIZE: usize = 64; + } else { + // Unknown target_pointer_width + } +} + +// limits.h +pub const PATH_MAX: ::c_int = 4096; + +// fcntl.h +pub const F_GETLK: ::c_int = 5; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + // TODO: relibc { - pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; +pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; // } // dlfcn.h - pub const RTLD_LAZY: ::c_int = 0x0001; pub const RTLD_NOW: ::c_int = 0x0002; pub const RTLD_GLOBAL: ::c_int = 0x0100; pub const RTLD_LOCAL: ::c_int = 0x0000; // errno.h -pub const EPERM: ::c_int = 1; -pub const ENOENT: ::c_int = 2; -pub const ESRCH: ::c_int = 3; -pub const EINTR: ::c_int = 4; -pub const EIO: ::c_int = 5; -pub const ENXIO: ::c_int = 6; -pub const E2BIG: ::c_int = 7; -pub const ENOEXEC: ::c_int = 8; -pub const EBADF: ::c_int = 9; -pub const ECHILD: ::c_int = 10; -pub const EAGAIN: ::c_int = 11; -pub const ENOMEM: ::c_int = 12; -pub const EACCES: ::c_int = 13; -pub const EFAULT: ::c_int = 14; -pub const ENOTBLK: ::c_int = 15; -pub const EBUSY: ::c_int = 16; -pub const EEXIST: ::c_int = 17; -pub const EXDEV: ::c_int = 18; -pub const ENODEV: ::c_int = 19; -pub const ENOTDIR: ::c_int = 20; -pub const EISDIR: ::c_int = 21; -pub const EINVAL: ::c_int = 22; -pub const ENFILE: ::c_int = 23; -pub const EMFILE: ::c_int = 24; -pub const ENOTTY: ::c_int = 25; -pub const ETXTBSY: ::c_int = 26; -pub const EFBIG: ::c_int = 27; -pub const ENOSPC: ::c_int = 28; -pub const ESPIPE: ::c_int = 29; -pub const EROFS: ::c_int = 30; -pub const EMLINK: ::c_int = 31; -pub const EPIPE: ::c_int = 32; -pub const EDOM: ::c_int = 33; -pub const ERANGE: ::c_int = 34; -pub const EDEADLK: ::c_int = 35; -pub const ENOSYS: ::c_int = 38; -pub const EWOULDBLOCK: ::c_int = 41; -pub const EADDRINUSE: ::c_int = 98; -pub const EADDRNOTAVAIL: ::c_int = 99; -pub const ECONNABORTED: ::c_int = 103; -pub const ECONNRESET: ::c_int = 104; -pub const ENOTCONN: ::c_int = 107; -pub const ETIMEDOUT: ::c_int = 110; -pub const ECONNREFUSED: ::c_int = 111; -pub const EINPROGRESS: ::c_int = 115; +pub const EPERM: ::c_int = 1; /* Operation not permitted */ +pub const ENOENT: ::c_int = 2; /* No such file or directory */ +pub const ESRCH: ::c_int = 3; /* No such process */ +pub const EINTR: ::c_int = 4; /* Interrupted system call */ +pub const EIO: ::c_int = 5; /* I/O error */ +pub const ENXIO: ::c_int = 6; /* No such device or address */ +pub const E2BIG: ::c_int = 7; /* Argument list too long */ +pub const ENOEXEC: ::c_int = 8; /* Exec format error */ +pub const EBADF: ::c_int = 9; /* Bad file number */ +pub const ECHILD: ::c_int = 10; /* No child processes */ +pub const EAGAIN: ::c_int = 11; /* Try again */ +pub const ENOMEM: ::c_int = 12; /* Out of memory */ +pub const EACCES: ::c_int = 13; /* Permission denied */ +pub const EFAULT: ::c_int = 14; /* Bad address */ +pub const ENOTBLK: ::c_int = 15; /* Block device required */ +pub const EBUSY: ::c_int = 16; /* Device or resource busy */ +pub const EEXIST: ::c_int = 17; /* File exists */ +pub const EXDEV: ::c_int = 18; /* Cross-device link */ +pub const ENODEV: ::c_int = 19; /* No such device */ +pub const ENOTDIR: ::c_int = 20; /* Not a directory */ +pub const EISDIR: ::c_int = 21; /* Is a directory */ +pub const EINVAL: ::c_int = 22; /* Invalid argument */ +pub const ENFILE: ::c_int = 23; /* File table overflow */ +pub const EMFILE: ::c_int = 24; /* Too many open files */ +pub const ENOTTY: ::c_int = 25; /* Not a typewriter */ +pub const ETXTBSY: ::c_int = 26; /* Text file busy */ +pub const EFBIG: ::c_int = 27; /* File too large */ +pub const ENOSPC: ::c_int = 28; /* No space left on device */ +pub const ESPIPE: ::c_int = 29; /* Illegal seek */ +pub const EROFS: ::c_int = 30; /* Read-only file system */ +pub const EMLINK: ::c_int = 31; /* Too many links */ +pub const EPIPE: ::c_int = 32; /* Broken pipe */ +pub const EDOM: ::c_int = 33; /* Math argument out of domain of func */ +pub const ERANGE: ::c_int = 34; /* Math result not representable */ +pub const EDEADLK: ::c_int = 35; /* Resource deadlock would occur */ +pub const ENAMETOOLONG: ::c_int = 36; /* File name too long */ +pub const ENOLCK: ::c_int = 37; /* No record locks available */ +pub const ENOSYS: ::c_int = 38; /* Function not implemented */ +pub const ENOTEMPTY: ::c_int = 39; /* Directory not empty */ +pub const ELOOP: ::c_int = 40; /* Too many symbolic links encountered */ +pub const EWOULDBLOCK: ::c_int = 41; /* Operation would block */ +pub const ENOMSG: ::c_int = 42; /* No message of desired type */ +pub const EIDRM: ::c_int = 43; /* Identifier removed */ +pub const ECHRNG: ::c_int = 44; /* Channel number out of range */ +pub const EL2NSYNC: ::c_int = 45; /* Level 2 not synchronized */ +pub const EL3HLT: ::c_int = 46; /* Level 3 halted */ +pub const EL3RST: ::c_int = 47; /* Level 3 reset */ +pub const ELNRNG: ::c_int = 48; /* Link number out of range */ +pub const EUNATCH: ::c_int = 49; /* Protocol driver not attached */ +pub const ENOCSI: ::c_int = 50; /* No CSI structure available */ +pub const EL2HLT: ::c_int = 51; /* Level 2 halted */ +pub const EBADE: ::c_int = 52; /* Invalid exchange */ +pub const EBADR: ::c_int = 53; /* Invalid request descriptor */ +pub const EXFULL: ::c_int = 54; /* Exchange full */ +pub const ENOANO: ::c_int = 55; /* No anode */ +pub const EBADRQC: ::c_int = 56; /* Invalid request code */ +pub const EBADSLT: ::c_int = 57; /* Invalid slot */ +pub const EDEADLOCK: ::c_int = 58; /* Resource deadlock would occur */ +pub const EBFONT: ::c_int = 59; /* Bad font file format */ +pub const ENOSTR: ::c_int = 60; /* Device not a stream */ +pub const ENODATA: ::c_int = 61; /* No data available */ +pub const ETIME: ::c_int = 62; /* Timer expired */ +pub const ENOSR: ::c_int = 63; /* Out of streams resources */ +pub const ENONET: ::c_int = 64; /* Machine is not on the network */ +pub const ENOPKG: ::c_int = 65; /* Package not installed */ +pub const EREMOTE: ::c_int = 66; /* Object is remote */ +pub const ENOLINK: ::c_int = 67; /* Link has been severed */ +pub const EADV: ::c_int = 68; /* Advertise error */ +pub const ESRMNT: ::c_int = 69; /* Srmount error */ +pub const ECOMM: ::c_int = 70; /* Communication error on send */ +pub const EPROTO: ::c_int = 71; /* Protocol error */ +pub const EMULTIHOP: ::c_int = 72; /* Multihop attempted */ +pub const EDOTDOT: ::c_int = 73; /* RFS specific error */ +pub const EBADMSG: ::c_int = 74; /* Not a data message */ +pub const EOVERFLOW: ::c_int = 75; /* Value too large for defined data type */ +pub const ENOTUNIQ: ::c_int = 76; /* Name not unique on network */ +pub const EBADFD: ::c_int = 77; /* File descriptor in bad state */ +pub const EREMCHG: ::c_int = 78; /* Remote address changed */ +pub const ELIBACC: ::c_int = 79; /* Can not access a needed shared library */ +pub const ELIBBAD: ::c_int = 80; /* Accessing a corrupted shared library */ +pub const ELIBSCN: ::c_int = 81; /* .lib section in a.out corrupted */ +/* Attempting to link in too many shared libraries */ +pub const ELIBMAX: ::c_int = 82; +pub const ELIBEXEC: ::c_int = 83; /* Cannot exec a shared library directly */ +pub const EILSEQ: ::c_int = 84; /* Illegal byte sequence */ +/* Interrupted system call should be restarted */ +pub const ERESTART: ::c_int = 85; +pub const ESTRPIPE: ::c_int = 86; /* Streams pipe error */ +pub const EUSERS: ::c_int = 87; /* Too many users */ +pub const ENOTSOCK: ::c_int = 88; /* Socket operation on non-socket */ +pub const EDESTADDRREQ: ::c_int = 89; /* Destination address required */ +pub const EMSGSIZE: ::c_int = 90; /* Message too long */ +pub const EPROTOTYPE: ::c_int = 91; /* Protocol wrong type for socket */ +pub const ENOPROTOOPT: ::c_int = 92; /* Protocol not available */ +pub const EPROTONOSUPPORT: ::c_int = 93; /* Protocol not supported */ +pub const ESOCKTNOSUPPORT: ::c_int = 94; /* Socket type not supported */ +/* Operation not supported on transport endpoint */ +pub const EOPNOTSUPP: ::c_int = 95; +pub const EPFNOSUPPORT: ::c_int = 96; /* Protocol family not supported */ +/* Address family not supported by protocol */ +pub const EAFNOSUPPORT: ::c_int = 97; +pub const EADDRINUSE: ::c_int = 98; /* Address already in use */ +pub const EADDRNOTAVAIL: ::c_int = 99; /* Cannot assign requested address */ +pub const ENETDOWN: ::c_int = 100; /* Network is down */ +pub const ENETUNREACH: ::c_int = 101; /* Network is unreachable */ +/* Network dropped connection because of reset */ +pub const ENETRESET: ::c_int = 102; +pub const ECONNABORTED: ::c_int = 103; /* Software caused connection abort */ +pub const ECONNRESET: ::c_int = 104; /* Connection reset by peer */ +pub const ENOBUFS: ::c_int = 105; /* No buffer space available */ +pub const EISCONN: ::c_int = 106; /* Transport endpoint is already connected */ +pub const ENOTCONN: ::c_int = 107; /* Transport endpoint is not connected */ +/* Cannot send after transport endpoint shutdown */ +pub const ESHUTDOWN: ::c_int = 108; +pub const ETOOMANYREFS: ::c_int = 109; /* Too many references: cannot splice */ +pub const ETIMEDOUT: ::c_int = 110; /* Connection timed out */ +pub const ECONNREFUSED: ::c_int = 111; /* Connection refused */ +pub const EHOSTDOWN: ::c_int = 112; /* Host is down */ +pub const EHOSTUNREACH: ::c_int = 113; /* No route to host */ +pub const EALREADY: ::c_int = 114; /* Operation already in progress */ +pub const EINPROGRESS: ::c_int = 115; /* Operation now in progress */ +pub const ESTALE: ::c_int = 116; /* Stale NFS file handle */ +pub const EUCLEAN: ::c_int = 117; /* Structure needs cleaning */ +pub const ENOTNAM: ::c_int = 118; /* Not a XENIX named type file */ +pub const ENAVAIL: ::c_int = 119; /* No XENIX semaphores available */ +pub const EISNAM: ::c_int = 120; /* Is a named type file */ +pub const EREMOTEIO: ::c_int = 121; /* Remote I/O error */ +pub const EDQUOT: ::c_int = 122; /* Quota exceeded */ +pub const ENOMEDIUM: ::c_int = 123; /* No medium found */ +pub const EMEDIUMTYPE: ::c_int = 124; /* Wrong medium type */ +pub const ECANCELED: ::c_int = 125; /* Operation Canceled */ +pub const ENOKEY: ::c_int = 126; /* Required key not available */ +pub const EKEYEXPIRED: ::c_int = 127; /* Key has expired */ +pub const EKEYREVOKED: ::c_int = 128; /* Key has been revoked */ +pub const EKEYREJECTED: ::c_int = 129; /* Key was rejected by service */ +pub const EOWNERDEAD: ::c_int = 130; /* Owner died */ +pub const ENOTRECOVERABLE: ::c_int = 131; /* State not recoverable */ // fcntl.h pub const F_DUPFD: ::c_int = 0; @@ -281,7 +412,7 @@ pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; // TODO: relibc { - pub const F_DUPFD_CLOEXEC: ::c_int = ::F_DUPFD; +pub const F_DUPFD_CLOEXEC: ::c_int = ::F_DUPFD; // } pub const FD_CLOEXEC: ::c_int = 0x0100_0000; pub const O_RDONLY: ::c_int = 0x0001_0000; @@ -310,25 +441,25 @@ pub const EAI_SYSTEM: ::c_int = -11; // netinet/in.h // TODO: relibc { - pub const IP_TTL: ::c_int = 2; - pub const IPV6_UNICAST_HOPS: ::c_int = 16; - pub const IPV6_MULTICAST_IF: ::c_int = 17; - pub const IPV6_MULTICAST_HOPS: ::c_int = 18; - pub const IPV6_MULTICAST_LOOP: ::c_int = 19; - pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; - pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; - pub const IPV6_V6ONLY: ::c_int = 26; - pub const IP_MULTICAST_IF: ::c_int = 32; - pub const IP_MULTICAST_TTL: ::c_int = 33; - pub const IP_MULTICAST_LOOP: ::c_int = 34; - pub const IP_ADD_MEMBERSHIP: ::c_int = 35; - pub const IP_DROP_MEMBERSHIP: ::c_int = 36; +pub const IP_TTL: ::c_int = 2; +pub const IPV6_UNICAST_HOPS: ::c_int = 16; +pub const IPV6_MULTICAST_IF: ::c_int = 17; +pub const IPV6_MULTICAST_HOPS: ::c_int = 18; +pub const IPV6_MULTICAST_LOOP: ::c_int = 19; +pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; +pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; +pub const IPV6_V6ONLY: ::c_int = 26; +pub const IP_MULTICAST_IF: ::c_int = 32; +pub const IP_MULTICAST_TTL: ::c_int = 33; +pub const IP_MULTICAST_LOOP: ::c_int = 34; +pub const IP_ADD_MEMBERSHIP: ::c_int = 35; +pub const IP_DROP_MEMBERSHIP: ::c_int = 36; // } // netinet/tcp.h pub const TCP_NODELAY: ::c_int = 1; // TODO: relibc { - pub const TCP_KEEPIDLE: ::c_int = 1; +pub const TCP_KEEPIDLE: ::c_int = 1; // } // poll.h @@ -345,7 +476,7 @@ pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_INITIALIZER: ::pthread_mutex_t = -1isize as *mut _; pub const PTHREAD_COND_INITIALIZER: ::pthread_cond_t = -1isize as *mut _; pub const PTHREAD_RWLOCK_INITIALIZER: ::pthread_rwlock_t = -1isize as *mut _; -pub const PTHREAD_STACK_MIN : ::size_t = 4096; +pub const PTHREAD_STACK_MIN: ::size_t = 4096; // signal.h pub const SIG_BLOCK: ::c_int = 0; @@ -384,6 +515,15 @@ pub const SIGPWR: ::c_int = 30; pub const SIGSYS: ::c_int = 31; pub const NSIG: ::c_int = 32; +pub const SA_NOCLDSTOP: ::c_ulong = 0x00000001; +pub const SA_NOCLDWAIT: ::c_ulong = 0x00000002; +pub const SA_SIGINFO: ::c_ulong = 0x00000004; +pub const SA_RESTORER: ::c_ulong = 0x04000000; +pub const SA_ONSTACK: ::c_ulong = 0x08000000; +pub const SA_RESTART: ::c_ulong = 0x10000000; +pub const SA_NODEFER: ::c_ulong = 0x40000000; +pub const SA_RESETHAND: ::c_ulong = 0x80000000; + // sys/epoll.h pub const EPOLL_CLOEXEC: ::c_int = 0x0100_0000; pub const EPOLL_CTL_ADD: ::c_int = 1; @@ -434,8 +574,8 @@ pub const EXIT_FAILURE: ::c_int = 1; // sys/ioctl.h // TODO: relibc { - pub const FIONBIO: ::c_ulong = 0x5421; - pub const FIOCLEX: ::c_ulong = 0x5451; +pub const FIONBIO: ::c_ulong = 0x5421; +pub const FIOCLEX: ::c_ulong = 0x5451; // } pub const TCGETS: ::c_ulong = 0x5401; pub const TCSETS: ::c_ulong = 0x5402; @@ -472,6 +612,17 @@ pub const SOL_SOCKET: ::c_int = 1; // sys/wait.h pub const WNOHANG: ::c_int = 1; +pub const WUNTRACED: ::c_int = 2; + +pub const WSTOPPED: ::c_int = 2; +pub const WEXITED: ::c_int = 4; +pub const WCONTINUED: ::c_int = 8; +pub const WNOWAIT: ::c_int = 0x0100_0000; + +pub const __WNOTHREAD: ::c_int = 0x2000_0000; +pub const __WALL: ::c_int = 0x4000_0000; +#[allow(overflowing_literals)] +pub const __WCLONE: ::c_int = 0x8000_0000; // termios.h pub const NCCS: usize = 32; @@ -481,7 +632,34 @@ pub const CLOCK_REALTIME: ::c_int = 1; pub const CLOCK_MONOTONIC: ::c_int = 4; // unistd.h +// POSIX.1 { +pub const _SC_ARG_MAX: ::c_int = 0; +pub const _SC_CHILD_MAX: ::c_int = 1; +pub const _SC_CLK_TCK: ::c_int = 2; +pub const _SC_NGROUPS_MAX: ::c_int = 3; +pub const _SC_OPEN_MAX: ::c_int = 4; +pub const _SC_STREAM_MAX: ::c_int = 5; +pub const _SC_TZNAME_MAX: ::c_int = 6; +// ... +pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; +pub const _SC_PAGE_SIZE: ::c_int = 30; +// ... +pub const _SC_RE_DUP_MAX: ::c_int = 44; +// ... +pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; +pub const _SC_TTY_NAME_MAX: ::c_int = 72; +// ... +pub const _SC_SYMLOOP_MAX: ::c_int = 173; +// ... +pub const _SC_HOST_NAME_MAX: ::c_int = 180; +// } POSIX.1 + +pub const F_OK: ::c_int = 0; +pub const R_OK: ::c_int = 4; +pub const W_OK: ::c_int = 2; +pub const X_OK: ::c_int = 1; + pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; @@ -489,109 +667,327 @@ pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; -// wait.h -pub fn WIFSTOPPED(status: ::c_int) -> bool { - (status & 0xff) == 0x7f -} +pub const _PC_LINK_MAX: ::c_int = 0; +pub const _PC_MAX_CANON: ::c_int = 1; +pub const _PC_MAX_INPUT: ::c_int = 2; +pub const _PC_NAME_MAX: ::c_int = 3; +pub const _PC_PATH_MAX: ::c_int = 4; +pub const _PC_PIPE_BUF: ::c_int = 5; +pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; +pub const _PC_NO_TRUNC: ::c_int = 7; +pub const _PC_VDISABLE: ::c_int = 8; +pub const _PC_SYNC_IO: ::c_int = 9; +pub const _PC_ASYNC_IO: ::c_int = 10; +pub const _PC_PRIO_IO: ::c_int = 11; +pub const _PC_SOCK_MAXBUF: ::c_int = 12; +pub const _PC_FILESIZEBITS: ::c_int = 13; +pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; +pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; +pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; +pub const _PC_REC_XFER_ALIGN: ::c_int = 17; +pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; +pub const _PC_SYMLINK_MAX: ::c_int = 19; +pub const _PC_2_SYMLINKS: ::c_int = 20; -pub fn WSTOPSIG(status: ::c_int) -> ::c_int { - (status >> 8) & 0xff -} +// wait.h +f! { + pub fn WIFSTOPPED(status: ::c_int) -> bool { + (status & 0xff) == 0x7f + } -pub fn WIFCONTINUED(status: ::c_int) -> bool { - status == 0xffff -} + pub fn WSTOPSIG(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } -pub fn WIFSIGNALED(status: ::c_int) -> bool { - ((status & 0x7f) + 1) as i8 >= 2 -} + pub fn WIFCONTINUED(status: ::c_int) -> bool { + status == 0xffff + } -pub fn WTERMSIG(status: ::c_int) -> ::c_int { - status & 0x7f -} + pub fn WIFSIGNALED(status: ::c_int) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 + } -pub fn WIFEXITED(status: ::c_int) -> bool { - (status & 0x7f) == 0 -} + pub fn WTERMSIG(status: ::c_int) -> ::c_int { + status & 0x7f + } -pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { - (status >> 8) & 0xff -} + pub fn WIFEXITED(status: ::c_int) -> bool { + (status & 0x7f) == 0 + } -pub fn WCOREDUMP(status: ::c_int) -> bool { - (status & 0x80) != 0 -} + pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } -// intentionally not public, only used for fd_set -cfg_if! { - if #[cfg(target_pointer_width = "32")] { - const ULONG_SIZE: usize = 32; - } else if #[cfg(target_pointer_width = "64")] { - const ULONG_SIZE: usize = 64; - } else { - // Unknown target_pointer_width + pub fn WCOREDUMP(status: ::c_int) -> bool { + (status & 0x80) != 0 } } extern { - pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; - pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; - + // errno.h + pub fn __errno_location() -> *mut ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; - pub fn __errno_location() -> *mut ::c_int; + + // unistd.h + pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; // malloc.h pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; // pthread.h - pub fn pthread_atfork(prepare: ::Option, - parent: ::Option, - child: ::Option) -> ::c_int; - pub fn pthread_create(tid: *mut ::pthread_t, - attr: *const ::pthread_attr_t, - start: extern fn(*mut ::c_void) -> *mut ::c_void, - arg: *mut ::c_void) -> ::c_int; - pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, - clock_id: ::clockid_t) -> ::c_int; + pub fn pthread_atfork( + prepare: ::Option, + parent: ::Option, + child: ::Option, + ) -> ::c_int; + pub fn pthread_create( + tid: *mut ::pthread_t, + attr: *const ::pthread_attr_t, + start: extern fn(*mut ::c_void) -> *mut ::c_void, + arg: *mut ::c_void, + ) -> ::c_int; + pub fn pthread_condattr_setclock( + attr: *mut pthread_condattr_t, + clock_id: ::clockid_t, + ) -> ::c_int; + + // pwd.h + pub fn getpwuid_r(uid: ::uid_t, + pwd: *mut passwd, + buf: *mut ::c_char, + buflen: ::size_t, + result: *mut *mut passwd) -> ::c_int; // signal.h - pub fn pthread_sigmask(how: ::c_int, - set: *const ::sigset_t, - oldset: *mut ::sigset_t) -> ::c_int; + pub fn pthread_sigmask( + how: ::c_int, + set: *const ::sigset_t, + oldset: *mut ::sigset_t, + ) -> ::c_int; // sys/epoll.h pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; - pub fn epoll_wait(epfd: ::c_int, - events: *mut ::epoll_event, - maxevents: ::c_int, - timeout: ::c_int) -> ::c_int; - pub fn epoll_ctl(epfd: ::c_int, - op: ::c_int, - fd: ::c_int, - event: *mut ::epoll_event) -> ::c_int; + pub fn epoll_wait( + epfd: ::c_int, + events: *mut ::epoll_event, + maxevents: ::c_int, + timeout: ::c_int, + ) -> ::c_int; + pub fn epoll_ctl( + epfd: ::c_int, + op: ::c_int, + fd: ::c_int, + event: *mut ::epoll_event, + ) -> ::c_int; // sys/ioctl.h pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; + // sys/resource.h + pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; + pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; + // sys/socket.h - pub fn bind(socket: ::c_int, address: *const ::sockaddr, - address_len: ::socklen_t) -> ::c_int; - pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, - flags: ::c_int, addr: *mut ::sockaddr, - addrlen: *mut ::socklen_t) -> ::ssize_t; + pub fn bind( + socket: ::c_int, + address: *const ::sockaddr, + address_len: ::socklen_t, + ) -> ::c_int; + pub fn recvfrom( + socket: ::c_int, + buf: *mut ::c_void, + len: ::size_t, + flags: ::c_int, + addr: *mut ::sockaddr, + addrlen: *mut ::socklen_t, + ) -> ::ssize_t; + + // sys/stat.h + pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; // sys/uio.h - pub fn readv(fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int) -> ::ssize_t; - pub fn writev(fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int) -> ::ssize_t; + pub fn readv( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; + pub fn writev( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; + + // sys/utsname.h + pub fn uname(utsname: *mut utsname) -> ::c_int; // time.h pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; } + +cfg_if! { + if #[cfg(feature = "extra_traits")] { + impl PartialEq for dirent { + fn eq(&self, other: &dirent) -> bool { + self.d_ino == other.d_ino + && self.d_off == other.d_off + && self.d_reclen == other.d_reclen + && self.d_type == other.d_type + && self + .d_name + .iter() + .zip(other.d_name.iter()) + .all(|(a,b)| a == b) + } + } + + impl Eq for dirent {} + + impl ::fmt::Debug for dirent { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("dirent") + .field("d_ino", &self.d_ino) + .field("d_off", &self.d_off) + .field("d_reclen", &self.d_reclen) + .field("d_type", &self.d_type) + // FIXME: .field("d_name", &self.d_name) + .finish() + } + } + + impl ::hash::Hash for dirent { + fn hash(&self, state: &mut H) { + self.d_ino.hash(state); + self.d_off.hash(state); + self.d_reclen.hash(state); + self.d_type.hash(state); + self.d_name.hash(state); + } + } + + impl PartialEq for sockaddr_un { + fn eq(&self, other: &sockaddr_un) -> bool { + self.sun_family == other.sun_family + && self + .sun_path + .iter() + .zip(other.sun_path.iter()) + .all(|(a,b)| a == b) + } + } + + impl Eq for sockaddr_un {} + + impl ::fmt::Debug for sockaddr_un { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("sockaddr_un") + .field("sun_family", &self.sun_family) + // FIXME: .field("sun_path", &self.sun_path) + .finish() + } + } + + impl ::hash::Hash for sockaddr_un { + fn hash(&self, state: &mut H) { + self.sun_family.hash(state); + self.sun_path.hash(state); + } + } + + impl PartialEq for sockaddr_storage { + fn eq(&self, other: &sockaddr_storage) -> bool { + self.ss_family == other.ss_family + && self.__ss_align == self.__ss_align + && self + .__ss_padding + .iter() + .zip(other.__ss_padding.iter()) + .all(|(a,b)| a == b) + } + } + + impl Eq for sockaddr_storage {} + + impl ::fmt::Debug for sockaddr_storage { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("sockaddr_storage") + .field("ss_family", &self.ss_family) + .field("__ss_align", &self.__ss_align) + // FIXME: .field("__ss_padding", &self.__ss_padding) + .finish() + } + } + + impl ::hash::Hash for sockaddr_storage { + fn hash(&self, state: &mut H) { + self.ss_family.hash(state); + self.__ss_padding.hash(state); + self.__ss_align.hash(state); + } + } + + impl PartialEq for utsname { + fn eq(&self, other: &utsname) -> bool { + self.sysname + .iter() + .zip(other.sysname.iter()) + .all(|(a, b)| a == b) + && self + .nodename + .iter() + .zip(other.nodename.iter()) + .all(|(a, b)| a == b) + && self + .release + .iter() + .zip(other.release.iter()) + .all(|(a, b)| a == b) + && self + .version + .iter() + .zip(other.version.iter()) + .all(|(a, b)| a == b) + && self + .machine + .iter() + .zip(other.machine.iter()) + .all(|(a, b)| a == b) + && self + .domainname + .iter() + .zip(other.domainname.iter()) + .all(|(a, b)| a == b) + } + } + + impl Eq for utsname {} + + impl ::fmt::Debug for utsname { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("utsname") + // FIXME: .field("sysname", &self.sysname) + // FIXME: .field("nodename", &self.nodename) + // FIXME: .field("release", &self.release) + // FIXME: .field("version", &self.version) + // FIXME: .field("machine", &self.machine) + // FIXME: .field("domainname", &self.domainname) + .finish() + } + } + + impl ::hash::Hash for utsname { + fn hash(&self, state: &mut H) { + self.sysname.hash(state); + self.nodename.hash(state); + self.release.hash(state); + self.version.hash(state); + self.machine.hash(state); + self.domainname.hash(state); + } + } + } +} diff --git a/vendor/libc/src/vxworks/aarch64.rs b/vendor/libc/src/vxworks/aarch64.rs new file mode 100644 index 0000000000..577c8bef16 --- /dev/null +++ b/vendor/libc/src/vxworks/aarch64.rs @@ -0,0 +1,3 @@ +pub type c_char = u8; +pub type c_long = i64; +pub type c_ulong = u64; diff --git a/vendor/libc/src/vxworks/arm.rs b/vendor/libc/src/vxworks/arm.rs new file mode 100644 index 0000000000..cfdce825a0 --- /dev/null +++ b/vendor/libc/src/vxworks/arm.rs @@ -0,0 +1,3 @@ +pub type c_char = u8; +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/vendor/libc/src/vxworks/armv7.rs b/vendor/libc/src/vxworks/armv7.rs new file mode 100644 index 0000000000..9b0b338b91 --- /dev/null +++ b/vendor/libc/src/vxworks/armv7.rs @@ -0,0 +1,2 @@ +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/vendor/libc/src/vxworks/mod.rs b/vendor/libc/src/vxworks/mod.rs new file mode 100755 index 0000000000..19aa2b69d0 --- /dev/null +++ b/vendor/libc/src/vxworks/mod.rs @@ -0,0 +1,2319 @@ +//! Hacking together the definitions for VxWorks Bindings +use core::mem::size_of; +use core::ptr::null_mut; + +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum DIR {} +impl ::Copy for DIR {} +impl ::Clone for DIR { + fn clone(&self) -> DIR { + *self + } +} + +pub type c_schar = i8; +pub type c_uchar = u8; +pub type c_short = i16; +pub type c_ushort = u16; +pub type c_int = i32; +pub type c_uint = u32; +pub type c_float = f32; +pub type c_double = f64; +pub type c_longlong = i64; +pub type c_ulonglong = u64; +pub type intmax_t = i64; +pub type uintmax_t = u64; + +pub type size_t = usize; +pub type ptrdiff_t = isize; +pub type intptr_t = isize; +pub type uintptr_t = usize; +pub type ssize_t = isize; + +pub type pid_t = i32; +pub type in_addr_t = u32; +pub type in_port_t = u16; +pub type sighandler_t = ::size_t; +pub type cc_t = ::c_uchar; + +pub type blkcnt_t = ::c_long; +pub type blksize_t = ::c_long; +pub type ino_t = ::c_ulong; +pub type ino32_t = u32; +pub type off_t = ::c_longlong; + +pub type rlim_t = ::c_ulonglong; +pub type suseconds_t = ::c_long; +pub type time_t = ::c_long; +pub type wchar_t = ::c_int; +pub type errno_t = ::c_int; + +pub type useconds_t = ::c_ulong; + +pub type socklen_t = ::c_int; + +pub type pthread_t = ::c_ulong; + +pub type clockid_t = ::c_int; + +//defined for the structs +pub type dev_t = ::c_ulong; +pub type mode_t = ::c_int; +pub type nlink_t = ::c_ulong; +pub type uid_t = ::c_ushort; +pub type gid_t = ::c_ushort; +pub type sigset_t = ::c_ulonglong; +pub type key_t = ::c_long; +pub type shmatt_t = ::c_ulong; + +pub type mqd_t = ::c_int; + +pub type nfds_t = ::c_uint; +pub type nl_item = ::c_int; +pub type stat64 = ::stat; + +pub type pthread_key_t = ::c_ulong; + +// From b_off_t.h +pub type off64_t = ::c_longlong; +pub type off_t64 = ::c_longlong; + +// From b_BOOL.h +pub type BOOL = ::c_int; // excuse me what + +//Straight from vxWind.h .. +pub type _Vx_OBJ_HANDLE = ::c_int; +pub type _Vx_TASK_ID = ::_Vx_OBJ_HANDLE; +pub type _Vx_MSG_Q_ID = ::_Vx_OBJ_HANDLE; +pub type _Vx_SEM_ID_KERNEL = ::_Vx_OBJ_HANDLE; +pub type _Vx_RTP_ID = ::_Vx_OBJ_HANDLE; +pub type _Vx_SD_ID = ::_Vx_OBJ_HANDLE; +pub type _Vx_CONDVAR_ID = ::_Vx_OBJ_HANDLE; +pub type _Vx_SEM_ID = *mut ::_Vx_semaphore; +pub type OBJ_HANDLE = ::_Vx_OBJ_HANDLE; +pub type TASK_ID = ::OBJ_HANDLE; +pub type MSG_Q_ID = ::OBJ_HANDLE; +pub type SEM_ID_KERNEL = ::OBJ_HANDLE; +pub type RTP_ID = ::OBJ_HANDLE; +pub type SD_ID = ::OBJ_HANDLE; +pub type CONDVAR_ID = ::OBJ_HANDLE; + +// From vxTypes.h +pub type _Vx_usr_arg_t = ::ssize_t; // c_int for LP32 +pub type _Vx_exit_code_t = ::ssize_t; // c_int for LP32 +pub type _Vx_ticks_t = ::c_uint; +pub type _Vx_ticks64_t = ::c_ulonglong; + +// From vxTypesBase.h +pub type va_list = *mut ::c_char; + +pub type sa_family_t = ::c_uchar; + +// structs that only exist in userspace +s! { + // b_struct_vx_eventsResourceCb.h + pub struct _Vx_EVENTS_RSRC { + pub registered : ::c_uint, + pub taskId : ::c_int, + pub options : ::c_uchar, + pub pad : [::c_uchar; 3], + } + + // b_struct_vx_semaphore.h + pub struct _Vx_semaphore { + pub magic : ::c_uint, + pub semType: ::c_uint, + pub options: ::c_uint, + pub recurse: ::c_uint, + pub owned_k: ::c_uint, // owned_k is volatile + pub semId_k: ::_Vx_SEM_ID_KERNEL, + pub state : ::c_uint, //state is union of _Vx_UINT and _Vx_UINT + pub events : ::_Vx_EVENTS_RSRC, + } + + // b_pthread_condattr_t.h + pub struct pthread_condattr_t { + pub condAttrStatus: ::c_int, + pub condAttrPshared: ::c_int, + pub _CondAttrClockId: ::clockid_t, + } + + // b_pthread_cond_t.h + pub struct pthread_cond_t{ + pub condSemId: ::_Vx_SEM_ID, + pub condValid: ::c_int, + pub condInitted: ::c_int, + pub condRefCount: ::c_int, + pub condMutex: *mut ::pthread_mutex_t, + pub condAttr: ::pthread_condattr_t, + pub condSemName: [::c_char; PTHREAD_SHARED_SEM_NAME_MAX] + } + + // b_pthread_rwlockattr_t.h + pub struct pthread_rwlockattr_t { + pub rwlockAttrStatus: ::c_int, + pub rwlockAttrMaxReaders: ::c_uint, + } + + // b_pthread_rwlock_t.h + pub struct pthread_rwlock_t { + pub rwlockSemId: :: _Vx_SEM_ID, + pub rwlockReadersRefCount: ::c_int, + pub rwlockValid: ::c_int, + pub rwlockInitted: ::c_int, + pub rwlockAttr: ::pthread_rwlockattr_t, + pub rwlockName: [::c_char; PTHREAD_SHARED_SEM_NAME_MAX] + } + + // b_struct_timeval.h + pub struct timeval { + pub tv_sec: ::time_t, + pub tv_usec: ::suseconds_t, + } + + // socket.h + pub struct sockaddr { + pub sa_len : ::c_uchar, + pub sa_family : sa_family_t, + pub sa_data : [::c_char; 14], + } + + // socket.h + pub struct sockaddr_storage { + pub ss_len : ::c_uchar, + pub ss_family : ::sa_family_t, + pub __ss_pad1 : [::c_char; _SS_PAD1SIZE], + pub __ss_align : i32, + // pub __ss_pad2 : [::c_char; _SS_PAD2SIZE], + pub __ss_pad2 : [::c_char; 32], + pub __ss_pad3 : [::c_char; 32], + pub __ss_pad4 : [::c_char; 32], + pub __ss_pad5 : [::c_char; 32], + } + pub struct iovec { + pub iov_base: *mut ::c_void, + pub iov_len: ::size_t, + } + + // poll.h + pub struct pollfd { + pub fd : ::c_int, + pub events : ::c_short, + pub revents : ::c_short, + } + + // dirent.h + pub struct dirent { + pub d_ino : ::ino_t, + // pub d_name : [::c_char; (_PARM_NAME_MAX + 1)], + pub d_name : [::c_char; 32], + pub d_name1 : [::c_char; 32], + pub d_name2 : [::c_char; 32], + pub d_name3 : [::c_char; 32], + pub d_name4 : [::c_char; 32], + pub d_name5 : [::c_char; 32], + pub d_name6 : [::c_char; 32], + pub d_name7 : [::c_char; 32], + } + + pub struct dirent64 { + pub d_ino : ::ino_t, + pub d_off : ::off64_t, + pub d_reclen : u16, + pub d_type : u8, + // pub d_name : [::c_char; 256], + pub d_name : [::c_char; 32], + pub d_name1 : [::c_char; 32], + pub d_name2 : [::c_char; 32], + pub d_name3 : [::c_char; 32], + pub d_name4 : [::c_char; 32], + pub d_name5 : [::c_char; 32], + pub d_name6 : [::c_char; 32], + pub d_name7 : [::c_char; 32], + } // Doesn't seem like it exists anymore + + // resource.h + pub struct rlimit { /* Is this really needed? Questionable ... */ + pub rlim_cur : ::size_t, + pub rlim_max : ::size_t, + } + + // stat.h + pub struct stat { + pub st_dev : ::dev_t, + pub st_ino : ::ino_t, + pub st_mode : ::mode_t, + pub st_nlink : ::nlink_t, + pub st_uid : ::uid_t, + pub st_gid : ::gid_t, + pub st_rdev : ::dev_t, + pub st_size : ::off64_t, + pub st_atime : ::time_t, + pub st_mtime : ::time_t, + pub st_ctime : ::time_t, + pub st_blksize : ::blksize_t, + pub st_blocks : ::blkcnt_t, + pub st_attrib : ::c_uchar, + pub st_reserved1 : ::c_int, + pub st_reserved2 : ::c_int, + pub st_reserved3 : ::c_int, + pub st_reserved4 : ::c_int, + } + + //b_struct__Timespec.h + pub struct _Timespec { + pub tv_sec : ::time_t, + pub tv_nsec : ::c_long, + } + + // b_struct__Sched_param.h + pub struct _Sched_param { + pub sched_priority: ::c_int, /* scheduling priority */ + pub sched_ss_low_priority: ::c_int, /* low scheduling priority */ + pub sched_ss_repl_period: ::_Timespec, /* replenishment period */ + pub sched_ss_init_budget: ::_Timespec, /* initial budget */ + pub sched_ss_max_repl: ::c_int, /* max pending replenishment */ + + } + + // b_pthread_attr_t.h + pub struct pthread_attr_t { + pub threadAttrStatus : ::c_int, + pub threadAttrStacksize : ::size_t, + pub threadAttrStackaddr : *mut ::c_void, + pub threadAttrGuardsize : ::size_t, + pub threadAttrDetachstate : ::c_int, + pub threadAttrContentionscope : ::c_int, + pub threadAttrInheritsched : ::c_int, + pub threadAttrSchedpolicy : ::c_int, + pub threadAttrName : *mut ::c_char, + pub threadAttrOptions : ::c_int, + pub threadAttrSchedparam : ::_Sched_param, + } + + // signal.h + pub struct sigaction { // pulled from kernel side, + pub sa_u : ::size_t, + // This is a union of two function pointers. + // Under the assumption that function pointers are the same + // size as other pointers, we can replace the union with size_t + pub sa_mask : ::sigset_t, + pub sa_flags : ::c_int, + } + + // b_stack_t.h + pub struct stack_t { + pub ss_sp : *mut ::c_void, + pub ss_size : ::size_t, + pub ss_flags : ::c_int, + } + + // signal.h + pub struct siginfo_t { + pub si_signo : ::c_int, + pub si_code : ::c_int, + // This field is a union of int and void * in vxworks + // The size has been set to the larger of the two + pub si_value : ::size_t, + } + + pub struct ipc_perm { + pub __key : key_t, + pub uid : uid_t, + pub gid : gid_t, + pub cuid : uid_t, + pub cgid : gid_t, + pub mode : ::c_ushort, + pub __seq : ::c_ushort, + } + + pub struct shmid_ds { + pub shm_perm : ipc_perm, + pub shm_segsz : ::c_int, + } + + // pthread.h (krnl) + // b_pthread_mutexattr_t.h (usr) + pub struct pthread_mutexattr_t { + mutexAttrStatus : ::c_int, + mutexAttrPshared : ::c_int, + mutexAttrProtocol : ::c_int, + mutexAttrPrioceiling : ::c_int, + mutexAttrType : ::c_int, + } + + // pthread.h (krnl) + // b_pthread_mutex_t.h (usr) + pub struct pthread_mutex_t { + pub mutexSemId: ::_Vx_SEM_ID, /*_Vx_SEM_ID ..*/ + pub mutexValid: ::c_int, + pub mutexInitted: ::c_int, + pub mutexCondRefCount: ::c_int, + pub mutexSavPriority: ::c_int, + pub mutexAttr: ::pthread_mutexattr_t, + pub mutexSemName: [::c_char; PTHREAD_SHARED_SEM_NAME_MAX], + } + + // b_struct_timespec.h + pub struct timespec { + pub tv_sec: ::time_t, + pub tv_nsec: ::c_long, + } + + // in.h + pub struct in_addr { + pub s_addr: in_addr_t, + } + + // in.h + pub struct ip_mreq { + pub imr_multiaddr: in_addr, + pub imr_interface: in_addr, + } + + // in6.h + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + // in6.h + pub struct ipv6_mreq { + pub ipv6mr_multiaddr: in6_addr, + pub ipv6mr_interface: ::c_uint, + } + + // netdb.h + pub struct addrinfo { + pub ai_flags : ::c_int, + pub ai_family : ::c_int, + pub ai_socktype : ::c_int, + pub ai_protocol : ::c_int, + pub ai_addrlen : ::size_t, + pub ai_canonname: *mut ::c_char, + pub ai_addr : *mut ::sockaddr, + pub ai_next : *mut ::addrinfo, + } + + // in.h + pub struct sockaddr_in { + pub sin_len : u8, + pub sin_family: u8, + pub sin_port : u16, + pub sin_addr : ::in_addr, + pub sin_zero : [::c_char; 8], + } + + // in6.h + // There is a different implementation in ipv6.h in + // krnl directory, but this seems to only happen + // when the VSB is built for ipv6 only. + pub struct sockaddr_in6 { + pub sin6_len : u8, + pub sin6_family : u8, + pub sin6_port : u16, + pub sin6_flowinfo: u32, + pub sin6_addr : ::in6_addr, + pub sin6_scope_id: u32, + } + + pub struct sockaddr_un { + pub sun_family: sa_family_t, + //pub sun_path: [::c_char; 108] + pub sun_path: [::c_char; 32], + pub sun_path1: [::c_char; 32], + pub sun_path2: [::c_char; 32], + pub sun_path3: [::c_char; 12], + } + + pub struct passwd { + pub pw_name: *mut ::c_char, + pub pw_uid: ::uid_t, + pub pw_gid: ::gid_t, + pub pw_dir: *mut ::c_char, + pub pw_shell: *mut ::c_char, + } + + // rtpLibCommon.h + pub struct RTP_DESC { + pub status : ::c_int, + pub options : u32, + pub entrAddr : *mut ::c_void, + pub initTaskId: ::TASK_ID, + pub parentId : ::RTP_ID, + //pub pathName : [::c_char; (VX_RTP_NAME_LENGTH + 1)], + pub pathName : [::c_char; 32], + pub pathName1 : [::c_char; 32], + pub pathName2 : [::c_char; 32], + pub pathName3 : [::c_char; 32], + pub pathName4 : [::c_char; 32], + pub pathName5 : [::c_char; 32], + pub pathName6 : [::c_char; 32], + pub pathName7 : [::c_char; 32], + pub taskCnt : u32, + pub textStart : *mut ::c_void, + pub textEnd : *mut ::c_void, + } + + pub struct Dl_info { + pub dli_fname: *const ::c_char, + pub dli_fbase: *mut ::c_void, + pub dli_sname: *const ::c_char, + pub dli_saddr: *mut ::c_void, + } +} + +pub const STDIN_FILENO: ::c_int = 0; +pub const STDOUT_FILENO: ::c_int = 1; +pub const STDERR_FILENO: ::c_int = 2; + +pub const EXIT_SUCCESS: ::c_int = 0; +pub const EXIT_FAILURE: ::c_int = 1; + +pub const EAI_SERVICE: ::c_int = 9; +pub const EAI_SOCKTYPE: ::c_int = 10; +pub const EAI_SYSTEM: ::c_int = 11; + +pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; + +//Clock Lib Stuff +pub const CLOCK_REALTIME: ::c_int = 0x0; +pub const CLOCK_MONOTONIC: ::c_int = 0x1; +pub const CLOCK_PROCESS_CPUTIME_ID: ::c_int = 0x2; +pub const CLOCK_THREAD_CPUTIME_ID: ::c_int = 0x3; +pub const TIMER_ABSTIME: ::c_int = 0x1; +pub const TIME_RELTIME: ::c_int = 0xFFFFFFFE; + +// PTHREAD STUFF +pub const PTHREAD_INITIALIZED_OBJ: ::c_int = 0xF70990EF; +pub const PTHREAD_DESTROYED_OBJ: ::c_int = -1; +pub const PTHREAD_VALID_OBJ: ::c_int = 0xEC542A37; +pub const PTHREAD_INVALID_OBJ: ::c_int = -1; +pub const PTHREAD_UNUSED_YET_OBJ: ::c_int = -1; + +pub const PTHREAD_PRIO_NONE: ::c_int = 0; +pub const PTHREAD_PRIO_INHERIT: ::c_int = 1; +pub const PTHREAD_PRIO_PROTECT: ::c_int = 2; + +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; +pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const PTHREAD_STACK_MIN: usize = 4096; +pub const PTHREAD_SHARED_SEM_NAME_MAX: usize = 30; + +pub const EFAULT: ::c_int = 14; +pub const EBUSY: ::c_int = 16; +pub const EEXIST: ::c_int = 17; +pub const ENODEV: ::c_int = 19; +pub const EINVAL: ::c_int = 22; +pub const EPIPE: ::c_int = 32; +pub const ERANGE: ::c_int = 34; + +// ERRNO STUFF +pub const EPERM: ::c_int = 1; /* Not owner */ +pub const ENOENT: ::c_int = 2; /* No such file or directory */ +pub const ESRCH: ::c_int = 3; /* No such process */ +pub const EINTR: ::c_int = 4; /* Interrupted system call */ +pub const EIOA: ::c_int = 5; /* I/O error */ +pub const ENXIO: ::c_int = 6; /* No such device or address */ +pub const E2BIG: ::c_int = 7; /* Arg list too long */ +pub const ENOEXEC: ::c_int = 8; /* Exec format error */ +pub const EBADF: ::c_int = 9; /* Bad file number */ +pub const CHILD: ::c_int = 10; /* No children */ +pub const EAGAIN: ::c_int = 11; /* No more processes */ +pub const ENOMEM: ::c_int = 12; /* Not enough core */ +pub const EACCES: ::c_int = 13; /* Permission denied */ +pub const EDEADLK: ::c_int = 33; +pub const EINPROGRESS: ::c_int = 68; +pub const EALREADY: ::c_int = 69; +pub const EWOULDBLOCK: ::c_int = 70; +pub const ENOSYS: ::c_int = 71; +pub const EDESTADDRREQ: ::c_int = 40; +pub const EPROTOTYPE: ::c_int = 41; +pub const ENOPROTOOPT: ::c_int = 42; +pub const EPROTONOSUPPORT: ::c_int = 43; +pub const ESOCKTNOSUPPORT: ::c_int = 44; +pub const EOPNOTSUPP: ::c_int = 45; +pub const EPFNOSUPPORT: ::c_int = 46; +pub const EAFNOSUPPORT: ::c_int = 47; +pub const EADDRINUSE: ::c_int = 48; +pub const EADDRNOTAVAIL: ::c_int = 49; +pub const ENOTSOCK: ::c_int = 50; +pub const ENETUNREACH: ::c_int = 51; +pub const ENETRESET: ::c_int = 52; +pub const ECONNABORTED: ::c_int = 53; +pub const ECONNRESET: ::c_int = 54; +pub const ENOBUFS: ::c_int = 55; +pub const EISCONN: ::c_int = 56; +pub const ENOTCONN: ::c_int = 57; +pub const ESHUTDOWN: ::c_int = 58; +pub const ETOOMANYREFS: ::c_int = 59; +pub const ETIMEDOUT: ::c_int = 60; +pub const ECONNREFUSED: ::c_int = 61; + +// NFS errnos: Refer to pkgs_v2/storage/fs/nfs/h/nfs/nfsCommon.h +const M_nfsStat: ::c_int = 48 << 16; +enum nfsstat { + NFS_OK = 0, + NFSERR_PERM = 1, + NFSERR_NOENT = 2, + NFSERR_IO = 5, + NFSERR_NXIO = 6, + NFSERR_ACCESS = 13, + NFSERR_EXIST = 17, + NFSERR_XDEV = 18, + NFSERR_NODEV = 19, + NFSERR_NOTDIR = 20, + NFSERR_ISDIR = 21, + NFSERR_INVAL = 22, + NFSERR_FBIG = 27, + NFSERR_NOSPC = 28, + NFSERR_ROFS = 30, + NFSERR_MLINK = 31, + NFSERR_NAMETOOLONG = 63, + NFSERR_NOTEMPTY = 66, + NFSERR_DQUOT = 69, + NFSERR_STALE = 70, + NFSERR_REMOTE = 71, + NFSERR_WFLUSH = 99, + NFSERR_BADHANDLE = 10001, + NFSERR_NOT_SYNC = 10002, + NFSERR_BAD_COOKIE = 10003, + NFSERR_NOTSUPP = 10004, + NFSERR_TOOSMALL = 10005, + NFSERR_SERVERFAULT = 10006, + NFSERR_BADTYPE = 10007, + NFSERR_JUKEBOX = 10008, +} + +pub const S_nfsLib_NFS_OK: ::c_int = M_nfsStat | nfsstat::NFS_OK as ::c_int; +pub const S_nfsLib_NFSERR_PERM: ::c_int = + M_nfsStat | nfsstat::NFSERR_PERM as ::c_int; +pub const S_nfsLib_NFSERR_NOENT: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOENT as ::c_int; +pub const S_nfsLib_NFSERR_IO: ::c_int = + M_nfsStat | nfsstat::NFSERR_IO as ::c_int; +pub const S_nfsLib_NFSERR_NXIO: ::c_int = + M_nfsStat | nfsstat::NFSERR_NXIO as ::c_int; +pub const S_nfsLib_NFSERR_ACCESS: ::c_int = + M_nfsStat | nfsstat::NFSERR_ACCESS as ::c_int; +pub const S_nfsLib_NFSERR_EXIST: ::c_int = + M_nfsStat | nfsstat::NFSERR_EXIST as ::c_int; +pub const S_nfsLib_NFSERR_XDEV: ::c_int = + M_nfsStat | nfsstat::NFSERR_XDEV as ::c_int; +pub const S_nfsLib_NFSERR_NODEV: ::c_int = + M_nfsStat | nfsstat::NFSERR_NODEV as ::c_int; +pub const S_nfsLib_NFSERR_NOTDIR: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOTDIR as ::c_int; +pub const S_nfsLib_NFSERR_ISDIR: ::c_int = + M_nfsStat | nfsstat::NFSERR_ISDIR as ::c_int; +pub const S_nfsLib_NFSERR_INVAL: ::c_int = + M_nfsStat | nfsstat::NFSERR_INVAL as ::c_int; +pub const S_nfsLib_NFSERR_FBIG: ::c_int = + M_nfsStat | nfsstat::NFSERR_FBIG as ::c_int; +pub const S_nfsLib_NFSERR_NOSPC: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOSPC as ::c_int; +pub const S_nfsLib_NFSERR_ROFS: ::c_int = + M_nfsStat | nfsstat::NFSERR_ROFS as ::c_int; +pub const S_nfsLib_NFSERR_MLINK: ::c_int = + M_nfsStat | nfsstat::NFSERR_MLINK as ::c_int; +pub const S_nfsLib_NFSERR_NAMETOOLONG: ::c_int = + M_nfsStat | nfsstat::NFSERR_NAMETOOLONG as ::c_int; +pub const S_nfsLib_NFSERR_NOTEMPTY: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOTEMPTY as ::c_int; +pub const S_nfsLib_NFSERR_DQUOT: ::c_int = + M_nfsStat | nfsstat::NFSERR_DQUOT as ::c_int; +pub const S_nfsLib_NFSERR_STALE: ::c_int = + M_nfsStat | nfsstat::NFSERR_STALE as ::c_int; +pub const S_nfsLib_NFSERR_WFLUSH: ::c_int = + M_nfsStat | nfsstat::NFSERR_WFLUSH as ::c_int; +pub const S_nfsLib_NFSERR_REMOTE: ::c_int = + M_nfsStat | nfsstat::NFSERR_REMOTE as ::c_int; +pub const S_nfsLib_NFSERR_BADHANDLE: ::c_int = + M_nfsStat | nfsstat::NFSERR_BADHANDLE as ::c_int; +pub const S_nfsLib_NFSERR_NOT_SYNC: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOT_SYNC as ::c_int; +pub const S_nfsLib_NFSERR_BAD_COOKIE: ::c_int = + M_nfsStat | nfsstat::NFSERR_BAD_COOKIE as ::c_int; +pub const S_nfsLib_NFSERR_NOTSUPP: ::c_int = + M_nfsStat | nfsstat::NFSERR_NOTSUPP as ::c_int; +pub const S_nfsLib_NFSERR_TOOSMALL: ::c_int = + M_nfsStat | nfsstat::NFSERR_TOOSMALL as ::c_int; +pub const S_nfsLib_NFSERR_SERVERFAULT: ::c_int = + M_nfsStat | nfsstat::NFSERR_SERVERFAULT as ::c_int; +pub const S_nfsLib_NFSERR_BADTYPE: ::c_int = + M_nfsStat | nfsstat::NFSERR_BADTYPE as ::c_int; +pub const S_nfsLib_NFSERR_JUKEBOX: ::c_int = + M_nfsStat | nfsstat::NFSERR_JUKEBOX as ::c_int; + +// IP Stuff? These are allll guesswork +pub const IPPROTO_IP: ::c_int = 0; +pub const IP_TTL: ::c_int = 4; // not sure if this is right +pub const IP_ADD_MEMBERSHIP: ::c_int = 11; +pub const IP_DROP_MEMBERSHIP: ::c_int = 12; +pub const IPV6_V6ONLY: ::c_int = 26; +pub const IP_MULTICAST_TTL: ::c_int = 33; +pub const IP_MULTICAST_LOOP: ::c_int = 34; +pub const IPV6_MULTICAST_LOOP: ::c_int = 19; +pub const IPPROTO_IPV6: ::c_int = 41; // or this one, for that matter + +// STAT Stuff +pub const S_IFMT: ::c_int = 0xf000; +pub const S_IFIFO: ::c_int = 0x1000; +pub const S_IFCHR: ::c_int = 0x2000; +pub const S_IFDIR: ::c_int = 0x4000; +pub const S_IFBLK: ::c_int = 0x6000; +pub const S_IFREG: ::c_int = 0x8000; +pub const S_IFLNK: ::c_int = 0xa000; +pub const S_IFSHM: ::c_int = 0xb000; +pub const S_IFDEVMEM: ::c_int = 0xd000; +pub const S_IFSOCK: ::c_int = 0xc000; +pub const S_ISUID: ::c_int = 0x0800; +pub const S_ISGID: ::c_int = 0x0400; +pub const S_ISTXT: ::c_int = 0x0200; +pub const S_IRUSR: ::c_int = 0x0100; +pub const S_IWUSR: ::c_int = 0x0080; +pub const S_IXUSR: ::c_int = 0x0040; +pub const S_IRWXU: ::c_int = 0x01c0; +pub const S_IRGRP: ::c_int = 0x0020; +pub const S_IWGRP: ::c_int = 0x0010; +pub const S_IXGRP: ::c_int = 0x0008; +pub const S_IRWXG: ::c_int = 0x0038; +pub const S_IROTH: ::c_int = 0x0004; +pub const S_IWOTH: ::c_int = 0x0002; +pub const S_IXOTH: ::c_int = 0x0001; +pub const S_IRWXO: ::c_int = 0x0007; + +pub const SOL_SOCKET: ::c_int = 0xffff; +pub const SO_BROADCAST: ::c_int = 0x001e; +pub const SO_SNDTIMEO: ::c_int = 0x1005; +pub const SO_RCVTIMEO: ::c_int = 0x1006; +pub const SOCK_STREAM: ::c_int = 1; +pub const SOCK_DGRAM: ::c_int = 2; +pub const SOCK_RAW: ::c_int = 3; +pub const SOCK_RDM: ::c_int = 4; +pub const SOCK_SEQPACKET: ::c_int = 5; +pub const SOCK_PACKET: ::c_int = 10; +pub const SO_DEBUG: ::c_int = 0x0001; +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_RCVLOWAT: ::c_int = 0x0012; + +pub const _SS_MAXSIZE: usize = 128; +pub const _SS_ALIGNSIZE: usize = size_of::(); +pub const _SS_PAD1SIZE: usize = + (_SS_ALIGNSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>()); +pub const _SS_PAD2SIZE: usize = (_SS_MAXSIZE + - size_of::<::c_uchar>() + - size_of::<::sa_family_t>() + - _SS_PAD1SIZE + - _SS_ALIGNSIZE); + +pub const MSG_OOB: ::c_int = 0x0001; +pub const MSG_PEEK: ::c_int = 0x0002; +pub const MSG_DONTROUTE: ::c_int = 0x0004; +pub const MSG_EOR: ::c_int = 0x0008; +pub const MSG_TRUNC: ::c_int = 0x0010; +pub const MSG_CTRUNC: ::c_int = 0x0020; +pub const MSG_WAITALL: ::c_int = 0x0040; +pub const MSG_DONTWAIT: ::c_int = 0x0080; +pub const MSG_EOF: ::c_int = 0x0100; +pub const MSG_EXP: ::c_int = 0x0200; +pub const MSG_MBUF: ::c_int = 0x0400; +pub const MSG_NOTIFICATION: ::c_int = 0x0800; +pub const MSG_COMPAT: ::c_int = 0x8000; + +pub const AF_UNSPEC: ::c_int = 0; +pub const AF_LOCAL: ::c_int = 1; +pub const AF_UNIX: ::c_int = AF_LOCAL; +pub const AF_INET: ::c_int = 2; +pub const AF_NETLINK: ::c_int = 16; +pub const AF_ROUTE: ::c_int = 17; +pub const AF_LINK: ::c_int = 18; +pub const AF_PACKET: ::c_int = 19; +pub const pseudo_AF_KEY: ::c_int = 27; +pub const AF_KEY: ::c_int = pseudo_AF_KEY; +pub const AF_INET6: ::c_int = 28; +pub const AF_SOCKDEV: ::c_int = 31; +pub const AF_TIPC: ::c_int = 33; +pub const AF_MIPC: ::c_int = 34; +pub const AF_MIPC_SAFE: ::c_int = 35; +pub const AF_MAX: ::c_int = 36; + +pub const SHUT_RD: ::c_int = 0; +pub const SHUT_WR: ::c_int = 1; +pub const SHUT_RDWR: ::c_int = 2; + +pub const IPPROTO_TCP: ::c_int = 6; +pub const TCP_NODELAY: ::c_int = 1; +pub const TCP_MAXSEG: ::c_int = 2; +pub const TCP_NOPUSH: ::c_int = 3; +pub const TCP_KEEPIDLE: ::c_int = 4; +pub const TCP_KEEPINTVL: ::c_int = 5; +pub const TCP_KEEPCNT: ::c_int = 6; +pub const SO_ERROR: ::c_int = 4; + +// IO Lib Definitions: + +pub const FIONREAD: ::c_int = 1; +pub const FIOFLUSH: ::c_int = 2; +pub const FIOOPTIONS: ::c_int = 3; +pub const FIOBAUDRATE: ::c_int = 4; +pub const FIODISKFORMAT: ::c_int = 5; +pub const FIODISKINIT: ::c_int = 6; +pub const FIOSEEK: ::c_int = 7; +pub const FIOWHERE: ::c_int = 8; +pub const FIODIRENTRY: ::c_int = 9; +pub const FIORENAME: ::c_int = 10; +pub const FIOREADYCHANGE: ::c_int = 11; +pub const FIOWRITE: ::c_int = 12; +pub const FIODISKCHANGE: ::c_int = 13; +pub const FIOCANCEL: ::c_int = 14; +pub const FIOSQUEEZE: ::c_int = 15; +pub const FIONBIO: ::c_int = -1878786032; // it goes on ... +pub const _POSIX_PATH_MAX: ::c_int = 256; + +// Some poll stuff +pub const POLLIN: ::c_short = 0x0001; +pub const POLLPRI: ::c_short = 0x0002; +pub const POLLOUT: ::c_short = 0x0004; +pub const POLLRDNORM: ::c_short = 0x0040; +pub const POLLWRNORM: ::c_short = POLLOUT; +pub const POLLRDBAND: ::c_short = 0x0080; +pub const POLLWRBAND: ::c_short = 0x0100; +pub const POLLER: ::c_short = 0x0008; +pub const POLLHUP: ::c_short = 0x0010; +pub const POLLNVAL: ::c_short = 0x0020; + +//Some Fcntlcom Stuff (look at fcntlcom.h to find definitions) +pub const FD_CLOEXEC: ::c_int = 1; +pub const F_DUPFD: ::c_int = 0; +pub const F_GETFD: ::c_int = 1; +pub const F_SETFD: ::c_int = 2; +pub const F_GETFL: ::c_int = 3; +pub const F_SETFL: ::c_int = 4; +pub const F_GETOWN: ::c_int = 5; +pub const F_SETOWN: ::c_int = 6; +pub const F_GETLK: ::c_int = 7; +pub const F_SETLK: ::c_int = 8; +pub const F_SETLKW: ::c_int = 9; +pub const F_DUPFD_CLOEXEC: ::c_int = 14; + +//Some Dirent.h stuff +pub const DT_UNKNOWN: ::c_uchar = 0x0; +pub const DT_FIFO: ::c_uchar = 0x1; +pub const DT_CHR: ::c_uchar = 0x2; +pub const DT_DIR: ::c_uchar = 0x4; +pub const DT_BLK: ::c_uchar = 0x6; +pub const DT_REG: ::c_uchar = 0x8; +pub const DT_LNK: ::c_uchar = 0xA; +pub const DT_SOCK: ::c_uchar = 0xC; +pub const DT_WHT: ::c_uchar = 0xE; + +// Other Random Stuff +pub const VXSIM_EWOULDBLOCK: ::c_int = 70; +pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; +pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; + +pub const SIG_DFL: sighandler_t = 0 as sighandler_t; +pub const SIG_IGN: sighandler_t = 1 as sighandler_t; +pub const SIG_ERR: sighandler_t = !0 as sighandler_t; + +pub const SIGHUP: ::c_int = 1; +pub const SIGINT: ::c_int = 2; +pub const SIGQUIT: ::c_int = 3; +pub const SIGILL: ::c_int = 4; +pub const SIGTRAP: ::c_int = 5; +pub const SIGABRT: ::c_int = 6; +pub const SIGEMT: ::c_int = 7; +pub const SIGFPE: ::c_int = 8; +pub const SIGKILL: ::c_int = 9; +pub const SIGBUS: ::c_int = 10; +pub const SIGSEGV: ::c_int = 11; +pub const SIGFMT: ::c_int = 12; +pub const SIGPIPE: ::c_int = 13; +pub const SIGALRM: ::c_int = 14; +pub const SIGTERM: ::c_int = 15; +pub const SIGCNCL: ::c_int = 16; +pub const SIGSTOP: ::c_int = 17; +pub const SIGTSTP: ::c_int = 18; +pub const SIGCONT: ::c_int = 19; +pub const SIGCHLD: ::c_int = 20; +pub const SIGTTIN: ::c_int = 21; +pub const SIGTTOU: ::c_int = 22; + +pub const SIG_BLOCK: ::c_int = 1; +pub const SIG_UNBLOCK: ::c_int = 2; +pub const SIG_SETMASK: ::c_int = 3; + +pub const SI_SYNC: ::c_int = 0; +pub const SI_USER: ::c_int = -1; +pub const SI_QUEUE: ::c_int = -2; +pub const SI_TIMER: ::c_int = -3; +pub const SI_ASYNCIO: ::c_int = -4; +pub const SI_MESGQ: ::c_int = -5; +pub const SI_CHILD: ::c_int = -6; +pub const SI_KILL: ::c_int = SI_USER; + +// vxParams.h definitions +pub const _PARM_NAME_MAX: usize = 255; +pub const _PARM_PATH_MAX: usize = 1024; + +// WAIT STUFF +pub const WNOHANG: ::c_int = 0x01; +pub const WUNTRACED: ::c_int = 0x02; + +const PTHREAD_MUTEXATTR_INITIALIZER: pthread_mutexattr_t = + pthread_mutexattr_t { + mutexAttrStatus: PTHREAD_INITIALIZED_OBJ, + mutexAttrProtocol: PTHREAD_PRIO_NONE, + mutexAttrPrioceiling: 0, + mutexAttrType: PTHREAD_MUTEX_DEFAULT, + mutexAttrPshared: 1, + }; +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + mutexSemId: null_mut(), + mutexValid: PTHREAD_VALID_OBJ, + mutexInitted: PTHREAD_UNUSED_YET_OBJ, + mutexCondRefCount: 0, + mutexSavPriority: 0, + mutexAttr: PTHREAD_MUTEXATTR_INITIALIZER, + mutexSemName: [0; PTHREAD_SHARED_SEM_NAME_MAX], +}; + +const PTHREAD_CONDATTR_INITIALIZER: pthread_condattr_t = pthread_condattr_t { + condAttrStatus: 0, + condAttrPshared: 0, + _CondAttrClockId: CLOCK_REALTIME, +}; +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + condSemId: null_mut(), + condValid: PTHREAD_VALID_OBJ, + condInitted: PTHREAD_UNUSED_YET_OBJ, + condRefCount: 0, + condMutex: null_mut(), + condAttr: PTHREAD_CONDATTR_INITIALIZER, + condSemName: [0; PTHREAD_SHARED_SEM_NAME_MAX], +}; + +const PTHREAD_RWLOCKATTR_INITIALIZER: pthread_rwlockattr_t = + pthread_rwlockattr_t { + rwlockAttrStatus: PTHREAD_INITIALIZED_OBJ, + rwlockAttrMaxReaders: 0, + }; +pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + rwlockSemId: null_mut(), + rwlockReadersRefCount: 0, + rwlockValid: PTHREAD_VALID_OBJ, + rwlockInitted: PTHREAD_UNUSED_YET_OBJ, + rwlockAttr: PTHREAD_RWLOCKATTR_INITIALIZER, + rwlockName: [0; PTHREAD_SHARED_SEM_NAME_MAX], +}; + +pub const SEEK_SET: ::c_int = 0; +pub const SEEK_CUR: ::c_int = 1; +pub const SEEK_END: ::c_int = 2; + +// rtpLibCommon.h +pub const VX_RTP_NAME_LENGTH: usize = 255; + +//Some unsupported stuff +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = -1; // Via unistd.h +pub const _SC_PAGESIZE: ::c_int = 64; +pub const O_ACCMODE: ::c_int = 3; +pub const O_CLOEXEC: ::c_int = 0x100000; // fcntlcom +pub const O_EXCL: ::c_int = 0x0800; +pub const O_CREAT: ::c_int = 0x0200; +pub const O_TRUNC: ::c_int = 0x0400; +pub const O_APPEND: ::c_int = 0x0008; +pub const O_RDWR: ::c_int = 2; +pub const O_WRONLY: ::c_int = 1; +pub const O_RDONLY: ::c_int = 0; +pub const O_NONBLOCK: ::c_int = 0x4; + +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum FILE {} +impl ::Copy for FILE {} +impl ::Clone for FILE { + fn clone(&self) -> FILE { + *self + } +} +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum fpos_t {} // TODO: fill this out with a struct +impl ::Copy for fpos_t {} +impl ::Clone for fpos_t { + fn clone(&self) -> fpos_t { + *self + } +} + +extern { + pub fn isalnum(c: c_int) -> c_int; + pub fn isalpha(c: c_int) -> c_int; + pub fn iscntrl(c: c_int) -> c_int; + pub fn isdigit(c: c_int) -> c_int; + pub fn isgraph(c: c_int) -> c_int; + pub fn islower(c: c_int) -> c_int; + pub fn isprint(c: c_int) -> c_int; + pub fn ispunct(c: c_int) -> c_int; + pub fn isspace(c: c_int) -> c_int; + pub fn isupper(c: c_int) -> c_int; + pub fn isxdigit(c: c_int) -> c_int; + pub fn tolower(c: c_int) -> c_int; + pub fn toupper(c: c_int) -> c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "fopen$UNIX2003" + )] + pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "freopen$UNIX2003" + )] + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + file: *mut FILE, + ) -> *mut FILE; + pub fn fflush(file: *mut FILE) -> c_int; + pub fn fclose(file: *mut FILE) -> c_int; + pub fn remove(filename: *const c_char) -> c_int; + pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; + pub fn tmpfile() -> *mut FILE; + pub fn setvbuf( + stream: *mut FILE, + buffer: *mut c_char, + mode: c_int, + size: size_t, + ) -> c_int; + pub fn setbuf(stream: *mut FILE, buf: *mut c_char); + pub fn getchar() -> c_int; + pub fn putchar(c: c_int) -> c_int; + pub fn fgetc(stream: *mut FILE) -> c_int; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) + -> *mut c_char; + pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "fputs$UNIX2003" + )] + pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; + pub fn puts(s: *const c_char) -> c_int; + pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; + pub fn fread( + ptr: *mut c_void, + size: size_t, + nobj: size_t, + stream: *mut FILE, + ) -> size_t; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "fwrite$UNIX2003" + )] + pub fn fwrite( + ptr: *const c_void, + size: size_t, + nobj: size_t, + stream: *mut FILE, + ) -> size_t; + pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; + pub fn ftell(stream: *mut FILE) -> c_long; + pub fn rewind(stream: *mut FILE); + #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")] + pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")] + pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; + pub fn feof(stream: *mut FILE) -> c_int; + pub fn ferror(stream: *mut FILE) -> c_int; + pub fn perror(s: *const c_char); + pub fn atoi(s: *const c_char) -> c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "strtod$UNIX2003" + )] + pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; + pub fn strtol( + s: *const c_char, + endp: *mut *mut c_char, + base: c_int, + ) -> c_long; + pub fn strtoul( + s: *const c_char, + endp: *mut *mut c_char, + base: c_int, + ) -> c_ulong; + pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; + pub fn malloc(size: size_t) -> *mut c_void; + pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; + pub fn free(p: *mut c_void); + pub fn abort() -> !; + pub fn exit(status: c_int) -> !; + // pub fn _exit(status: c_int) -> !; + pub fn atexit(cb: extern fn()) -> c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "system$UNIX2003" + )] + pub fn system(s: *const c_char) -> c_int; + pub fn getenv(s: *const c_char) -> *mut c_char; + + pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; + pub fn strncpy( + dst: *mut c_char, + src: *const c_char, + n: size_t, + ) -> *mut c_char; + pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; + pub fn strncat( + s: *mut c_char, + ct: *const c_char, + n: size_t, + ) -> *mut c_char; + pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; + pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strdup(cs: *const c_char) -> *mut c_char; + pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; + pub fn strncasecmp( + s1: *const c_char, + s2: *const c_char, + n: size_t, + ) -> c_int; + pub fn strlen(cs: *const c_char) -> size_t; + pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "strerror$UNIX2003" + )] + pub fn strerror(n: c_int) -> *mut c_char; + pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; + pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; + pub fn wcslen(buf: *const wchar_t) -> size_t; + pub fn wcstombs( + dest: *mut c_char, + src: *const wchar_t, + n: size_t, + ) -> ::size_t; + + pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; + pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; + pub fn memcpy( + dest: *mut c_void, + src: *const c_void, + n: size_t, + ) -> *mut c_void; + pub fn memmove( + dest: *mut c_void, + src: *const c_void, + n: size_t, + ) -> *mut c_void; + pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; +} + +extern { + #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam50")] + pub fn getpwnam(name: *const ::c_char) -> *mut passwd; + #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid50")] + pub fn getpwuid(uid: ::uid_t) -> *mut passwd; + + pub fn fprintf( + stream: *mut ::FILE, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn printf(format: *const ::c_char, ...) -> ::c_int; + pub fn snprintf( + s: *mut ::c_char, + n: ::size_t, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; + pub fn fscanf( + stream: *mut ::FILE, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn scanf(format: *const ::c_char, ...) -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) + -> ::c_int; + pub fn getchar_unlocked() -> ::c_int; + pub fn putchar_unlocked(c: ::c_int) -> ::c_int; + + pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; + + pub fn pclose(stream: *mut ::FILE) -> ::c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "fdopen$UNIX2003" + )] + pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; + pub fn fileno(stream: *mut ::FILE) -> ::c_int; + + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "open$UNIX2003" + )] + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "creat$UNIX2003" + )] + pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; + + pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; + + pub fn rewinddir(dirp: *mut ::DIR); + + pub fn openat( + dirfd: ::c_int, + pathname: *const ::c_char, + flags: ::c_int, + ... + ) -> ::c_int; + pub fn fchmodat( + dirfd: ::c_int, + pathname: *const ::c_char, + mode: ::mode_t, + flags: ::c_int, + ) -> ::c_int; + pub fn fchown(fd: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int; + pub fn fchownat( + dirfd: ::c_int, + pathname: *const ::c_char, + owner: ::uid_t, + group: ::gid_t, + flags: ::c_int, + ) -> ::c_int; + #[cfg_attr(target_os = "macos", link_name = "fstatat$INODE64")] + #[cfg_attr(target_os = "freebsd", link_name = "fstatat@FBSD_1.1")] + pub fn fstatat( + dirfd: ::c_int, + pathname: *const ::c_char, + buf: *mut stat, + flags: ::c_int, + ) -> ::c_int; + pub fn linkat( + olddirfd: ::c_int, + oldpath: *const ::c_char, + newdirfd: ::c_int, + newpath: *const ::c_char, + flags: ::c_int, + ) -> ::c_int; + pub fn mkdirat( + dirfd: ::c_int, + pathname: *const ::c_char, + mode: ::mode_t, + ) -> ::c_int; + pub fn readlinkat( + dirfd: ::c_int, + pathname: *const ::c_char, + buf: *mut ::c_char, + bufsiz: ::size_t, + ) -> ::ssize_t; + pub fn renameat( + olddirfd: ::c_int, + oldpath: *const ::c_char, + newdirfd: ::c_int, + newpath: *const ::c_char, + ) -> ::c_int; + pub fn symlinkat( + target: *const ::c_char, + newdirfd: ::c_int, + linkpath: *const ::c_char, + ) -> ::c_int; + + pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; + pub fn alarm(seconds: ::c_uint) -> ::c_uint; + pub fn fchdir(dirfd: ::c_int) -> ::c_int; + pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "lchown$UNIX2003" + )] + pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; + pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> ::c_int; + pub fn execle( + path: *const ::c_char, + arg0: *const ::c_char, + ... + ) -> ::c_int; + pub fn execlp( + file: *const ::c_char, + arg0: *const ::c_char, + ... + ) -> ::c_int; + pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; + pub fn execve( + prog: *const c_char, + argv: *const *const c_char, + envp: *const *const c_char, + ) -> ::c_int; + /* + pub fn execvp(c: *const c_char, + argv: *const *const c_char) -> ::c_int; + */ + // pub fn fork() -> pid_t; + pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; + pub fn getegid() -> gid_t; + pub fn geteuid() -> uid_t; + pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; + pub fn getlogin() -> *mut c_char; + pub fn getopt( + argc: ::c_int, + argv: *const *mut c_char, + optstr: *const c_char, + ) -> ::c_int; + pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; + pub fn pause() -> ::c_int; + pub fn seteuid(uid: uid_t) -> ::c_int; + pub fn setegid(gid: gid_t) -> ::c_int; + pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int; + pub fn setsid() -> pid_t; + pub fn sleep(secs: ::c_uint) -> ::c_uint; + pub fn tcgetpgrp(fd: ::c_int) -> pid_t; + pub fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int; + pub fn ttyname(fd: ::c_int) -> *mut c_char; + pub fn wait(status: *mut ::c_int) -> pid_t; + /* + pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, + offset: off_t) -> ::ssize_t; + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "pwrite$UNIX2003")] + pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, + offset: off_t) -> ::ssize_t; + */ + pub fn umask(mask: mode_t) -> mode_t; + + // #[cfg_attr(target_os = "netbsd", link_name = "__utime50")] + // pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int; + + /* + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "kill$UNIX2003")] + pub fn kill(pid: pid_t, sig: ::c_int) -> ::c_int; + */ + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "killpg$UNIX2003" + )] + pub fn killpg(pgrp: pid_t, sig: ::c_int) -> ::c_int; + + pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; + pub fn munlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; + pub fn mlockall(flags: ::c_int) -> ::c_int; + pub fn munlockall() -> ::c_int; + + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "mmap$UNIX2003" + )] + pub fn mmap( + addr: *mut ::c_void, + len: ::size_t, + prot: ::c_int, + flags: ::c_int, + fd: ::c_int, + offset: off_t, + ) -> *mut ::c_void; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "munmap$UNIX2003" + )] + pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; + + pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint; + pub fn if_indextoname( + ifindex: ::c_uint, + ifname: *mut ::c_char, + ) -> *mut ::c_char; + + pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; + + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "getrlimit$UNIX2003" + )] + pub fn getrlimit(resource: ::c_int, rlim: *mut rlimit) -> ::c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "setrlimit$UNIX2003" + )] + pub fn setrlimit(resource: ::c_int, rlim: *const rlimit) -> ::c_int; + // #[cfg_attr(target_os = "netbsd", link_name = "__getrusage50")] + // pub fn getrusage(resource: ::c_int, usage: *mut rusage) -> ::c_int; + + /* + #[cfg_attr(any(target_os = "macos", target_os = "ios"), + link_name = "realpath$DARWIN_EXTSN")] + pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) + -> *mut ::c_char; + */ + pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int; + + #[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")] + pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; + pub fn pthread_exit(value: *mut ::c_void); + pub fn pthread_attr_setdetachstate( + attr: *mut ::pthread_attr_t, + state: ::c_int, + ) -> ::c_int; + + pub fn strerror_r( + errnum: ::c_int, + buf: *mut c_char, + buflen: ::size_t, + ) -> ::c_int; + + pub fn sigaction( + signum: ::c_int, + act: *const sigaction, + oldact: *mut sigaction, + ) -> ::c_int; + + #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")] + pub fn utimes( + filename: *const ::c_char, + times: *const ::timeval, + ) -> ::c_int; + pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; + pub fn dlerror() -> *mut ::c_char; + pub fn dlsym( + handle: *mut ::c_void, + symbol: *const ::c_char, + ) -> *mut ::c_void; + pub fn dlclose(handle: *mut ::c_void) -> ::c_int; + pub fn res_init() -> ::c_int; + /* + #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] + pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; + #[cfg_attr(target_os = "netbsd", link_name = "__localtime_r50")] + pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; + #[cfg_attr(all(target_os = "macos", target_arch = "x86"), + link_name = "mktime$UNIX2003")] + #[cfg_attr(target_os = "netbsd", link_name = "__mktime50")] + pub fn mktime(tm: *mut tm) -> time_t; + #[cfg_attr(target_os = "netbsd", link_name = "__time50")] + pub fn time(time: *mut time_t) -> time_t; + #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")] + pub fn gmtime(time_p: *const time_t) -> *mut tm; + #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")] + pub fn localtime(time_p: *const time_t) -> *mut tm; + */ + #[cfg_attr(target_os = "netbsd", link_name = "__difftime50")] + pub fn difftime(time1: time_t, time0: time_t) -> ::c_double; + + #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] + #[cfg_attr(target_os = "freebsd", link_name = "mknod@FBSD_1.0")] + pub fn mknod( + pathname: *const ::c_char, + mode: ::mode_t, + dev: ::dev_t, + ) -> ::c_int; + pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; + // pub fn getservbyname(name: *const ::c_char, + // proto: *const ::c_char) -> *mut servent; + // pub fn getprotobyname(name: *const ::c_char) -> *mut protoent; + // pub fn getprotobynumber(proto: ::c_int) -> *mut protoent; + pub fn chroot(name: *const ::c_char) -> ::c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "usleep$UNIX2003" + )] + pub fn usleep(secs: ::c_uint) -> ::c_int; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "putenv$UNIX2003" + )] + pub fn putenv(string: *mut c_char) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__select50")] + // pub fn select(nfds: ::c_int, + // readfs: *mut fd_set, + // writefds: *mut fd_set, + // errorfds: *mut fd_set, + // timeout: *mut timeval) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__setlocale50")] + pub fn setlocale( + category: ::c_int, + locale: *const ::c_char, + ) -> *mut ::c_char; + // pub fn localeconv() -> *mut lconv; + + pub fn sigprocmask( + how: ::c_int, + set: *const sigset_t, + oldset: *mut sigset_t, + ) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] + pub fn sigpending(set: *mut sigset_t) -> ::c_int; + + pub fn getsid(pid: pid_t) -> pid_t; + + pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; + + pub fn fseeko( + stream: *mut ::FILE, + offset: ::off_t, + whence: ::c_int, + ) -> ::c_int; + pub fn ftello(stream: *mut ::FILE) -> ::off_t; + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "tcdrain$UNIX2003" + )] + pub fn tcdrain(fd: ::c_int) -> ::c_int; + pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; + pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; + pub fn tcgetsid(fd: ::c_int) -> ::pid_t; + pub fn tcsendbreak(fd: ::c_int, duration: ::c_int) -> ::c_int; + pub fn mkstemp(template: *mut ::c_char) -> ::c_int; + pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char; + + pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char; + + pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int); + pub fn closelog(); + pub fn setlogmask(maskpri: ::c_int) -> ::c_int; + #[cfg_attr(target_os = "macos", link_name = "syslog$DARWIN_EXTSN")] + pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); + #[cfg_attr( + all(target_os = "macos", target_arch = "x86"), + link_name = "nice$UNIX2003" + )] + pub fn nice(incr: ::c_int) -> ::c_int; + + pub fn grantpt(fd: ::c_int) -> ::c_int; + pub fn posix_openpt(flags: ::c_int) -> ::c_int; + pub fn ptsname(fd: ::c_int) -> *mut ::c_char; + pub fn unlockpt(fd: ::c_int) -> ::c_int; + + pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn getline( + lineptr: *mut *mut c_char, + n: *mut size_t, + stream: *mut FILE, + ) -> ssize_t; + + pub fn _rtld_dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; +} + +extern { + // this is gonna be a big one + + // stdlib.h + // This function may not be defined for armv7 + pub fn memalign(block_size: ::size_t, size_arg: ::size_t) + -> *mut ::c_void; + + // ioLib.h + pub fn getcwd(buf: *mut ::c_char, size: ::size_t) -> *mut ::c_char; + + // ioLib.h + pub fn chdir(attr: *const ::c_char) -> ::c_int; + + // pthread.h + pub fn pthread_mutexattr_init( + /* PTHREAD STUFF */ + attr: *mut pthread_mutexattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_mutexattr_destroy( + attr: *mut pthread_mutexattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_mutexattr_settype( + pAttr: *mut ::pthread_mutexattr_t, + pType: ::c_int, + ) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_init( + mutex: *mut pthread_mutex_t, + attr: *const pthread_mutexattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_timedlock( + attr: *mut pthread_mutex_t, + spec: *const timespec, + ) -> ::c_int; + + // pthread.h + pub fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> ::c_int; + + // pthread.h + pub fn pthread_attr_setname( + pAttr: *mut ::pthread_attr_t, + name: *mut ::c_char, + ) -> ::c_int; + + // pthread.h + pub fn pthread_attr_setstacksize( + attr: *mut ::pthread_attr_t, + stacksize: ::size_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_attr_getstacksize( + attr: *const ::pthread_attr_t, + size: *mut ::size_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; + + // pthread.h + pub fn pthread_create( + pThread: *mut ::pthread_t, + pAttr: *const ::pthread_attr_t, + start_routine: extern fn(*mut ::c_void) -> *mut ::c_void, + value: *mut ::c_void, + ) -> ::c_int; + + // pthread.h + pub fn pthread_attr_destroy(thread: *mut ::pthread_attr_t) -> ::c_int; + + // pthread.h + pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; + + // int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); + pub fn pthread_atfork( + prepare: ::Option, + parent: ::Option, + child: ::Option, + ) -> ::c_int; + // stat.h + pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; + + // stat.h + pub fn lstat(path: *const ::c_char, buf: *mut stat) -> ::c_int; + + // unistd.h + pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; + + // dirent.h + pub fn readdir_r( + pDir: *mut ::DIR, + entry: *mut ::dirent, + result: *mut *mut ::dirent, + ) -> ::c_int; + + // dirent.h + pub fn readdir(pDir: *mut ::DIR) -> *mut ::dirent; + + // fcntl.h or + // ioLib.h + pub fn open( + // this might be hacked + path: *const ::c_char, + oflag: ::c_int, + ... + ) -> ::c_int; + + // poll.h + pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; + + // pthread.h + pub fn pthread_condattr_init(attr: *mut ::pthread_condattr_t) -> ::c_int; + + // pthread.h + pub fn pthread_condattr_destroy( + attr: *mut ::pthread_condattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_condattr_getclock( + pAttr: *const ::pthread_condattr_t, + pClockId: *mut ::clockid_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_condattr_setclock( + pAttr: *mut ::pthread_condattr_t, + clockId: ::clockid_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_cond_init( + cond: *mut ::pthread_cond_t, + attr: *const ::pthread_condattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int; + + // pthread.h + pub fn pthread_cond_signal(cond: *mut ::pthread_cond_t) -> ::c_int; + + // pthread.h + pub fn pthread_cond_broadcast(cond: *mut ::pthread_cond_t) -> ::c_int; + + // pthread.h + pub fn pthread_cond_wait( + cond: *mut ::pthread_cond_t, + mutex: *mut ::pthread_mutex_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlockattr_init( + attr: *mut ::pthread_rwlockattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlockattr_destroy( + attr: *mut ::pthread_rwlockattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlockattr_setmaxreaders( + attr: *mut ::pthread_rwlockattr_t, + attr2: ::c_uint, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_init( + attr: *mut ::pthread_rwlock_t, + host: *const ::pthread_rwlockattr_t, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_destroy(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_rdlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_tryrdlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_timedrdlock( + attr: *mut ::pthread_rwlock_t, + host: *const ::timespec, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_wrlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_trywrlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_timedwrlock( + attr: *mut ::pthread_rwlock_t, + host: *const ::timespec, + ) -> ::c_int; + + // pthread.h + pub fn pthread_rwlock_unlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; + + // pthread.h + pub fn pthread_key_create( + key: *mut ::pthread_key_t, + dtor: ::Option, + ) -> ::c_int; + + // pthread.h + pub fn pthread_key_delete(key: ::pthread_key_t) -> ::c_int; + + // pthread.h + pub fn pthread_setspecific( + key: ::pthread_key_t, + value: *const ::c_void, + ) -> ::c_int; + + // pthread.h + pub fn pthread_getspecific(key: ::pthread_key_t) -> *mut ::c_void; + + // pthread.h + pub fn pthread_cond_timedwait( + cond: *mut ::pthread_cond_t, + mutex: *mut ::pthread_mutex_t, + abstime: *const ::timespec, + ) -> ::c_int; + + // pthread.h + pub fn pthread_attr_getname( + attr: *mut ::pthread_attr_t, + name: *mut *mut ::c_char, + ) -> ::c_int; + + // pthread.h + pub fn pthread_join( + thread: ::pthread_t, + status: *mut *mut ::c_void, + ) -> ::c_int; + + // pthread.h + pub fn pthread_self() -> ::pthread_t; + + // clockLib.h + pub fn clock_gettime( + clock_id: ::clockid_t, + tp: *mut ::timespec, + ) -> ::c_int; + + // clockLib.h + pub fn clock_settime( + clock_id: ::clockid_t, + tp: *const ::timespec, + ) -> ::c_int; + + // clockLib.h + pub fn clock_getres( + clock_id: ::clockid_t, + res: *mut ::timespec, + ) -> ::c_int; + + // clockLib.h + pub fn clock_nanosleep( + clock_id: ::clockid_t, + flags: ::c_int, + rqtp: *const ::timespec, + rmtp: *mut ::timespec, + ) -> ::c_int; + + // timerLib.h + pub fn nanosleep( + rqtp: *const ::timespec, + rmtp: *mut ::timespec, + ) -> ::c_int; + + // socket.h + pub fn accept( + s: ::c_int, + addr: *mut ::sockaddr, + addrlen: *mut ::socklen_t, + ) -> ::c_int; + + // socket.h + pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) + -> ::c_int; + + // socket.h + pub fn connect( + s: ::c_int, + name: *const ::sockaddr, + namelen: ::socklen_t, + ) -> ::c_int; + + // socket.h + pub fn getpeername( + s: ::c_int, + name: *mut ::sockaddr, + namelen: *mut ::socklen_t, + ) -> ::c_int; + + // socket.h + pub fn getsockname( + socket: ::c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, + ) -> ::c_int; + + // socket.h + pub fn getsockopt( + sockfd: ::c_int, + level: ::c_int, + optname: ::c_int, + optval: *mut ::c_void, + optlen: *mut ::socklen_t, + ) -> ::c_int; + + // socket.h + pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; + + // socket.h + pub fn recv( + s: ::c_int, + buf: *mut ::c_void, + bufLen: ::size_t, + flags: ::c_int, + ) -> ::ssize_t; + + // socket.h + pub fn recvfrom( + s: ::c_int, + buf: *mut ::c_void, + bufLen: ::size_t, + flags: ::c_int, + from: *mut ::sockaddr, + pFromLen: *mut ::socklen_t, + ) -> ::ssize_t; + + // socket.h + pub fn send( + socket: ::c_int, + buf: *const ::c_void, + len: ::size_t, + flags: ::c_int, + ) -> ::ssize_t; + + // socket.h + pub fn sendto( + socket: ::c_int, + buf: *const ::c_void, + len: ::size_t, + flags: ::c_int, + addr: *const sockaddr, + addrlen: socklen_t, + ) -> ::ssize_t; + + // socket.h + pub fn setsockopt( + socket: ::c_int, + level: ::c_int, + name: ::c_int, + value: *const ::c_void, + option_len: socklen_t, + ) -> ::c_int; + + // socket.h + pub fn shutdown(s: ::c_int, how: ::c_int) -> ::c_int; + + // socket.h + pub fn socket( + domain: ::c_int, + _type: ::c_int, + protocol: ::c_int, + ) -> ::c_int; + + pub fn socketpair( + // Doesn't exist + domain: ::c_int, + type_: ::c_int, + protocol: ::c_int, + socket_vector: *mut ::c_int, + ) -> ::c_int; + + // icotl.h + pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; + + // fcntl.h + pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; + + // ntp_rfc2553.h for kernel + // netdb.h for user + pub fn gai_strerror(errcode: ::c_int) -> *mut ::c_char; + + // ioLib.h or + // unistd.h + pub fn close(fd: ::c_int) -> ::c_int; + + // ioLib.h or + // unistd.h + pub fn read( + // Since this is from FD< big errors might happen + fd: ::c_int, + buf: *mut ::c_void, + count: ::size_t, + ) -> ::ssize_t; + + // ioLib.h or + // unistd.h + pub fn write( + fd: ::c_int, + buf: *const ::c_void, + count: ::size_t, + ) -> ::ssize_t; + + // ioLib.h or + // unistd.h + pub fn isatty(fd: ::c_int) -> ::c_int; + + // ioLib.h or + // unistd.h + pub fn dup(src: ::c_int) -> ::c_int; + + // ioLib.h or + // unistd.h + pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; + + // ioLib.h or + // unistd.h + pub fn pipe(fds: *mut ::c_int) -> ::c_int; + + // ioLib.h or + // unistd.h + pub fn unlink(pathname: *const ::c_char) -> ::c_int; + + // unistd.h and + // ioLib.h + pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; + + // netdb.h + pub fn getaddrinfo( + node: *const ::c_char, + service: *const ::c_char, + hints: *const addrinfo, + res: *mut *mut addrinfo, + ) -> ::c_int; + + // netdb.h + pub fn freeaddrinfo(res: *mut addrinfo); + + // signal.h + pub fn signal( + // Probably wrong ... + signum: ::c_int, + handler: sighandler_t, + ) -> sighandler_t; + + // unistd.h + pub fn getpid() -> ::c_int; //should be pid_t, but is being dodged + + // unistd.h + pub fn getppid() -> ::c_int; + + // wait.h + pub fn waitpid( + pid: ::c_int, //should be pid_t, but is being dodged + status: *mut ::c_int, + optons: ::c_int, + ) -> ::c_int; //should be pid_t, but is being dodged + + // unistd.h + pub fn sysconf(attr: ::c_int) -> ::c_long; + + // unistd.h + // For user space, return value is static inline int + // For kernel space, exactly how it should be + pub fn getpagesize() -> ::c_int; + + // stdlib.h + pub fn setenv( + // setenv.c + envVarName: *const ::c_char, + envVarValue: *const ::c_char, + overwrite: ::c_int, + ) -> ::c_int; + + // stdlib.h + pub fn unsetenv( + // setenv.c + envVarName: *const ::c_char, + ) -> ::c_int; + + // unistd.h + pub fn link(src: *const ::c_char, dst: *const ::c_char) -> ::c_int; + + // unistd.h + pub fn readlink( + path: *const ::c_char, + buf: *mut ::c_char, + bufsize: ::size_t, + ) -> ::ssize_t; + + // unistd.h + pub fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int; + + // dirent.h + pub fn opendir(name: *const ::c_char) -> *mut ::DIR; + + // unistd.h + pub fn rmdir(path: *const ::c_char) -> ::c_int; + + // stat.h + pub fn mkdir(dirName: *const ::c_char, mode: ::mode_t) -> ::c_int; + + // stat.h + pub fn chmod(path: *const ::c_char, mode: ::mode_t) -> ::c_int; + + // stat.h + pub fn fchmod(attr1: ::c_int, attr2: ::mode_t) -> ::c_int; + + // unistd.h + pub fn fsync(fd: ::c_int) -> ::c_int; + + // dirent.h + pub fn closedir(ptr: *mut ::DIR) -> ::c_int; + + pub fn pwrite64( + fd: ::c_int, // if you want to use fd, you gotta fix these + buf: *const ::c_void, + count: ::size_t, + offset: off64_t, + ) -> ::ssize_t; + + pub fn pread64( + fd: ::c_int, + buf: *const ::c_void, + count: ::size_t, + offset: off64_t, + ) -> ::ssize_t; + + // sched.h + pub fn sched_yield() -> ::c_int; + + // errnoLib.h + pub fn errnoSet(err: ::c_int) -> ::c_int; + + // errnoLib.h + pub fn errnoGet() -> ::c_int; + + pub fn fork(// Does not exist at all + ) -> ::c_int; + + // unistd.h + pub fn _exit(status: ::c_int) -> !; + + // unistd.h + pub fn setgid(gid: ::gid_t) -> ::c_int; + + // unistd.h + pub fn getgid() -> ::gid_t; + + // unistd.h + pub fn setuid(uid: ::uid_t) -> ::c_int; + + // unistd.h + pub fn getuid() -> ::uid_t; + + pub fn setgroups( + // Does not exist at all + ngroups: ::c_int, + grouplist: *const ::gid_t, + ) -> ::c_int; + + // signal.h + pub fn sigemptyset(__set: *mut sigset_t) -> ::c_int; + + // pthread.h for kernel + // signal.h for user + pub fn pthread_sigmask( + __how: ::c_int, + __set: *const sigset_t, + __oset: *mut sigset_t, + ) -> ::c_int; + + pub fn execvp( + // Does not exist at all + c: *const ::c_char, + argv: *const *const ::c_char, + ) -> ::c_int; + + // signal.h for user + pub fn kill( + __pid: ::c_int, //should be pid_t, but is being dodged + __signo: ::c_int, + ) -> ::c_int; + + // signal.h for user + pub fn sigqueue( + __pid: ::c_int, //should be pid_t, but is being dodged + __signo: ::c_int, + __value: ::size_t, // Actual type is const union sigval value, + // which is a union of int and void * + ) -> ::c_int; + + // signal.h for user + pub fn _sigqueue( + rtpId: ::RTP_ID, + signo: ::c_int, + pValue: *mut ::size_t, // Actual type is const union * sigval value, + // which is a union of int and void * + sigCode: ::c_int, + ) -> ::c_int; + + // signal.h + // It seems like for kernel space, this function doesn't actually exist, + // it just macros to kill + pub fn taskKill(taskId: ::TASK_ID, signo: ::c_int) -> ::c_int; + + // signal.h + pub fn raise(__signo: ::c_int) -> ::c_int; + // taskLibCommon.h + pub fn taskIdSelf() -> ::TASK_ID; + + // rtpLibCommon.h + pub fn rtpInfoGet(rtpId: ::RTP_ID, rtpStruct: *mut ::RTP_DESC) -> ::c_int; + + // ioLib.h + pub fn _realpath( + fileName: *const ::c_char, + resolvedName: *mut ::c_char, + ) -> *mut ::c_char; + + // pathLib.h + pub fn _pathIsAbsolute( + filepath: *const ::c_char, + pNameTail: *const *const ::c_char, + ) -> bool; + + pub fn writev( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; + pub fn readv( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; +} + +pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int { + unsafe { _rtld_dladdr(addr, info) } +} + +//Dummy functions, these don't really exist in VxWorks. + +// wait.h macros +pub fn WIFEXITED(status: ::c_int) -> bool { + (status & 0xFF00) == 0 +} +pub fn WIFSIGNALED(status: ::c_int) -> bool { + (status & 0xFF00) != 0 +} +pub fn WIFSTOPPED(status: ::c_int) -> bool { + (status & 0xFF0000) != 0 +} +pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { + status & 0xFF +} +pub fn WTERMSIG(status: ::c_int) -> ::c_int { + (status >> 8) & 0xFF +} +pub fn WSTOPSIG(status: ::c_int) -> ::c_int { + (status >> 16) & 0xFF +} + +pub fn pread( + _fd: ::c_int, + _buf: *mut ::c_void, + _count: ::size_t, + _offset: off64_t, +) -> ::ssize_t { + -1 +} + +pub fn pwrite( + _fd: ::c_int, + _buf: *const ::c_void, + _count: ::size_t, + _offset: off64_t, +) -> ::ssize_t { + -1 +} +pub fn posix_memalign( + memptr: *mut *mut ::c_void, + align: ::size_t, + size: ::size_t, +) -> ::c_int { + // check to see if align is a power of 2 and if align is a multiple + // of sizeof(void *) + if (align & align - 1 != 0) || (align % size_of::<::size_t>() != 0) { + return ::EINVAL; + } + + unsafe { + // posix_memalign should not set errno + let e = ::errnoGet(); + + let temp = memalign(align, size); + ::errnoSet(e as ::c_int); + + if temp.is_null() { + ::ENOMEM + } else { + *memptr = temp; + 0 + } + } +} + +// From sysconf.c -> doesn't seem to be supported? +pub fn getpwuid_r( + _uid: ::uid_t, + _pwd: *mut passwd, + _buf: *mut ::c_char, + _buflen: ::size_t, + _result: *mut *mut passwd, +) -> ::c_int { + 0 +} + +// VxWorks requires that resolvedName be allocated in userspace +pub fn realpath( + fileName: *const ::c_char, + resolvedName: *mut ::c_char, +) -> *mut ::c_char { + unsafe { + if resolvedName == null_mut::<::c_char>() { + let emptyResolvedName = + super::malloc(::_POSIX_PATH_MAX as _) as *mut ::c_char; + let r = _realpath(fileName, emptyResolvedName); + + if r == null_mut::<::c_char>() { + super::free(emptyResolvedName as *mut _); + } + r + } else { + _realpath(fileName, resolvedName) + } + } +} + +cfg_if! { + if #[cfg(libc_core_cvoid)] { + pub use ::ffi::c_void; + } else { + // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help + // enable more optimization opportunities around it recognizing things + // like malloc/free. + #[repr(u8)] + #[allow(missing_copy_implementations)] + #[allow(missing_debug_implementations)] + pub enum c_void { + // Two dummy variants so the #[repr] attribute can be used. + #[doc(hidden)] + __variant1, + #[doc(hidden)] + __variant2, + } + } +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::*; + } else if #[cfg(any(target_arch = "arm"))] { + mod arm; + pub use self::arm::*; + } else if #[cfg(any(target_arch = "armv7"))] { + mod armv7; + pub use self::armv7::*; + } else if #[cfg(any(target_arch = "x86"))] { + mod x86; + pub use self::x86::*; + } else if #[cfg(any(target_arch = "x86_64"))] { + mod x86_64; + pub use self::x86_64::*; + } else if #[cfg(any(target_arch = "powerpc"))] { + mod powerpc; + pub use self::powerpc::*; + } else if #[cfg(any(target_arch = "powerpc64"))] { + mod powerpc64; + pub use self::powerpc64::*; + } else { + // Unknown target_arch + } +} diff --git a/vendor/libc/src/vxworks/powerpc.rs b/vendor/libc/src/vxworks/powerpc.rs new file mode 100644 index 0000000000..cfdce825a0 --- /dev/null +++ b/vendor/libc/src/vxworks/powerpc.rs @@ -0,0 +1,3 @@ +pub type c_char = u8; +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/vendor/libc/src/vxworks/powerpc64.rs b/vendor/libc/src/vxworks/powerpc64.rs new file mode 100644 index 0000000000..577c8bef16 --- /dev/null +++ b/vendor/libc/src/vxworks/powerpc64.rs @@ -0,0 +1,3 @@ +pub type c_char = u8; +pub type c_long = i64; +pub type c_ulong = u64; diff --git a/vendor/libc/src/vxworks/x86.rs b/vendor/libc/src/vxworks/x86.rs new file mode 100644 index 0000000000..81ba14588b --- /dev/null +++ b/vendor/libc/src/vxworks/x86.rs @@ -0,0 +1,3 @@ +pub type c_char = i8; +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/vendor/libc/src/vxworks/x86_64.rs b/vendor/libc/src/vxworks/x86_64.rs new file mode 100644 index 0000000000..27b9412668 --- /dev/null +++ b/vendor/libc/src/vxworks/x86_64.rs @@ -0,0 +1,3 @@ +pub type c_long = i64; +pub type c_ulong = u64; +pub type c_char = i8; diff --git a/vendor/lock_api-0.1.3/.cargo-checksum.json b/vendor/lock_api-0.1.3/.cargo-checksum.json new file mode 100644 index 0000000000..dde064c5b8 --- /dev/null +++ b/vendor/lock_api-0.1.3/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"9a369b3ff1ef121205879d10ba966bbccb81d6461843a75460f4cfcb82c3c849","src/lib.rs":"62142edfbe7e6cc04473aef25ab42553f02e4455ce567cb4303f0bbfee94d87d","src/mutex.rs":"d7ea4e06ae1a2d470e23bdfe73f52272f7c8b4231fe62fd9846e2a3773dcface","src/remutex.rs":"2fc11fec14af2886e507104e501caf6fddcf199ee7db38eabcd35ab9cf430d89","src/rwlock.rs":"45b940a9d046c7ee0c295237abac45f694c32a247724d93e3879a79f6e60b399"},"package":"949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"} \ No newline at end of file diff --git a/vendor/lock_api-0.1.3/Cargo.toml b/vendor/lock_api-0.1.3/Cargo.toml new file mode 100644 index 0000000000..ae2dc215ab --- /dev/null +++ b/vendor/lock_api-0.1.3/Cargo.toml @@ -0,0 +1,31 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "lock_api" +version = "0.1.3" +authors = ["Amanieu d'Antras "] +description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." +keywords = ["mutex", "rwlock", "lock", "no_std"] +categories = ["concurrency", "no-std"] +license = "Apache-2.0/MIT" +repository = "https://github.com/Amanieu/parking_lot" +[dependencies.owning_ref] +version = "0.3" +optional = true + +[dependencies.scopeguard] +version = "0.3" +default-features = false + +[features] +nightly = [] diff --git a/vendor/lock_api-0.1.3/src/lib.rs b/vendor/lock_api-0.1.3/src/lib.rs new file mode 100644 index 0000000000..cb031b705a --- /dev/null +++ b/vendor/lock_api-0.1.3/src/lib.rs @@ -0,0 +1,106 @@ +// Copyright 2018 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +//! This library provides type-safe and fully-featured `Mutex` and `RwLock` +//! types which wrap a simple raw mutex or rwlock type. This has several +//! benefits: not only does it eliminate a large portion of the work in +//! implementing custom lock types, it also allows users to write code which is +//! generic with regards to different lock implementations. +//! +//! Basic usage of this crate is very straightfoward: +//! +//! 1. Create a raw lock type. This should only contain the lock state, not any +//! data protected by the lock. +//! 2. Implement the `RawMutex` trait for your custom lock type. +//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and +//! your mutex guard as a type alias for `lock_api::MutexGuard`. +//! See the [example](#example) below for details. +//! +//! This process is similar for RwLocks, except that two guards need to be +//! exported instead of one. (Or 3 guards if your type supports upgradable read +//! locks, see [extension traits](#extension-traits) below for details) +//! +//! # Example +//! +//! ``` +//! use lock_api::{RawMutex, Mutex}; +//! use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; +//! +//! // 1. Define our raw lock type +//! pub struct RawSpinlock(AtomicBool); +//! +//! // 2. Implement RawMutex for this type +//! unsafe impl RawMutex for RawSpinlock { +//! const INIT: RawSpinlock = RawSpinlock(ATOMIC_BOOL_INIT); +//! +//! fn lock(&self) { +//! // Note: This isn't the best way of implementing a spinlock, but it +//! // suffices for the sake of this example. +//! while !self.try_lock() {} +//! } +//! +//! fn try_lock(&self) -> bool { +//! self.0.swap(true, Ordering::Acquire) +//! } +//! +//! fn unlock(&self) { +//! self.0.store(false, Ordering::Release); +//! } +//! } +//! +//! // 3. Export the wrappers. This are the types that your users will actually use. +//! pub type Spinlock = lock_api::Mutex; +//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>; +//! ``` +//! +//! # Extension traits +//! +//! In addition to basic locking & unlocking functionality, you have the option +//! of exposing additional functionality in your lock types by implementing +//! additional traits for it. Examples of extension features include: +//! +//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`) +//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`) +//! - Downgradable write locks (`RawRwLockDowngradable`) +//! - Recursive read locks (`RawRwLockRecursive`) +//! - Upgradable read locks (`RawRwLockUpgrade`) +//! +//! The `Mutex` and `RwLock` wrappers will automatically expose this additional +//! functionality if the raw lock type implements these extension traits. +//! +//! # Cargo features +//! +//! This crate supports two cargo features: +//! +//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate. +//! - `nightly`: Enables nightly-only features. At the moment the only such +//! feature is `const fn` constructors for lock types. + +#![no_std] +#![warn(missing_docs)] +#![cfg_attr(feature = "nightly", feature(const_fn))] + +#[macro_use] +extern crate scopeguard; + +#[cfg(feature = "owning_ref")] +extern crate owning_ref; + +/// Marker type which indicates that the Guard type for a lock is `Send`. +pub struct GuardSend(()); + +/// Marker type which indicates that the Guard type for a lock is not `Send`. +pub struct GuardNoSend(*mut ()); + +mod mutex; +pub use mutex::*; + +mod remutex; +pub use remutex::*; + +mod rwlock; +pub use rwlock::*; diff --git a/vendor/lock_api-0.1.3/src/mutex.rs b/vendor/lock_api-0.1.3/src/mutex.rs new file mode 100644 index 0000000000..f2b838986f --- /dev/null +++ b/vendor/lock_api-0.1.3/src/mutex.rs @@ -0,0 +1,496 @@ +// Copyright 2018 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::cell::UnsafeCell; +use core::fmt; +use core::marker::PhantomData; +use core::mem; +use core::ops::{Deref, DerefMut}; + +#[cfg(feature = "owning_ref")] +use owning_ref::StableAddress; + +/// Basic operations for a mutex. +/// +/// Types implementing this trait can be used by `Mutex` to form a safe and +/// fully-functioning mutex type. +/// +/// # Safety +/// +/// Implementations of this trait must ensure that the mutex is actually +/// exclusive: a lock can't be acquired while the mutex is already locked. +pub unsafe trait RawMutex { + /// Initial value for an unlocked mutex. + const INIT: Self; + + /// Marker type which determines whether a lock guard should be `Send`. Use + /// one of the `GuardSend` or `GuardNoSend` helper types here. + type GuardMarker; + + /// Acquires this mutex, blocking the current thread until it is able to do so. + fn lock(&self); + + /// Attempts to acquire this mutex without blocking. + fn try_lock(&self) -> bool; + + /// Unlocks this mutex. + fn unlock(&self); +} + +/// Additional methods for mutexes which support fair unlocking. +/// +/// Fair unlocking means that a lock is handed directly over to the next waiting +/// thread if there is one, without giving other threads the opportunity to +/// "steal" the lock in the meantime. This is typically slower than unfair +/// unlocking, but may be necessary in certain circumstances. +pub unsafe trait RawMutexFair: RawMutex { + /// Unlocks this mutex using a fair unlock protocol. + fn unlock_fair(&self); + + /// Temporarily yields the mutex to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `lock`, however it can be much more efficient in the case where there + /// are no waiting threads. + fn bump(&self) { + self.unlock_fair(); + self.lock(); + } +} + +/// Additional methods for mutexes which support locking with timeouts. +/// +/// The `Duration` and `Instant` types are specified as associated types so that +/// this trait is usable even in `no_std` environments. +pub unsafe trait RawMutexTimed: RawMutex { + /// Duration type used for `try_lock_for`. + type Duration; + + /// Instant type used for `try_lock_until`. + type Instant; + + /// Attempts to acquire this lock until a timeout is reached. + fn try_lock_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to acquire this lock until a timeout is reached. + fn try_lock_until(&self, timeout: Self::Instant) -> bool; +} + +/// A mutual exclusion primitive useful for protecting shared data +/// +/// This mutex will block threads waiting for the lock to become available. The +/// mutex can also be statically initialized or created via a `new` +/// constructor. Each mutex has a type parameter which represents the data that +/// it is protecting. The data can only be accessed through the RAII guards +/// returned from `lock` and `try_lock`, which guarantees that the data is only +/// ever accessed when the mutex is locked. +pub struct Mutex { + raw: R, + data: UnsafeCell, +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +impl Mutex { + /// Creates a new mutex in an unlocked state ready for use. + #[cfg(feature = "nightly")] + #[inline] + pub const fn new(val: T) -> Mutex { + Mutex { + data: UnsafeCell::new(val), + raw: R::INIT, + } + } + + /// Creates a new mutex in an unlocked state ready for use. + #[cfg(not(feature = "nightly"))] + #[inline] + pub fn new(val: T) -> Mutex { + Mutex { + data: UnsafeCell::new(val), + raw: R::INIT, + } + } + + /// Consumes this mutex, returning the underlying data. + #[inline] + #[allow(unused_unsafe)] + pub fn into_inner(self) -> T { + unsafe { self.data.into_inner() } + } +} + +impl Mutex { + #[inline] + fn guard(&self) -> MutexGuard { + MutexGuard { + mutex: self, + marker: PhantomData, + } + } + + /// Acquires a mutex, blocking the current thread until it is able to do so. + /// + /// This function will block the local thread until it is available to acquire + /// the mutex. Upon returning, the thread is the only thread with the mutex + /// held. An RAII guard is returned to allow scoped unlock of the lock. When + /// the guard goes out of scope, the mutex will be unlocked. + /// + /// Attempts to lock a mutex in the thread which already holds the lock will + /// result in a deadlock. + #[inline] + pub fn lock(&self) -> MutexGuard { + self.raw.lock(); + self.guard() + } + + /// Attempts to acquire this lock. + /// + /// If the lock could not be acquired at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned. The lock will be unlocked when the + /// guard is dropped. + /// + /// This function does not block. + #[inline] + pub fn try_lock(&self) -> Option> { + if self.raw.try_lock() { + Some(self.guard()) + } else { + None + } + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this call borrows the `Mutex` mutably, no actual locking needs to + /// take place---the mutable borrow statically guarantees no locks exist. + #[inline] + pub fn get_mut(&mut self) -> &mut T { + unsafe { &mut *self.data.get() } + } + + /// Forcibly unlocks the mutex. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `MutexGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `MutexGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a mutex is unlocked when not locked. + #[inline] + pub unsafe fn force_unlock(&self) { + self.raw.unlock(); + } + + /// Returns the underlying raw mutex object. + /// + /// Note that you will most likely need to import the `RawMutex` trait from + /// `lock_api` to be able to call functions on the raw mutex. + /// + /// # Safety + /// + /// This method is unsafe because it allows unlocking a mutex while + /// still holding a reference to a `MutexGuard`. + #[inline] + pub unsafe fn raw(&self) -> &R { + &self.raw + } +} + +impl Mutex { + /// Forcibly unlocks the mutex using a fair unlock procotol. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `MutexGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `MutexGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a mutex is unlocked when not locked. + #[inline] + pub unsafe fn force_unlock_fair(&self) { + self.raw.unlock_fair(); + } +} + +impl Mutex { + /// Attempts to acquire this lock until a timeout is reached. + /// + /// If the lock could not be acquired before the timeout expired, then + /// `None` is returned. Otherwise, an RAII guard is returned. The lock will + /// be unlocked when the guard is dropped. + #[inline] + pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { + if self.raw.try_lock_for(timeout) { + Some(self.guard()) + } else { + None + } + } + + /// Attempts to acquire this lock until a timeout is reached. + /// + /// If the lock could not be acquired before the timeout expired, then + /// `None` is returned. Otherwise, an RAII guard is returned. The lock will + /// be unlocked when the guard is dropped. + #[inline] + pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { + if self.raw.try_lock_until(timeout) { + Some(self.guard()) + } else { + None + } + } +} + +impl Default for Mutex { + #[inline] + fn default() -> Mutex { + Mutex::new(Default::default()) + } +} + +impl From for Mutex { + #[inline] + fn from(t: T) -> Mutex { + Mutex::new(t) + } +} + +impl fmt::Debug for Mutex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.try_lock() { + Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), + None => f.pad("Mutex { }"), + } + } +} + +/// An RAII implementation of a "scoped lock" of a mutex. When this structure is +/// dropped (falls out of scope), the lock will be unlocked. +/// +/// The data protected by the mutex can be accessed through this guard via its +/// `Deref` and `DerefMut` implementations. +#[must_use] +pub struct MutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> { + mutex: &'a Mutex, + marker: PhantomData<(&'a mut T, R::GuardMarker)>, +} + +unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { + /// Returns a reference to the original `Mutex` object. + pub fn mutex(s: &Self) -> &'a Mutex { + s.mutex + } + + /// Makes a new `MappedMutexGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `MutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `MutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedMutexGuard<'a, R, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let raw = &s.mutex.raw; + let data = f(unsafe { &mut *s.mutex.data.get() }); + mem::forget(s); + MappedMutexGuard { + raw, + data, + marker: PhantomData, + } + } + + /// Temporarily unlocks the mutex to execute the given function. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the mutex. + #[inline] + pub fn unlocked(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.mutex.raw.unlock(); + defer!(s.mutex.raw.lock()); + f() + } +} + +impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { + /// Unlocks the mutex using a fair unlock protocol. + /// + /// By default, mutexes are unfair and allow the current thread to re-lock + /// the mutex before another has the chance to acquire the lock, even if + /// that thread has been blocked on the mutex for a long time. This is the + /// default because it allows much higher throughput as it avoids forcing a + /// context switch on every mutex unlock. This can result in one thread + /// acquiring a mutex many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `MutexGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.mutex.raw.unlock_fair(); + mem::forget(s); + } + + /// Temporarily unlocks the mutex to execute the given function. + /// + /// The mutex is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the mutex. + #[inline] + pub fn unlocked_fair(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.mutex.raw.unlock_fair(); + defer!(s.mutex.raw.lock()); + f() + } + + /// Temporarily yields the mutex to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `lock`, however it can be much more efficient in the case where there + /// are no waiting threads. + #[inline] + pub fn bump(s: &mut Self) { + s.mutex.raw.bump(); + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.mutex.data.get() } + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.mutex.data.get() } + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.mutex.raw.unlock(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} + +/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a +/// subfield of the protected data. +/// +/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the +/// former doesn't support temporarily unlocking and re-locking, since that +/// could introduce soundness issues if the locked object is modified by another +/// thread. +#[must_use] +pub struct MappedMutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> { + raw: &'a R, + data: *mut T, + marker: PhantomData<&'a mut T>, +} + +unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync + for MappedMutexGuard<'a, R, T> +{} +unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Send for MappedMutexGuard<'a, R, T> where + R::GuardMarker: Send +{} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { + /// Makes a new `MappedMutexGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `MutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `MutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedMutexGuard<'a, R, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let raw = s.raw; + let data = f(unsafe { &mut *s.data }); + mem::forget(s); + MappedMutexGuard { + raw, + data, + marker: PhantomData, + } + } +} + +impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { + /// Unlocks the mutex using a fair unlock protocol. + /// + /// By default, mutexes are unfair and allow the current thread to re-lock + /// the mutex before another has the chance to acquire the lock, even if + /// that thread has been blocked on the mutex for a long time. This is the + /// default because it allows much higher throughput as it avoids forcing a + /// context switch on every mutex unlock. This can result in one thread + /// acquiring a mutex many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `MutexGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.raw.unlock_fair(); + mem::forget(s); + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.data } + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.data } + } +} + +impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.raw.unlock(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {} diff --git a/vendor/lock_api-0.1.3/src/remutex.rs b/vendor/lock_api-0.1.3/src/remutex.rs new file mode 100644 index 0000000000..3bede403e1 --- /dev/null +++ b/vendor/lock_api-0.1.3/src/remutex.rs @@ -0,0 +1,564 @@ +// Copyright 2018 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::cell::{Cell, UnsafeCell}; +use core::fmt; +use core::marker::PhantomData; +use core::mem; +use core::ops::Deref; +use core::sync::atomic::{AtomicUsize, Ordering}; +use mutex::{RawMutex, RawMutexFair, RawMutexTimed}; +use GuardNoSend; + +#[cfg(feature = "owning_ref")] +use owning_ref::StableAddress; + +/// Helper trait which returns a non-zero thread ID. +/// +/// The simplest way to implement this trait is to return the address of a +/// thread-local variable. +/// +/// # Safety +/// +/// Implementations of this trait must ensure that no two active threads share +/// the same thread ID. However the ID of a thread that has exited can be +/// re-used since that thread is no longer active. +pub unsafe trait GetThreadId { + /// Initial value. + const INIT: Self; + + /// Returns a non-zero thread ID which identifies the current thread of + /// execution. + fn nonzero_thread_id(&self) -> usize; +} + +struct RawReentrantMutex { + owner: AtomicUsize, + lock_count: Cell, + mutex: R, + get_thread_id: G, +} + +impl RawReentrantMutex { + #[inline] + fn lock_internal bool>(&self, try_lock: F) -> bool { + let id = self.get_thread_id.nonzero_thread_id(); + if self.owner.load(Ordering::Relaxed) == id { + self.lock_count.set( + self.lock_count + .get() + .checked_add(1) + .expect("ReentrantMutex lock count overflow"), + ); + } else { + if !try_lock() { + return false; + } + self.owner.store(id, Ordering::Relaxed); + self.lock_count.set(1); + } + true + } + + #[inline] + fn lock(&self) { + self.lock_internal(|| { + self.mutex.lock(); + true + }); + } + + #[inline] + fn try_lock(&self) -> bool { + self.lock_internal(|| self.mutex.try_lock()) + } + + #[inline] + fn unlock(&self) { + let lock_count = self.lock_count.get() - 1; + if lock_count == 0 { + self.owner.store(0, Ordering::Relaxed); + self.mutex.unlock(); + } else { + self.lock_count.set(lock_count); + } + } +} + +impl RawReentrantMutex { + #[inline] + fn unlock_fair(&self) { + let lock_count = self.lock_count.get() - 1; + if lock_count == 0 { + self.owner.store(0, Ordering::Relaxed); + self.mutex.unlock_fair(); + } else { + self.lock_count.set(lock_count); + } + } + + #[inline] + fn bump(&self) { + if self.lock_count.get() == 1 { + let id = self.owner.load(Ordering::Relaxed); + self.owner.store(0, Ordering::Relaxed); + self.mutex.bump(); + self.owner.store(id, Ordering::Relaxed); + } + } +} + +impl RawReentrantMutex { + #[inline] + fn try_lock_until(&self, timeout: R::Instant) -> bool { + self.lock_internal(|| self.mutex.try_lock_until(timeout)) + } + + #[inline] + fn try_lock_for(&self, timeout: R::Duration) -> bool { + self.lock_internal(|| self.mutex.try_lock_for(timeout)) + } +} + +/// A mutex which can be recursively locked by a single thread. +/// +/// This type is identical to `Mutex` except for the following points: +/// +/// - Locking multiple times from the same thread will work correctly instead of +/// deadlocking. +/// - `ReentrantMutexGuard` does not give mutable references to the locked data. +/// Use a `RefCell` if you need this. +/// +/// See [`Mutex`](struct.Mutex.html) for more details about the underlying mutex +/// primitive. +pub struct ReentrantMutex { + raw: RawReentrantMutex, + data: UnsafeCell, +} + +unsafe impl Send + for ReentrantMutex +{} +unsafe impl Sync + for ReentrantMutex +{} + +impl ReentrantMutex { + /// Creates a new reentrant mutex in an unlocked state ready for use. + #[cfg(feature = "nightly")] + #[inline] + pub const fn new(val: T) -> ReentrantMutex { + ReentrantMutex { + data: UnsafeCell::new(val), + raw: RawReentrantMutex { + owner: AtomicUsize::new(0), + lock_count: Cell::new(0), + mutex: R::INIT, + get_thread_id: G::INIT, + }, + } + } + + /// Creates a new reentrant mutex in an unlocked state ready for use. + #[cfg(not(feature = "nightly"))] + #[inline] + pub fn new(val: T) -> ReentrantMutex { + ReentrantMutex { + data: UnsafeCell::new(val), + raw: RawReentrantMutex { + owner: AtomicUsize::new(0), + lock_count: Cell::new(0), + mutex: R::INIT, + get_thread_id: G::INIT, + }, + } + } + + /// Consumes this mutex, returning the underlying data. + #[inline] + #[allow(unused_unsafe)] + pub fn into_inner(self) -> T { + unsafe { self.data.into_inner() } + } +} + +impl ReentrantMutex { + #[inline] + fn guard(&self) -> ReentrantMutexGuard { + ReentrantMutexGuard { + remutex: &self, + marker: PhantomData, + } + } + + /// Acquires a reentrant mutex, blocking the current thread until it is able + /// to do so. + /// + /// If the mutex is held by another thread then this function will block the + /// local thread until it is available to acquire the mutex. If the mutex is + /// already held by the current thread then this function will increment the + /// lock reference count and return immediately. Upon returning, + /// the thread is the only thread with the mutex held. An RAII guard is + /// returned to allow scoped unlock of the lock. When the guard goes out of + /// scope, the mutex will be unlocked. + #[inline] + pub fn lock(&self) -> ReentrantMutexGuard { + self.raw.lock(); + self.guard() + } + + /// Attempts to acquire this lock. + /// + /// If the lock could not be acquired at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned. The lock will be unlocked when the + /// guard is dropped. + /// + /// This function does not block. + #[inline] + pub fn try_lock(&self) -> Option> { + if self.raw.try_lock() { + Some(self.guard()) + } else { + None + } + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this call borrows the `ReentrantMutex` mutably, no actual locking needs to + /// take place---the mutable borrow statically guarantees no locks exist. + #[inline] + pub fn get_mut(&mut self) -> &mut T { + unsafe { &mut *self.data.get() } + } + + /// Forcibly unlocks the mutex. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `ReentrantMutexGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `ReentrantMutexGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a mutex is unlocked when not locked. + #[inline] + pub unsafe fn force_unlock(&self) { + self.raw.unlock(); + } + + /// Returns the underlying raw mutex object. + /// + /// Note that you will most likely need to import the `RawMutex` trait from + /// `lock_api` to be able to call functions on the raw mutex. + /// + /// # Safety + /// + /// This method is unsafe because it allows unlocking a mutex while + /// still holding a reference to a `ReentrantMutexGuard`. + #[inline] + pub unsafe fn raw(&self) -> &R { + &self.raw.mutex + } +} + +impl ReentrantMutex { + /// Forcibly unlocks the mutex using a fair unlock procotol. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `ReentrantMutexGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `ReentrantMutexGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a mutex is unlocked when not locked. + #[inline] + pub unsafe fn force_unlock_fair(&self) { + self.raw.unlock_fair(); + } +} + +impl ReentrantMutex { + /// Attempts to acquire this lock until a timeout is reached. + /// + /// If the lock could not be acquired before the timeout expired, then + /// `None` is returned. Otherwise, an RAII guard is returned. The lock will + /// be unlocked when the guard is dropped. + #[inline] + pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { + if self.raw.try_lock_for(timeout) { + Some(self.guard()) + } else { + None + } + } + + /// Attempts to acquire this lock until a timeout is reached. + /// + /// If the lock could not be acquired before the timeout expired, then + /// `None` is returned. Otherwise, an RAII guard is returned. The lock will + /// be unlocked when the guard is dropped. + #[inline] + pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { + if self.raw.try_lock_until(timeout) { + Some(self.guard()) + } else { + None + } + } +} + +impl Default for ReentrantMutex { + #[inline] + fn default() -> ReentrantMutex { + ReentrantMutex::new(Default::default()) + } +} + +impl From for ReentrantMutex { + #[inline] + fn from(t: T) -> ReentrantMutex { + ReentrantMutex::new(t) + } +} + +impl fmt::Debug for ReentrantMutex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.try_lock() { + Some(guard) => f + .debug_struct("ReentrantMutex") + .field("data", &&*guard) + .finish(), + None => f.pad("ReentrantMutex { }"), + } + } +} + +/// An RAII implementation of a "scoped lock" of a reentrant mutex. When this structure +/// is dropped (falls out of scope), the lock will be unlocked. +/// +/// The data protected by the mutex can be accessed through this guard via its +/// `Deref` implementation. +#[must_use] +pub struct ReentrantMutexGuard<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> { + remutex: &'a ReentrantMutex, + marker: PhantomData<(&'a T, GuardNoSend)>, +} + +unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync + for ReentrantMutexGuard<'a, R, G, T> +{} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGuard<'a, R, G, T> { + /// Returns a reference to the original `ReentrantMutex` object. + pub fn remutex(s: &Self) -> &'a ReentrantMutex { + s.remutex + } + + /// Makes a new `MappedReentrantMutexGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `ReentrantMutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedReentrantMutexGuard<'a, R, G, U> + where + F: FnOnce(&T) -> &U, + { + let raw = &s.remutex.raw; + let data = f(unsafe { &*s.remutex.data.get() }); + mem::forget(s); + MappedReentrantMutexGuard { + raw, + data, + marker: PhantomData, + } + } + + /// Temporarily unlocks the mutex to execute the given function. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the mutex. + #[inline] + pub fn unlocked(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.remutex.raw.unlock(); + defer!(s.remutex.raw.lock()); + f() + } +} + +impl<'a, R: RawMutexFair + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> + ReentrantMutexGuard<'a, R, G, T> +{ + /// Unlocks the mutex using a fair unlock protocol. + /// + /// By default, mutexes are unfair and allow the current thread to re-lock + /// the mutex before another has the chance to acquire the lock, even if + /// that thread has been blocked on the mutex for a long time. This is the + /// default because it allows much higher throughput as it avoids forcing a + /// context switch on every mutex unlock. This can result in one thread + /// acquiring a mutex many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `ReentrantMutexGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.remutex.raw.unlock_fair(); + mem::forget(s); + } + + /// Temporarily unlocks the mutex to execute the given function. + /// + /// The mutex is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the mutex. + #[inline] + pub fn unlocked_fair(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.remutex.raw.unlock_fair(); + defer!(s.remutex.raw.lock()); + f() + } + + /// Temporarily yields the mutex to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `lock`, however it can be much more efficient in the case where there + /// are no waiting threads. + #[inline] + pub fn bump(s: &mut Self) { + s.remutex.raw.bump(); + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Deref + for ReentrantMutexGuard<'a, R, G, T> +{ + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.remutex.data.get() } + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop + for ReentrantMutexGuard<'a, R, G, T> +{ + #[inline] + fn drop(&mut self) { + self.remutex.raw.unlock(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress + for ReentrantMutexGuard<'a, R, G, T> +{} + +/// An RAII mutex guard returned by `ReentrantMutexGuard::map`, which can point to a +/// subfield of the protected data. +/// +/// The main difference between `MappedReentrantMutexGuard` and `ReentrantMutexGuard` is that the +/// former doesn't support temporarily unlocking and re-locking, since that +/// could introduce soundness issues if the locked object is modified by another +/// thread. +#[must_use] +pub struct MappedReentrantMutexGuard<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> { + raw: &'a RawReentrantMutex, + data: *const T, + marker: PhantomData<&'a T>, +} + +unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync + for MappedReentrantMutexGuard<'a, R, G, T> +{} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> + MappedReentrantMutexGuard<'a, R, G, T> +{ + /// Makes a new `MappedReentrantMutexGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `ReentrantMutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedReentrantMutexGuard<'a, R, G, U> + where + F: FnOnce(&T) -> &U, + { + let raw = s.raw; + let data = f(unsafe { &*s.data }); + mem::forget(s); + MappedReentrantMutexGuard { + raw, + data, + marker: PhantomData, + } + } +} + +impl<'a, R: RawMutexFair + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> + MappedReentrantMutexGuard<'a, R, G, T> +{ + /// Unlocks the mutex using a fair unlock protocol. + /// + /// By default, mutexes are unfair and allow the current thread to re-lock + /// the mutex before another has the chance to acquire the lock, even if + /// that thread has been blocked on the mutex for a long time. This is the + /// default because it allows much higher throughput as it avoids forcing a + /// context switch on every mutex unlock. This can result in one thread + /// acquiring a mutex many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `ReentrantMutexGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.raw.unlock_fair(); + mem::forget(s); + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Deref + for MappedReentrantMutexGuard<'a, R, G, T> +{ + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.data } + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop + for MappedReentrantMutexGuard<'a, R, G, T> +{ + #[inline] + fn drop(&mut self) { + self.raw.unlock(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress + for MappedReentrantMutexGuard<'a, R, G, T> +{} diff --git a/vendor/lock_api-0.1.3/src/rwlock.rs b/vendor/lock_api-0.1.3/src/rwlock.rs new file mode 100644 index 0000000000..904ff95791 --- /dev/null +++ b/vendor/lock_api-0.1.3/src/rwlock.rs @@ -0,0 +1,1345 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::cell::UnsafeCell; +use core::fmt; +use core::marker::PhantomData; +use core::mem; +use core::ops::{Deref, DerefMut}; + +#[cfg(feature = "owning_ref")] +use owning_ref::StableAddress; + +/// Basic operations for a reader-writer lock. +/// +/// Types implementing this trait can be used by `RwLock` to form a safe and +/// fully-functioning `RwLock` type. +/// +/// # Safety +/// +/// Implementations of this trait must ensure that the `RwLock` is actually +/// exclusive: an exclusive lock can't be acquired while an exclusive or shared +/// lock exists, and a shared lock can't be acquire while an exclusive lock +/// exists. +pub unsafe trait RawRwLock { + /// Initial value for an unlocked `RwLock`. + const INIT: Self; + + /// Marker type which determines whether a lock guard should be `Send`. Use + /// one of the `GuardSend` or `GuardNoSend` helper types here. + type GuardMarker; + + /// Acquires a shared lock, blocking the current thread until it is able to do so. + fn lock_shared(&self); + + /// Attempts to acquire a shared lock without blocking. + fn try_lock_shared(&self) -> bool; + + /// Releases a shared lock. + fn unlock_shared(&self); + + /// Acquires an exclusive lock, blocking the current thread until it is able to do so. + fn lock_exclusive(&self); + + /// Attempts to acquire an exclusive lock without blocking. + fn try_lock_exclusive(&self) -> bool; + + /// Releases an exclusive lock. + fn unlock_exclusive(&self); +} + +/// Additional methods for RwLocks which support fair unlocking. +/// +/// Fair unlocking means that a lock is handed directly over to the next waiting +/// thread if there is one, without giving other threads the opportunity to +/// "steal" the lock in the meantime. This is typically slower than unfair +/// unlocking, but may be necessary in certain circumstances. +pub unsafe trait RawRwLockFair: RawRwLock { + /// Releases a shared lock using a fair unlock protocol. + fn unlock_shared_fair(&self); + + /// Releases an exclusive lock using a fair unlock protocol. + fn unlock_exclusive_fair(&self); + + /// Temporarily yields a shared lock to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_shared_fair` followed + /// by `lock_shared`, however it can be much more efficient in the case where there + /// are no waiting threads. + fn bump_shared(&self) { + self.unlock_shared_fair(); + self.lock_shared(); + } + + /// Temporarily yields an exclusive lock to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_exclusive_fair` followed + /// by `lock_exclusive`, however it can be much more efficient in the case where there + /// are no waiting threads. + fn bump_exclusive(&self) { + self.unlock_exclusive_fair(); + self.lock_exclusive(); + } +} + +/// Additional methods for RwLocks which support atomically downgrading an +/// exclusive lock to a shared lock. +pub unsafe trait RawRwLockDowngrade: RawRwLock { + /// Atomically downgrades an exclusive lock into a shared lock without + /// allowing any thread to take an exclusive lock in the meantime. + fn downgrade(&self); +} + +/// Additional methods for RwLocks which support locking with timeouts. +/// +/// The `Duration` and `Instant` types are specified as associated types so that +/// this trait is usable even in `no_std` environments. +pub unsafe trait RawRwLockTimed: RawRwLock { + /// Duration type used for `try_lock_for`. + type Duration; + + /// Instant type used for `try_lock_until`. + type Instant; + + /// Attempts to acquire a shared lock until a timeout is reached. + fn try_lock_shared_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to acquire a shared lock until a timeout is reached. + fn try_lock_shared_until(&self, timeout: Self::Instant) -> bool; + + /// Attempts to acquire an exclusive lock until a timeout is reached. + fn try_lock_exclusive_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to acquire an exclusive lock until a timeout is reached. + fn try_lock_exclusive_until(&self, timeout: Self::Instant) -> bool; +} + +/// Additional methods for RwLocks which support recursive read locks. +/// +/// These are guaranteed to succeed without blocking if +/// another read lock is held at the time of the call. This allows a thread +/// to recursively lock a `RwLock`. However using this method can cause +/// writers to starve since readers no longer block if a writer is waiting +/// for the lock. +pub unsafe trait RawRwLockRecursive: RawRwLock { + /// Acquires a shared lock without deadlocking in case of a recursive lock. + fn lock_shared_recursive(&self); + + /// Attempts to acquire a shared lock without deadlocking in case of a recursive lock. + fn try_lock_shared_recursive(&self) -> bool; +} + +/// Additional methods for RwLocks which support recursive read locks and timeouts. +pub unsafe trait RawRwLockRecursiveTimed: RawRwLockRecursive + RawRwLockTimed { + /// Attempts to acquire a shared lock until a timeout is reached, without + /// deadlocking in case of a recursive lock. + fn try_lock_shared_recursive_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to acquire a shared lock until a timeout is reached, without + /// deadlocking in case of a recursive lock. + fn try_lock_shared_recursive_until(&self, timeout: Self::Instant) -> bool; +} + +/// Additional methods for RwLocks which support atomically upgrading a shared +/// lock to an exclusive lock. +/// +/// This requires acquiring a special "upgradable read lock" instead of a +/// normal shared lock. There may only be one upgradable lock at any time, +/// otherwise deadlocks could occur when upgrading. +pub unsafe trait RawRwLockUpgrade: RawRwLock { + /// Acquires an upgradable lock, blocking the current thread until it is able to do so. + fn lock_upgradable(&self); + + /// Attempts to acquire an upgradable lock without blocking. + fn try_lock_upgradable(&self) -> bool; + + /// Releases an upgradable lock. + fn unlock_upgradable(&self); + + /// Upgrades an upgradable lock to an exclusive lock. + fn upgrade(&self); + + /// Attempts to upgrade an upgradable lock to an exclusive lock without + /// blocking. + fn try_upgrade(&self) -> bool; +} + +/// Additional methods for RwLocks which support upgradable locks and fair +/// unlocking. +pub unsafe trait RawRwLockUpgradeFair: RawRwLockUpgrade + RawRwLockFair { + /// Releases an upgradable lock using a fair unlock protocol. + fn unlock_upgradable_fair(&self); + + /// Temporarily yields an upgradable lock to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_upgradable_fair` followed + /// by `lock_upgradable`, however it can be much more efficient in the case where there + /// are no waiting threads. + fn bump_upgradable(&self) { + self.unlock_upgradable_fair(); + self.lock_upgradable(); + } +} + +/// Additional methods for RwLocks which support upgradable locks and lock +/// downgrading. +pub unsafe trait RawRwLockUpgradeDowngrade: RawRwLockUpgrade + RawRwLockDowngrade { + /// Downgrades an upgradable lock to a shared lock. + fn downgrade_upgradable(&self); + + /// Downgrades an exclusive lock to an upgradable lock. + fn downgrade_to_upgradable(&self); +} + +/// Additional methods for RwLocks which support upgradable locks and locking +/// with timeouts. +pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed { + /// Attempts to acquire an upgradable lock until a timeout is reached. + fn try_lock_upgradable_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to acquire an upgradable lock until a timeout is reached. + fn try_lock_upgradable_until(&self, timeout: Self::Instant) -> bool; + + /// Attempts to upgrade an upgradable lock to an exclusive lock until a + /// timeout is reached. + fn try_upgrade_for(&self, timeout: Self::Duration) -> bool; + + /// Attempts to upgrade an upgradable lock to an exclusive lock until a + /// timeout is reached. + fn try_upgrade_until(&self, timeout: Self::Instant) -> bool; +} + +/// A reader-writer lock +/// +/// This type of lock allows a number of readers or at most one writer at any +/// point in time. The write portion of this lock typically allows modification +/// of the underlying data (exclusive access) and the read portion of this lock +/// typically allows for read-only access (shared access). +/// +/// The type parameter `T` represents the data that this lock protects. It is +/// required that `T` satisfies `Send` to be shared across threads and `Sync` to +/// allow concurrent access through readers. The RAII guards returned from the +/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) +/// to allow access to the contained of the lock. +pub struct RwLock { + raw: R, + data: UnsafeCell, +} + +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} + +impl RwLock { + /// Creates a new instance of an `RwLock` which is unlocked. + #[cfg(feature = "nightly")] + #[inline] + pub const fn new(val: T) -> RwLock { + RwLock { + data: UnsafeCell::new(val), + raw: R::INIT, + } + } + + /// Creates a new instance of an `RwLock` which is unlocked. + #[cfg(not(feature = "nightly"))] + #[inline] + pub fn new(val: T) -> RwLock { + RwLock { + data: UnsafeCell::new(val), + raw: R::INIT, + } + } + + /// Consumes this `RwLock`, returning the underlying data. + #[inline] + #[allow(unused_unsafe)] + pub fn into_inner(self) -> T { + unsafe { self.data.into_inner() } + } +} + +impl RwLock { + #[inline] + fn read_guard(&self) -> RwLockReadGuard { + RwLockReadGuard { + rwlock: self, + marker: PhantomData, + } + } + + #[inline] + fn write_guard(&self) -> RwLockWriteGuard { + RwLockWriteGuard { + rwlock: self, + marker: PhantomData, + } + } + + /// Locks this `RwLock` with shared read access, blocking the current thread + /// until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers which + /// hold the lock. There may be other readers currently inside the lock when + /// this method returns. + /// + /// Note that attempts to recursively acquire a read lock on a `RwLock` when + /// the current thread already holds one may result in a deadlock. + /// + /// Returns an RAII guard which will release this thread's shared access + /// once it is dropped. + #[inline] + pub fn read(&self) -> RwLockReadGuard { + self.raw.lock_shared(); + self.read_guard() + } + + /// Attempts to acquire this `RwLock` with shared read access. + /// + /// If the access could not be granted at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned which will release the shared access + /// when it is dropped. + /// + /// This function does not block. + #[inline] + pub fn try_read(&self) -> Option> { + if self.raw.try_lock_shared() { + Some(self.read_guard()) + } else { + None + } + } + + /// Locks this `RwLock` with exclusive write access, blocking the current + /// thread until it can be acquired. + /// + /// This function will not return while other writers or other readers + /// currently have access to the lock. + /// + /// Returns an RAII guard which will drop the write access of this `RwLock` + /// when dropped. + #[inline] + pub fn write(&self) -> RwLockWriteGuard { + self.raw.lock_exclusive(); + self.write_guard() + } + + /// Attempts to lock this `RwLock` with exclusive write access. + /// + /// If the lock could not be acquired at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned which will release the lock when + /// it is dropped. + /// + /// This function does not block. + #[inline] + pub fn try_write(&self) -> Option> { + if self.raw.try_lock_exclusive() { + Some(self.write_guard()) + } else { + None + } + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this call borrows the `RwLock` mutably, no actual locking needs to + /// take place---the mutable borrow statically guarantees no locks exist. + #[inline] + pub fn get_mut(&mut self) -> &mut T { + unsafe { &mut *self.data.get() } + } + + /// Forcibly unlocks a read lock. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `RwLockReadGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a rwlock is read-unlocked when not read-locked. + #[inline] + pub unsafe fn force_unlock_read(&self) { + self.raw.unlock_shared(); + } + + /// Forcibly unlocks a write lock. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `RwLockWriteGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a rwlock is write-unlocked when not write-locked. + #[inline] + pub unsafe fn force_unlock_write(&self) { + self.raw.unlock_exclusive(); + } + + /// Returns the underlying raw reader-writer lock object. + /// + /// Note that you will most likely need to import the `RawRwLock` trait from + /// `lock_api` to be able to call functions on the raw + /// reader-writer lock. + /// + /// # Safety + /// + /// This method is unsafe because it allows unlocking a mutex while + /// still holding a reference to a lock guard. + pub unsafe fn raw(&self) -> &R { + &self.raw + } +} + +impl RwLock { + /// Forcibly unlocks a read lock using a fair unlock procotol. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `RwLockReadGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a rwlock is read-unlocked when not read-locked. + #[inline] + pub unsafe fn force_unlock_read_fair(&self) { + self.raw.unlock_shared_fair(); + } + + /// Forcibly unlocks a write lock using a fair unlock procotol. + /// + /// This is useful when combined with `mem::forget` to hold a lock without + /// the need to maintain a `RwLockWriteGuard` object alive, for example when + /// dealing with FFI. + /// + /// # Safety + /// + /// This method must only be called if the current thread logically owns a + /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`. + /// Behavior is undefined if a rwlock is write-unlocked when not write-locked. + #[inline] + pub unsafe fn force_unlock_write_fair(&self) { + self.raw.unlock_exclusive_fair(); + } +} + +impl RwLock { + /// Attempts to acquire this `RwLock` with shared read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + #[inline] + pub fn try_read_for(&self, timeout: R::Duration) -> Option> { + if self.raw.try_lock_shared_for(timeout) { + Some(self.read_guard()) + } else { + None + } + } + + /// Attempts to acquire this `RwLock` with shared read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + #[inline] + pub fn try_read_until(&self, timeout: R::Instant) -> Option> { + if self.raw.try_lock_shared_until(timeout) { + Some(self.read_guard()) + } else { + None + } + } + + /// Attempts to acquire this `RwLock` with exclusive write access until a + /// timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the exclusive access when it is dropped. + #[inline] + pub fn try_write_for(&self, timeout: R::Duration) -> Option> { + if self.raw.try_lock_exclusive_for(timeout) { + Some(self.write_guard()) + } else { + None + } + } + + /// Attempts to acquire this `RwLock` with exclusive write access until a + /// timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the exclusive access when it is dropped. + #[inline] + pub fn try_write_until(&self, timeout: R::Instant) -> Option> { + if self.raw.try_lock_exclusive_until(timeout) { + Some(self.write_guard()) + } else { + None + } + } +} + +impl RwLock { + /// Locks this `RwLock` with shared read access, blocking the current thread + /// until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers which + /// hold the lock. There may be other readers currently inside the lock when + /// this method returns. + /// + /// Unlike `read`, this method is guaranteed to succeed without blocking if + /// another read lock is held at the time of the call. This allows a thread + /// to recursively lock a `RwLock`. However using this method can cause + /// writers to starve since readers no longer block if a writer is waiting + /// for the lock. + /// + /// Returns an RAII guard which will release this thread's shared access + /// once it is dropped. + #[inline] + pub fn read_recursive(&self) -> RwLockReadGuard { + self.raw.lock_shared_recursive(); + self.read_guard() + } + + /// Attempts to acquire this `RwLock` with shared read access. + /// + /// If the access could not be granted at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned which will release the shared access + /// when it is dropped. + /// + /// This method is guaranteed to succeed if another read lock is held at the + /// time of the call. See the documentation for `read_recursive` for details. + /// + /// This function does not block. + #[inline] + pub fn try_read_recursive(&self) -> Option> { + if self.raw.try_lock_shared_recursive() { + Some(self.read_guard()) + } else { + None + } + } +} + +impl RwLock { + /// Attempts to acquire this `RwLock` with shared read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + /// + /// This method is guaranteed to succeed without blocking if another read + /// lock is held at the time of the call. See the documentation for + /// `read_recursive` for details. + #[inline] + pub fn try_read_recursive_for(&self, timeout: R::Duration) -> Option> { + if self.raw.try_lock_shared_recursive_for(timeout) { + Some(self.read_guard()) + } else { + None + } + } + + /// Attempts to acquire this `RwLock` with shared read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + #[inline] + pub fn try_read_recursive_until(&self, timeout: R::Instant) -> Option> { + if self.raw.try_lock_shared_recursive_until(timeout) { + Some(self.read_guard()) + } else { + None + } + } +} + +impl RwLock { + #[inline] + fn upgradable_guard(&self) -> RwLockUpgradableReadGuard { + RwLockUpgradableReadGuard { + rwlock: self, + marker: PhantomData, + } + } + + /// Locks this `RwLock` with upgradable read access, blocking the current thread + /// until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers or other + /// upgradable reads which hold the lock. There may be other readers currently + /// inside the lock when this method returns. + /// + /// Returns an RAII guard which will release this thread's shared access + /// once it is dropped. + #[inline] + pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard { + self.raw.lock_upgradable(); + self.upgradable_guard() + } + + /// Attempts to acquire this `RwLock` with upgradable read access. + /// + /// If the access could not be granted at this time, then `None` is returned. + /// Otherwise, an RAII guard is returned which will release the shared access + /// when it is dropped. + /// + /// This function does not block. + #[inline] + pub fn try_upgradable_read(&self) -> Option> { + if self.raw.try_lock_upgradable() { + Some(self.upgradable_guard()) + } else { + None + } + } +} + +impl RwLock { + /// Attempts to acquire this `RwLock` with upgradable read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + #[inline] + pub fn try_upgradable_read_for( + &self, + timeout: R::Duration, + ) -> Option> { + if self.raw.try_lock_upgradable_for(timeout) { + Some(self.upgradable_guard()) + } else { + None + } + } + + /// Attempts to acquire this `RwLock` with upgradable read access until a timeout + /// is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. Otherwise, an RAII guard is returned which will + /// release the shared access when it is dropped. + #[inline] + pub fn try_upgradable_read_until( + &self, + timeout: R::Instant, + ) -> Option> { + if self.raw.try_lock_upgradable_until(timeout) { + Some(self.upgradable_guard()) + } else { + None + } + } +} + +impl Default for RwLock { + #[inline] + fn default() -> RwLock { + RwLock::new(Default::default()) + } +} + +impl From for RwLock { + #[inline] + fn from(t: T) -> RwLock { + RwLock::new(t) + } +} + +impl fmt::Debug for RwLock { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.try_read() { + Some(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(), + None => f.pad("RwLock { }"), + } + } +} + +/// RAII structure used to release the shared read access of a lock when +/// dropped. +#[must_use] +pub struct RwLockReadGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { + rwlock: &'a RwLock, + marker: PhantomData<(&'a T, R::GuardMarker)>, +} + +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for RwLockReadGuard<'a, R, T> {} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { + /// Returns a reference to the original reader-writer lock object. + pub fn rwlock(s: &Self) -> &'a RwLock { + s.rwlock + } + + /// Make a new `MappedRwLockReadGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `RwLockReadGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U> + where + F: FnOnce(&T) -> &U, + { + let raw = &s.rwlock.raw; + let data = f(unsafe { &*s.rwlock.data.get() }); + mem::forget(s); + MappedRwLockReadGuard { + raw, + data, + marker: PhantomData, + } + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// The `RwLock` is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_shared(); + defer!(s.rwlock.raw.lock_shared()); + f() + } +} + +impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { + /// Unlocks the `RwLock` using a fair unlock protocol. + /// + /// By default, `RwLock` is unfair and allow the current thread to re-lock + /// the `RwLock` before another has the chance to acquire the lock, even if + /// that thread has been blocked on the `RwLock` for a long time. This is + /// the default because it allows much higher throughput as it avoids + /// forcing a context switch on every `RwLock` unlock. This can result in one + /// thread acquiring a `RwLock` many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `RwLockReadGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.rwlock.raw.unlock_shared_fair(); + mem::forget(s); + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// The `RwLock` is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked_fair(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_shared_fair(); + defer!(s.rwlock.raw.lock_shared()); + f() + } + + /// Temporarily yields the `RwLock` to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `read`, however it can be much more efficient in the case where there + /// are no waiting threads. + #[inline] + pub fn bump(s: &mut Self) { + s.rwlock.raw.bump_shared(); + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockReadGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.rwlock.data.get() } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.rwlock.raw.unlock_shared(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {} + +/// RAII structure used to release the exclusive write access of a lock when +/// dropped. +#[must_use] +pub struct RwLockWriteGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { + rwlock: &'a RwLock, + marker: PhantomData<(&'a mut T, R::GuardMarker)>, +} + +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for RwLockWriteGuard<'a, R, T> {} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { + /// Returns a reference to the original reader-writer lock object. + pub fn rwlock(s: &Self) -> &'a RwLock { + s.rwlock + } + + /// Make a new `MappedRwLockWriteGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `RwLockWriteGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let raw = &orig.rwlock.raw; + let data = f(unsafe { &mut *orig.rwlock.data.get() }); + mem::forget(orig); + MappedRwLockWriteGuard { + raw, + data, + marker: PhantomData, + } + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_exclusive(); + defer!(s.rwlock.raw.lock_exclusive()); + f() + } +} + +impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { + /// Atomically downgrades a write lock into a read lock without allowing any + /// writers to take exclusive access of the lock in the meantime. + /// + /// Note that if there are any writers currently waiting to take the lock + /// then other readers may not be able to acquire the lock even if it was + /// downgraded. + pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> { + s.rwlock.raw.downgrade(); + let rwlock = s.rwlock; + mem::forget(s); + RwLockReadGuard { + rwlock, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { + /// Atomically downgrades a write lock into an upgradable read lock without allowing any + /// writers to take exclusive access of the lock in the meantime. + /// + /// Note that if there are any writers currently waiting to take the lock + /// then other readers may not be able to acquire the lock even if it was + /// downgraded. + pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, R, T> { + s.rwlock.raw.downgrade_to_upgradable(); + let rwlock = s.rwlock; + mem::forget(s); + RwLockUpgradableReadGuard { + rwlock, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { + /// Unlocks the `RwLock` using a fair unlock protocol. + /// + /// By default, `RwLock` is unfair and allow the current thread to re-lock + /// the `RwLock` before another has the chance to acquire the lock, even if + /// that thread has been blocked on the `RwLock` for a long time. This is + /// the default because it allows much higher throughput as it avoids + /// forcing a context switch on every `RwLock` unlock. This can result in one + /// thread acquiring a `RwLock` many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `RwLockWriteGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.rwlock.raw.unlock_exclusive_fair(); + mem::forget(s); + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// The `RwLock` is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked_fair(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_exclusive_fair(); + defer!(s.rwlock.raw.lock_exclusive()); + f() + } + + /// Temporarily yields the `RwLock` to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `write`, however it can be much more efficient in the case where there + /// are no waiting threads. + #[inline] + pub fn bump(s: &mut Self) { + s.rwlock.raw.bump_exclusive(); + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockWriteGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.rwlock.data.get() } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for RwLockWriteGuard<'a, R, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.rwlock.data.get() } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.rwlock.raw.unlock_exclusive(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {} + +/// RAII structure used to release the upgradable read access of a lock when +/// dropped. +#[must_use] +pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> { + rwlock: &'a RwLock, + marker: PhantomData<(&'a T, R::GuardMarker)>, +} + +unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + Sync + 'a> Sync + for RwLockUpgradableReadGuard<'a, R, T> +{} + +impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { + /// Returns a reference to the original reader-writer lock object. + pub fn rwlock(s: &Self) -> &'a RwLock { + s.rwlock + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_upgradable(); + defer!(s.rwlock.raw.lock_upgradable()); + f() + } + + /// Atomically upgrades an upgradable read lock lock into a exclusive write lock, + /// blocking the current thread until it can be aquired. + pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> { + s.rwlock.raw.upgrade(); + let rwlock = s.rwlock; + mem::forget(s); + RwLockWriteGuard { + rwlock, + marker: PhantomData, + } + } + + /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock. + /// + /// If the access could not be granted at this time, then the current guard is returned. + pub fn try_upgrade(s: Self) -> Result, Self> { + if s.rwlock.raw.try_upgrade() { + let rwlock = s.rwlock; + mem::forget(s); + Ok(RwLockWriteGuard { + rwlock, + marker: PhantomData, + }) + } else { + Err(s) + } + } +} + +impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { + /// Unlocks the `RwLock` using a fair unlock protocol. + /// + /// By default, `RwLock` is unfair and allow the current thread to re-lock + /// the `RwLock` before another has the chance to acquire the lock, even if + /// that thread has been blocked on the `RwLock` for a long time. This is + /// the default because it allows much higher throughput as it avoids + /// forcing a context switch on every `RwLock` unlock. This can result in one + /// thread acquiring a `RwLock` many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `RwLockUpgradableReadGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.rwlock.raw.unlock_upgradable_fair(); + mem::forget(s); + } + + /// Temporarily unlocks the `RwLock` to execute the given function. + /// + /// The `RwLock` is unlocked a fair unlock protocol. + /// + /// This is safe because `&mut` guarantees that there exist no other + /// references to the data protected by the `RwLock`. + #[inline] + pub fn unlocked_fair(s: &mut Self, f: F) -> U + where + F: FnOnce() -> U, + { + s.rwlock.raw.unlock_upgradable_fair(); + defer!(s.rwlock.raw.lock_upgradable()); + f() + } + + /// Temporarily yields the `RwLock` to a waiting thread if there is one. + /// + /// This method is functionally equivalent to calling `unlock_fair` followed + /// by `upgradable_read`, however it can be much more efficient in the case where there + /// are no waiting threads. + #[inline] + pub fn bump(s: &mut Self) { + s.rwlock.raw.bump_upgradable(); + } +} + +impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { + /// Atomically downgrades an upgradable read lock lock into a shared read lock + /// without allowing any writers to take exclusive access of the lock in the + /// meantime. + /// + /// Note that if there are any writers currently waiting to take the lock + /// then other readers may not be able to acquire the lock even if it was + /// downgraded. + pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> { + s.rwlock.raw.downgrade_upgradable(); + let rwlock = s.rwlock; + mem::forget(s); + RwLockReadGuard { + rwlock, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { + /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// the current guard is returned. + pub fn try_upgrade_for( + s: Self, + timeout: R::Duration, + ) -> Result, Self> { + if s.rwlock.raw.try_upgrade_for(timeout) { + let rwlock = s.rwlock; + mem::forget(s); + Ok(RwLockWriteGuard { + rwlock, + marker: PhantomData, + }) + } else { + Err(s) + } + } + + /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// the current guard is returned. + #[inline] + pub fn try_upgrade_until( + s: Self, + timeout: R::Instant, + ) -> Result, Self> { + if s.rwlock.raw.try_upgrade_until(timeout) { + let rwlock = s.rwlock; + mem::forget(s); + Ok(RwLockWriteGuard { + rwlock, + marker: PhantomData, + }) + } else { + Err(s) + } + } +} + +impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.rwlock.data.get() } + } +} + +impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableReadGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.rwlock.raw.unlock_upgradable(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress + for RwLockUpgradableReadGuard<'a, R, T> +{} + +/// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a +/// subfield of the protected data. +/// +/// The main difference between `MappedRwLockReadGuard` and `RwLockReadGuard` is that the +/// former doesn't support temporarily unlocking and re-locking, since that +/// could introduce soundness issues if the locked object is modified by another +/// thread. +#[must_use] +pub struct MappedRwLockReadGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { + raw: &'a R, + data: *const T, + marker: PhantomData<&'a T>, +} + +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockReadGuard<'a, R, T> {} +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Send for MappedRwLockReadGuard<'a, R, T> where + R::GuardMarker: Send +{} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { + /// Make a new `MappedRwLockReadGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `MappedRwLockReadGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U> + where + F: FnOnce(&T) -> &U, + { + let raw = s.raw; + let data = f(unsafe { &*s.data }); + mem::forget(s); + MappedRwLockReadGuard { + raw, + data, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { + /// Unlocks the `RwLock` using a fair unlock protocol. + /// + /// By default, `RwLock` is unfair and allow the current thread to re-lock + /// the `RwLock` before another has the chance to acquire the lock, even if + /// that thread has been blocked on the `RwLock` for a long time. This is + /// the default because it allows much higher throughput as it avoids + /// forcing a context switch on every `RwLock` unlock. This can result in one + /// thread acquiring a `RwLock` many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `MappedRwLockReadGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.raw.unlock_shared_fair(); + mem::forget(s); + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockReadGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.data } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.raw.unlock_shared(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress + for MappedRwLockReadGuard<'a, R, T> +{} + +/// An RAII write lock guard returned by `RwLockWriteGuard::map`, which can point to a +/// subfield of the protected data. +/// +/// The main difference between `MappedRwLockWriteGuard` and `RwLockWriteGuard` is that the +/// former doesn't support temporarily unlocking and re-locking, since that +/// could introduce soundness issues if the locked object is modified by another +/// thread. +#[must_use] +pub struct MappedRwLockWriteGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { + raw: &'a R, + data: *mut T, + marker: PhantomData<&'a mut T>, +} + +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync + for MappedRwLockWriteGuard<'a, R, T> +{} +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Send for MappedRwLockWriteGuard<'a, R, T> where + R::GuardMarker: Send +{} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { + /// Make a new `MappedRwLockWriteGuard` for a component of the locked data. + /// + /// This operation cannot fail as the `MappedRwLockWriteGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let raw = orig.raw; + let data = f(unsafe { &mut *orig.data }); + mem::forget(orig); + MappedRwLockWriteGuard { + raw, + data, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { + /// Atomically downgrades a write lock into a read lock without allowing any + /// writers to take exclusive access of the lock in the meantime. + /// + /// Note that if there are any writers currently waiting to take the lock + /// then other readers may not be able to acquire the lock even if it was + /// downgraded. + pub fn downgrade(s: Self) -> MappedRwLockReadGuard<'a, R, T> { + s.raw.downgrade(); + let raw = s.raw; + let data = s.data; + mem::forget(s); + MappedRwLockReadGuard { + raw, + data, + marker: PhantomData, + } + } +} + +impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { + /// Unlocks the `RwLock` using a fair unlock protocol. + /// + /// By default, `RwLock` is unfair and allow the current thread to re-lock + /// the `RwLock` before another has the chance to acquire the lock, even if + /// that thread has been blocked on the `RwLock` for a long time. This is + /// the default because it allows much higher throughput as it avoids + /// forcing a context switch on every `RwLock` unlock. This can result in one + /// thread acquiring a `RwLock` many more times than other threads. + /// + /// However in some cases it can be beneficial to ensure fairness by forcing + /// the lock to pass on to a waiting thread if there is one. This is done by + /// using this method instead of dropping the `MappedRwLockWriteGuard` normally. + #[inline] + pub fn unlock_fair(s: Self) { + s.raw.unlock_exclusive_fair(); + mem::forget(s); + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockWriteGuard<'a, R, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + unsafe { &*self.data } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for MappedRwLockWriteGuard<'a, R, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.data } + } +} + +impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, R, T> { + #[inline] + fn drop(&mut self) { + self.raw.unlock_exclusive(); + } +} + +#[cfg(feature = "owning_ref")] +unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress + for MappedRwLockWriteGuard<'a, R, T> +{} diff --git a/vendor/lock_api/.cargo-checksum.json b/vendor/lock_api/.cargo-checksum.json index dde064c5b8..5507dd1f12 100644 --- a/vendor/lock_api/.cargo-checksum.json +++ b/vendor/lock_api/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"9a369b3ff1ef121205879d10ba966bbccb81d6461843a75460f4cfcb82c3c849","src/lib.rs":"62142edfbe7e6cc04473aef25ab42553f02e4455ce567cb4303f0bbfee94d87d","src/mutex.rs":"d7ea4e06ae1a2d470e23bdfe73f52272f7c8b4231fe62fd9846e2a3773dcface","src/remutex.rs":"2fc11fec14af2886e507104e501caf6fddcf199ee7db38eabcd35ab9cf430d89","src/rwlock.rs":"45b940a9d046c7ee0c295237abac45f694c32a247724d93e3879a79f6e60b399"},"package":"949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"} \ No newline at end of file +{"files":{"Cargo.toml":"62073f7e3f8dd1c6996e2d2310af31b3f0c4a9c6a58cbfd1296d5d4335329c03","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"d9ed1f911f058d066ebfd024940da8a5c1ebbab6cfd65a633dfbc613573dd823","src/mutex.rs":"179f232bbbe8279365af427287566f1e1382ddbee13d611deccbce34705c447b","src/remutex.rs":"29e724285529bc4fdff5be3a1d3066253a6da493bdcebf024c4ccbdfdd94457c","src/rwlock.rs":"5661564ab948f3a71be008bf1abb5c40d5d5660ca2f6a7c57ae73e51f31ababf"},"package":"f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"} \ No newline at end of file diff --git a/vendor/lock_api/Cargo.toml b/vendor/lock_api/Cargo.toml index ae2dc215ab..0d16782902 100644 --- a/vendor/lock_api/Cargo.toml +++ b/vendor/lock_api/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,8 +11,9 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "lock_api" -version = "0.1.3" +version = "0.3.1" authors = ["Amanieu d'Antras "] description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." keywords = ["mutex", "rwlock", "lock", "no_std"] @@ -20,11 +21,16 @@ categories = ["concurrency", "no-std"] license = "Apache-2.0/MIT" repository = "https://github.com/Amanieu/parking_lot" [dependencies.owning_ref] -version = "0.3" +version = "0.4" optional = true [dependencies.scopeguard] -version = "0.3" +version = "1.0" +default-features = false + +[dependencies.serde] +version = "1.0.90" +optional = true default-features = false [features] diff --git a/vendor/env_logger-0.5.13/LICENSE-APACHE b/vendor/lock_api/LICENSE-APACHE similarity index 100% rename from vendor/env_logger-0.5.13/LICENSE-APACHE rename to vendor/lock_api/LICENSE-APACHE diff --git a/vendor/quote/LICENSE-MIT b/vendor/lock_api/LICENSE-MIT similarity index 100% rename from vendor/quote/LICENSE-MIT rename to vendor/lock_api/LICENSE-MIT diff --git a/vendor/lock_api/src/lib.rs b/vendor/lock_api/src/lib.rs index cb031b705a..d388d8a3ce 100644 --- a/vendor/lock_api/src/lib.rs +++ b/vendor/lock_api/src/lib.rs @@ -11,7 +11,7 @@ //! implementing custom lock types, it also allows users to write code which is //! generic with regards to different lock implementations. //! -//! Basic usage of this crate is very straightfoward: +//! Basic usage of this crate is very straightforward: //! //! 1. Create a raw lock type. This should only contain the lock state, not any //! data protected by the lock. @@ -27,15 +27,18 @@ //! # Example //! //! ``` -//! use lock_api::{RawMutex, Mutex}; -//! use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; +//! use lock_api::{RawMutex, Mutex, GuardSend}; +//! use std::sync::atomic::{AtomicBool, Ordering}; //! //! // 1. Define our raw lock type //! pub struct RawSpinlock(AtomicBool); //! //! // 2. Implement RawMutex for this type //! unsafe impl RawMutex for RawSpinlock { -//! const INIT: RawSpinlock = RawSpinlock(ATOMIC_BOOL_INIT); +//! const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false)); +//! +//! // A spinlock guard can be sent to another thread and unlocked there +//! type GuardMarker = GuardSend; //! //! fn lock(&self) { //! // Note: This isn't the best way of implementing a spinlock, but it @@ -82,14 +85,12 @@ #![no_std] #![warn(missing_docs)] +#![warn(rust_2018_idioms)] #![cfg_attr(feature = "nightly", feature(const_fn))] #[macro_use] extern crate scopeguard; -#[cfg(feature = "owning_ref")] -extern crate owning_ref; - /// Marker type which indicates that the Guard type for a lock is `Send`. pub struct GuardSend(()); @@ -97,10 +98,10 @@ pub struct GuardSend(()); pub struct GuardNoSend(*mut ()); mod mutex; -pub use mutex::*; +pub use crate::mutex::*; mod remutex; -pub use remutex::*; +pub use crate::remutex::*; mod rwlock; -pub use rwlock::*; +pub use crate::rwlock::*; diff --git a/vendor/lock_api/src/mutex.rs b/vendor/lock_api/src/mutex.rs index f2b838986f..95a46fb623 100644 --- a/vendor/lock_api/src/mutex.rs +++ b/vendor/lock_api/src/mutex.rs @@ -14,6 +14,9 @@ use core::ops::{Deref, DerefMut}; #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + /// Basic operations for a mutex. /// /// Types implementing this trait can be used by `Mutex` to form a safe and @@ -93,6 +96,35 @@ pub struct Mutex { data: UnsafeCell, } +// Copied and modified from serde +#[cfg(feature = "serde")] +impl Serialize for Mutex +where + R: RawMutex, + T: Serialize + ?Sized, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.lock().serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, R, T> Deserialize<'de> for Mutex +where + R: RawMutex, + T: Deserialize<'de> + ?Sized, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Mutex::new) + } +} + unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} @@ -101,20 +133,14 @@ impl Mutex { #[cfg(feature = "nightly")] #[inline] pub const fn new(val: T) -> Mutex { - Mutex { - data: UnsafeCell::new(val), - raw: R::INIT, - } + Mutex { data: UnsafeCell::new(val), raw: R::INIT } } /// Creates a new mutex in an unlocked state ready for use. #[cfg(not(feature = "nightly"))] #[inline] pub fn new(val: T) -> Mutex { - Mutex { - data: UnsafeCell::new(val), - raw: R::INIT, - } + Mutex { data: UnsafeCell::new(val), raw: R::INIT } } /// Consumes this mutex, returning the underlying data. @@ -126,12 +152,12 @@ impl Mutex { } impl Mutex { + /// # Safety + /// + /// The lock must be held when calling this method. #[inline] - fn guard(&self) -> MutexGuard { - MutexGuard { - mutex: self, - marker: PhantomData, - } + unsafe fn guard(&self) -> MutexGuard<'_, R, T> { + MutexGuard { mutex: self, marker: PhantomData } } /// Acquires a mutex, blocking the current thread until it is able to do so. @@ -144,9 +170,10 @@ impl Mutex { /// Attempts to lock a mutex in the thread which already holds the lock will /// result in a deadlock. #[inline] - pub fn lock(&self) -> MutexGuard { + pub fn lock(&self) -> MutexGuard<'_, R, T> { self.raw.lock(); - self.guard() + // SAFETY: The lock is held, as required. + unsafe { self.guard() } } /// Attempts to acquire this lock. @@ -157,9 +184,10 @@ impl Mutex { /// /// This function does not block. #[inline] - pub fn try_lock(&self) -> Option> { + pub fn try_lock(&self) -> Option> { if self.raw.try_lock() { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -230,9 +258,10 @@ impl Mutex { /// `None` is returned. Otherwise, an RAII guard is returned. The lock will /// be unlocked when the guard is dropped. #[inline] - pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { + pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { if self.raw.try_lock_for(timeout) { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -244,9 +273,10 @@ impl Mutex { /// `None` is returned. Otherwise, an RAII guard is returned. The lock will /// be unlocked when the guard is dropped. #[inline] - pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { + pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { if self.raw.try_lock_until(timeout) { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -268,10 +298,19 @@ impl From for Mutex { } impl fmt::Debug for Mutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), - None => f.pad("Mutex { }"), + None => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("") + } + } + + f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish() + } } } } @@ -281,8 +320,8 @@ impl fmt::Debug for Mutex { /// /// The data protected by the mutex can be accessed through this guard via its /// `Deref` and `DerefMut` implementations. -#[must_use] -pub struct MutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the Mutex will immediately unlock"] +pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> { mutex: &'a Mutex, marker: PhantomData<(&'a mut T, R::GuardMarker)>, } @@ -311,11 +350,30 @@ impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { let raw = &s.mutex.raw; let data = f(unsafe { &mut *s.mutex.data.get() }); mem::forget(s); - MappedMutexGuard { - raw, - data, - marker: PhantomData, - } + MappedMutexGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedMutexGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `MutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `MutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + let raw = &s.mutex.raw; + let data = match f(unsafe { &mut *s.mutex.data.get() }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedMutexGuard { raw, data, marker: PhantomData }) } /// Temporarily unlocks the mutex to execute the given function. @@ -401,6 +459,18 @@ impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> { } } +impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} @@ -411,8 +481,8 @@ unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<' /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. -#[must_use] -pub struct MappedMutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the Mutex will immediately unlock"] +pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> { raw: &'a R, data: *mut T, marker: PhantomData<&'a mut T>, @@ -420,19 +490,21 @@ pub struct MappedMutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> { unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MappedMutexGuard<'a, R, T> -{} +{ +} unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Send for MappedMutexGuard<'a, R, T> where R::GuardMarker: Send -{} +{ +} impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { /// Makes a new `MappedMutexGuard` for a component of the locked data. /// - /// This operation cannot fail as the `MutexGuard` passed + /// This operation cannot fail as the `MappedMutexGuard` passed /// in already locked the mutex. /// /// This is an associated function that needs to be - /// used as `MutexGuard::map(...)`. A method would interfere with methods of + /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the locked data. #[inline] pub fn map(s: Self, f: F) -> MappedMutexGuard<'a, R, U> @@ -442,11 +514,30 @@ impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { let raw = s.raw; let data = f(unsafe { &mut *s.data }); mem::forget(s); - MappedMutexGuard { - raw, - data, - marker: PhantomData, - } + MappedMutexGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedMutexGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `MappedMutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + let raw = s.raw; + let data = match f(unsafe { &mut *s.data }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedMutexGuard { raw, data, marker: PhantomData }) } } @@ -492,5 +583,19 @@ impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> { } } +impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for MappedMutexGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {} diff --git a/vendor/lock_api/src/remutex.rs b/vendor/lock_api/src/remutex.rs index 3bede403e1..69dcf01b4c 100644 --- a/vendor/lock_api/src/remutex.rs +++ b/vendor/lock_api/src/remutex.rs @@ -5,18 +5,26 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use core::cell::{Cell, UnsafeCell}; -use core::fmt; -use core::marker::PhantomData; -use core::mem; -use core::ops::Deref; -use core::sync::atomic::{AtomicUsize, Ordering}; -use mutex::{RawMutex, RawMutexFair, RawMutexTimed}; -use GuardNoSend; +use crate::{ + mutex::{RawMutex, RawMutexFair, RawMutexTimed}, + GuardNoSend, +}; +use core::{ + cell::{Cell, UnsafeCell}, + fmt, + marker::PhantomData, + mem, + num::NonZeroUsize, + ops::Deref, + sync::atomic::{AtomicUsize, Ordering}, +}; #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + /// Helper trait which returns a non-zero thread ID. /// /// The simplest way to implement this trait is to return the address of a @@ -33,7 +41,7 @@ pub unsafe trait GetThreadId { /// Returns a non-zero thread ID which identifies the current thread of /// execution. - fn nonzero_thread_id(&self) -> usize; + fn nonzero_thread_id(&self) -> NonZeroUsize; } struct RawReentrantMutex { @@ -46,19 +54,17 @@ struct RawReentrantMutex { impl RawReentrantMutex { #[inline] fn lock_internal bool>(&self, try_lock: F) -> bool { - let id = self.get_thread_id.nonzero_thread_id(); + let id = self.get_thread_id.nonzero_thread_id().get(); if self.owner.load(Ordering::Relaxed) == id { self.lock_count.set( - self.lock_count - .get() - .checked_add(1) - .expect("ReentrantMutex lock count overflow"), + self.lock_count.get().checked_add(1).expect("ReentrantMutex lock count overflow"), ); } else { if !try_lock() { return false; } self.owner.store(id, Ordering::Relaxed); + debug_assert_eq!(self.lock_count.get(), 0); self.lock_count.set(1); } true @@ -80,11 +86,10 @@ impl RawReentrantMutex { #[inline] fn unlock(&self) { let lock_count = self.lock_count.get() - 1; + self.lock_count.set(lock_count); if lock_count == 0 { self.owner.store(0, Ordering::Relaxed); self.mutex.unlock(); - } else { - self.lock_count.set(lock_count); } } } @@ -93,11 +98,10 @@ impl RawReentrantMutex { #[inline] fn unlock_fair(&self) { let lock_count = self.lock_count.get() - 1; + self.lock_count.set(lock_count); if lock_count == 0 { self.owner.store(0, Ordering::Relaxed); self.mutex.unlock_fair(); - } else { - self.lock_count.set(lock_count); } } @@ -140,12 +144,45 @@ pub struct ReentrantMutex { data: UnsafeCell, } +// Copied and modified from serde +#[cfg(feature = "serde")] +impl Serialize for ReentrantMutex +where + R: RawMutex, + G: GetThreadId, + T: Serialize + ?Sized, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.lock().serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, R, G, T> Deserialize<'de> for ReentrantMutex +where + R: RawMutex, + G: GetThreadId, + T: Deserialize<'de> + ?Sized, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(ReentrantMutex::new) + } +} + unsafe impl Send for ReentrantMutex -{} +{ +} unsafe impl Sync for ReentrantMutex -{} +{ +} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state ready for use. @@ -187,12 +224,12 @@ impl ReentrantMutex { } impl ReentrantMutex { + /// # Safety + /// + /// The lock must be held when calling this method. #[inline] - fn guard(&self) -> ReentrantMutexGuard { - ReentrantMutexGuard { - remutex: &self, - marker: PhantomData, - } + unsafe fn guard(&self) -> ReentrantMutexGuard<'_, R, G, T> { + ReentrantMutexGuard { remutex: &self, marker: PhantomData } } /// Acquires a reentrant mutex, blocking the current thread until it is able @@ -206,9 +243,10 @@ impl ReentrantMutex { /// returned to allow scoped unlock of the lock. When the guard goes out of /// scope, the mutex will be unlocked. #[inline] - pub fn lock(&self) -> ReentrantMutexGuard { + pub fn lock(&self) -> ReentrantMutexGuard<'_, R, G, T> { self.raw.lock(); - self.guard() + // SAFETY: The lock is held, as required. + unsafe { self.guard() } } /// Attempts to acquire this lock. @@ -219,9 +257,10 @@ impl ReentrantMutex { /// /// This function does not block. #[inline] - pub fn try_lock(&self) -> Option> { + pub fn try_lock(&self) -> Option> { if self.raw.try_lock() { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -268,7 +307,7 @@ impl ReentrantMutex { } impl ReentrantMutex { - /// Forcibly unlocks the mutex using a fair unlock procotol. + /// Forcibly unlocks the mutex using a fair unlock protocol. /// /// This is useful when combined with `mem::forget` to hold a lock without /// the need to maintain a `ReentrantMutexGuard` object alive, for example when @@ -292,9 +331,10 @@ impl ReentrantMutex { /// `None` is returned. Otherwise, an RAII guard is returned. The lock will /// be unlocked when the guard is dropped. #[inline] - pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { + pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { if self.raw.try_lock_for(timeout) { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -306,9 +346,10 @@ impl ReentrantMutex { /// `None` is returned. Otherwise, an RAII guard is returned. The lock will /// be unlocked when the guard is dropped. #[inline] - pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { + pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { if self.raw.try_lock_until(timeout) { - Some(self.guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.guard() }) } else { None } @@ -330,13 +371,19 @@ impl From for ReentrantMutex { } impl fmt::Debug for ReentrantMutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { - Some(guard) => f - .debug_struct("ReentrantMutex") - .field("data", &&*guard) - .finish(), - None => f.pad("ReentrantMutex { }"), + Some(guard) => f.debug_struct("ReentrantMutex").field("data", &&*guard).finish(), + None => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("") + } + } + + f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish() + } } } } @@ -346,15 +393,16 @@ impl fmt::Debug for Reentra /// /// The data protected by the mutex can be accessed through this guard via its /// `Deref` implementation. -#[must_use] -pub struct ReentrantMutexGuard<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the ReentrantMutex will immediately unlock"] +pub struct ReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { remutex: &'a ReentrantMutex, marker: PhantomData<(&'a T, GuardNoSend)>, } unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync for ReentrantMutexGuard<'a, R, G, T> -{} +{ +} impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGuard<'a, R, G, T> { /// Returns a reference to the original `ReentrantMutex` object. @@ -378,11 +426,33 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGu let raw = &s.remutex.raw; let data = f(unsafe { &*s.remutex.data.get() }); mem::forget(s); - MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - } + MappedReentrantMutexGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedReentrantMutexGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `ReentrantMutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map( + s: Self, + f: F, + ) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + let raw = &s.remutex.raw; + let data = match f(unsafe { &mut *s.remutex.data.get() }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedReentrantMutexGuard { raw, data, marker: PhantomData }) } /// Temporarily unlocks the mutex to execute the given function. @@ -467,10 +537,27 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop } } +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug + for ReentrantMutexGuard<'a, R, G, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for ReentrantMutexGuard<'a, R, G, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress for ReentrantMutexGuard<'a, R, G, T> -{} +{ +} /// An RAII mutex guard returned by `ReentrantMutexGuard::map`, which can point to a /// subfield of the protected data. @@ -479,8 +566,8 @@ unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAdd /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. -#[must_use] -pub struct MappedReentrantMutexGuard<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the ReentrantMutex will immediately unlock"] +pub struct MappedReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { raw: &'a RawReentrantMutex, data: *const T, marker: PhantomData<&'a T>, @@ -488,18 +575,19 @@ pub struct MappedReentrantMutexGuard<'a, R: RawMutex + 'a, G: GetThreadId + 'a, unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MappedReentrantMutexGuard<'a, R, G, T> -{} +{ +} impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> MappedReentrantMutexGuard<'a, R, G, T> { /// Makes a new `MappedReentrantMutexGuard` for a component of the locked data. /// - /// This operation cannot fail as the `ReentrantMutexGuard` passed + /// This operation cannot fail as the `MappedReentrantMutexGuard` passed /// in already locked the mutex. /// /// This is an associated function that needs to be - /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of + /// used as `MappedReentrantMutexGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the locked data. #[inline] pub fn map(s: Self, f: F) -> MappedReentrantMutexGuard<'a, R, G, U> @@ -509,11 +597,33 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> let raw = s.raw; let data = f(unsafe { &*s.data }); mem::forget(s); - MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - } + MappedReentrantMutexGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedReentrantMutexGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `MappedReentrantMutexGuard` passed + /// in already locked the mutex. + /// + /// This is an associated function that needs to be + /// used as `MappedReentrantMutexGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map( + s: Self, + f: F, + ) -> Result, Self> + where + F: FnOnce(&T) -> Option<&U>, + { + let raw = s.raw; + let data = match f(unsafe { &*s.data }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedReentrantMutexGuard { raw, data, marker: PhantomData }) } } @@ -558,7 +668,24 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop } } +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug + for MappedReentrantMutexGuard<'a, R, G, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for MappedReentrantMutexGuard<'a, R, G, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress for MappedReentrantMutexGuard<'a, R, G, T> -{} +{ +} diff --git a/vendor/lock_api/src/rwlock.rs b/vendor/lock_api/src/rwlock.rs index 904ff95791..874ebd60bb 100644 --- a/vendor/lock_api/src/rwlock.rs +++ b/vendor/lock_api/src/rwlock.rs @@ -14,6 +14,9 @@ use core::ops::{Deref, DerefMut}; #[cfg(feature = "owning_ref")] use owning_ref::StableAddress; +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + /// Basic operations for a reader-writer lock. /// /// Types implementing this trait can be used by `RwLock` to form a safe and @@ -230,6 +233,35 @@ pub struct RwLock { data: UnsafeCell, } +// Copied and modified from serde +#[cfg(feature = "serde")] +impl Serialize for RwLock +where + R: RawRwLock, + T: Serialize + ?Sized, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.read().serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, R, T> Deserialize<'de> for RwLock +where + R: RawRwLock, + T: Deserialize<'de> + ?Sized, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(RwLock::new) + } +} + unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} @@ -238,20 +270,14 @@ impl RwLock { #[cfg(feature = "nightly")] #[inline] pub const fn new(val: T) -> RwLock { - RwLock { - data: UnsafeCell::new(val), - raw: R::INIT, - } + RwLock { data: UnsafeCell::new(val), raw: R::INIT } } /// Creates a new instance of an `RwLock` which is unlocked. #[cfg(not(feature = "nightly"))] #[inline] pub fn new(val: T) -> RwLock { - RwLock { - data: UnsafeCell::new(val), - raw: R::INIT, - } + RwLock { data: UnsafeCell::new(val), raw: R::INIT } } /// Consumes this `RwLock`, returning the underlying data. @@ -263,20 +289,20 @@ impl RwLock { } impl RwLock { + /// # Safety + /// + /// The lock must be held when calling this method. #[inline] - fn read_guard(&self) -> RwLockReadGuard { - RwLockReadGuard { - rwlock: self, - marker: PhantomData, - } + unsafe fn read_guard(&self) -> RwLockReadGuard<'_, R, T> { + RwLockReadGuard { rwlock: self, marker: PhantomData } } + /// # Safety + /// + /// The lock must be held when calling this method. #[inline] - fn write_guard(&self) -> RwLockWriteGuard { - RwLockWriteGuard { - rwlock: self, - marker: PhantomData, - } + unsafe fn write_guard(&self) -> RwLockWriteGuard<'_, R, T> { + RwLockWriteGuard { rwlock: self, marker: PhantomData } } /// Locks this `RwLock` with shared read access, blocking the current thread @@ -292,9 +318,10 @@ impl RwLock { /// Returns an RAII guard which will release this thread's shared access /// once it is dropped. #[inline] - pub fn read(&self) -> RwLockReadGuard { + pub fn read(&self) -> RwLockReadGuard<'_, R, T> { self.raw.lock_shared(); - self.read_guard() + // SAFETY: The lock is held, as required. + unsafe { self.read_guard() } } /// Attempts to acquire this `RwLock` with shared read access. @@ -305,9 +332,10 @@ impl RwLock { /// /// This function does not block. #[inline] - pub fn try_read(&self) -> Option> { + pub fn try_read(&self) -> Option> { if self.raw.try_lock_shared() { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -322,9 +350,10 @@ impl RwLock { /// Returns an RAII guard which will drop the write access of this `RwLock` /// when dropped. #[inline] - pub fn write(&self) -> RwLockWriteGuard { + pub fn write(&self) -> RwLockWriteGuard<'_, R, T> { self.raw.lock_exclusive(); - self.write_guard() + // SAFETY: The lock is held, as required. + unsafe { self.write_guard() } } /// Attempts to lock this `RwLock` with exclusive write access. @@ -335,9 +364,10 @@ impl RwLock { /// /// This function does not block. #[inline] - pub fn try_write(&self) -> Option> { + pub fn try_write(&self) -> Option> { if self.raw.try_lock_exclusive() { - Some(self.write_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.write_guard() }) } else { None } @@ -441,9 +471,10 @@ impl RwLock { /// `None` is returned. Otherwise, an RAII guard is returned which will /// release the shared access when it is dropped. #[inline] - pub fn try_read_for(&self, timeout: R::Duration) -> Option> { + pub fn try_read_for(&self, timeout: R::Duration) -> Option> { if self.raw.try_lock_shared_for(timeout) { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -456,9 +487,10 @@ impl RwLock { /// `None` is returned. Otherwise, an RAII guard is returned which will /// release the shared access when it is dropped. #[inline] - pub fn try_read_until(&self, timeout: R::Instant) -> Option> { + pub fn try_read_until(&self, timeout: R::Instant) -> Option> { if self.raw.try_lock_shared_until(timeout) { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -471,9 +503,10 @@ impl RwLock { /// `None` is returned. Otherwise, an RAII guard is returned which will /// release the exclusive access when it is dropped. #[inline] - pub fn try_write_for(&self, timeout: R::Duration) -> Option> { + pub fn try_write_for(&self, timeout: R::Duration) -> Option> { if self.raw.try_lock_exclusive_for(timeout) { - Some(self.write_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.write_guard() }) } else { None } @@ -486,9 +519,10 @@ impl RwLock { /// `None` is returned. Otherwise, an RAII guard is returned which will /// release the exclusive access when it is dropped. #[inline] - pub fn try_write_until(&self, timeout: R::Instant) -> Option> { + pub fn try_write_until(&self, timeout: R::Instant) -> Option> { if self.raw.try_lock_exclusive_until(timeout) { - Some(self.write_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.write_guard() }) } else { None } @@ -512,9 +546,10 @@ impl RwLock { /// Returns an RAII guard which will release this thread's shared access /// once it is dropped. #[inline] - pub fn read_recursive(&self) -> RwLockReadGuard { + pub fn read_recursive(&self) -> RwLockReadGuard<'_, R, T> { self.raw.lock_shared_recursive(); - self.read_guard() + // SAFETY: The lock is held, as required. + unsafe { self.read_guard() } } /// Attempts to acquire this `RwLock` with shared read access. @@ -528,9 +563,10 @@ impl RwLock { /// /// This function does not block. #[inline] - pub fn try_read_recursive(&self) -> Option> { + pub fn try_read_recursive(&self) -> Option> { if self.raw.try_lock_shared_recursive() { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -549,9 +585,13 @@ impl RwLock { /// lock is held at the time of the call. See the documentation for /// `read_recursive` for details. #[inline] - pub fn try_read_recursive_for(&self, timeout: R::Duration) -> Option> { + pub fn try_read_recursive_for( + &self, + timeout: R::Duration, + ) -> Option> { if self.raw.try_lock_shared_recursive_for(timeout) { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -564,9 +604,13 @@ impl RwLock { /// `None` is returned. Otherwise, an RAII guard is returned which will /// release the shared access when it is dropped. #[inline] - pub fn try_read_recursive_until(&self, timeout: R::Instant) -> Option> { + pub fn try_read_recursive_until( + &self, + timeout: R::Instant, + ) -> Option> { if self.raw.try_lock_shared_recursive_until(timeout) { - Some(self.read_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.read_guard() }) } else { None } @@ -574,12 +618,12 @@ impl RwLock { } impl RwLock { + /// # Safety + /// + /// The lock must be held when calling this method. #[inline] - fn upgradable_guard(&self) -> RwLockUpgradableReadGuard { - RwLockUpgradableReadGuard { - rwlock: self, - marker: PhantomData, - } + unsafe fn upgradable_guard(&self) -> RwLockUpgradableReadGuard<'_, R, T> { + RwLockUpgradableReadGuard { rwlock: self, marker: PhantomData } } /// Locks this `RwLock` with upgradable read access, blocking the current thread @@ -592,9 +636,10 @@ impl RwLock { /// Returns an RAII guard which will release this thread's shared access /// once it is dropped. #[inline] - pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard { + pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<'_, R, T> { self.raw.lock_upgradable(); - self.upgradable_guard() + // SAFETY: The lock is held, as required. + unsafe { self.upgradable_guard() } } /// Attempts to acquire this `RwLock` with upgradable read access. @@ -605,9 +650,10 @@ impl RwLock { /// /// This function does not block. #[inline] - pub fn try_upgradable_read(&self) -> Option> { + pub fn try_upgradable_read(&self) -> Option> { if self.raw.try_lock_upgradable() { - Some(self.upgradable_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.upgradable_guard() }) } else { None } @@ -625,9 +671,10 @@ impl RwLock { pub fn try_upgradable_read_for( &self, timeout: R::Duration, - ) -> Option> { + ) -> Option> { if self.raw.try_lock_upgradable_for(timeout) { - Some(self.upgradable_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.upgradable_guard() }) } else { None } @@ -643,9 +690,10 @@ impl RwLock { pub fn try_upgradable_read_until( &self, timeout: R::Instant, - ) -> Option> { + ) -> Option> { if self.raw.try_lock_upgradable_until(timeout) { - Some(self.upgradable_guard()) + // SAFETY: The lock is held, as required. + Some(unsafe { self.upgradable_guard() }) } else { None } @@ -667,18 +715,27 @@ impl From for RwLock { } impl fmt::Debug for RwLock { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_read() { Some(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(), - None => f.pad("RwLock { }"), + None => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("") + } + } + + f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish() + } } } } /// RAII structure used to release the shared read access of a lock when /// dropped. -#[must_use] -pub struct RwLockReadGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the RwLock will immediately unlock"] +pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { rwlock: &'a RwLock, marker: PhantomData<(&'a T, R::GuardMarker)>, } @@ -707,11 +764,30 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { let raw = &s.rwlock.raw; let data = f(unsafe { &*s.rwlock.data.get() }); mem::forget(s); - MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - } + MappedRwLockReadGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedRwLockReadGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `RwLockReadGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&T) -> Option<&U>, + { + let raw = &s.rwlock.raw; + let data = match f(unsafe { &*s.rwlock.data.get() }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedRwLockReadGuard { raw, data, marker: PhantomData }) } /// Temporarily unlocks the `RwLock` to execute the given function. @@ -792,13 +868,27 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> { } } +impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockReadGuard<'a, R, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for RwLockReadGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {} /// RAII structure used to release the exclusive write access of a lock when /// dropped. -#[must_use] -pub struct RwLockWriteGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the RwLock will immediately unlock"] +pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { rwlock: &'a RwLock, marker: PhantomData<(&'a mut T, R::GuardMarker)>, } @@ -820,18 +910,37 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the locked data. #[inline] - pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> + pub fn map(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> where F: FnOnce(&mut T) -> &mut U, { - let raw = &orig.rwlock.raw; - let data = f(unsafe { &mut *orig.rwlock.data.get() }); - mem::forget(orig); - MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - } + let raw = &s.rwlock.raw; + let data = f(unsafe { &mut *s.rwlock.data.get() }); + mem::forget(s); + MappedRwLockWriteGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `RwLockWriteGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + let raw = &s.rwlock.raw; + let data = match f(unsafe { &mut *s.rwlock.data.get() }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedRwLockWriteGuard { raw, data, marker: PhantomData }) } /// Temporarily unlocks the `RwLock` to execute the given function. @@ -860,10 +969,7 @@ impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> s.rwlock.raw.downgrade(); let rwlock = s.rwlock; mem::forget(s); - RwLockReadGuard { - rwlock, - marker: PhantomData, - } + RwLockReadGuard { rwlock, marker: PhantomData } } } @@ -878,10 +984,7 @@ impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, s.rwlock.raw.downgrade_to_upgradable(); let rwlock = s.rwlock; mem::forget(s); - RwLockUpgradableReadGuard { - rwlock, - marker: PhantomData, - } + RwLockUpgradableReadGuard { rwlock, marker: PhantomData } } } @@ -953,20 +1056,35 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> } } +impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockWriteGuard<'a, R, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for RwLockWriteGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {} /// RAII structure used to release the upgradable read access of a lock when /// dropped. -#[must_use] -pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the RwLock will immediately unlock"] +pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> { rwlock: &'a RwLock, marker: PhantomData<(&'a T, R::GuardMarker)>, } unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + Sync + 'a> Sync for RwLockUpgradableReadGuard<'a, R, T> -{} +{ +} impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { /// Returns a reference to the original reader-writer lock object. @@ -989,15 +1107,12 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, } /// Atomically upgrades an upgradable read lock lock into a exclusive write lock, - /// blocking the current thread until it can be aquired. + /// blocking the current thread until it can be acquired. pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> { s.rwlock.raw.upgrade(); let rwlock = s.rwlock; mem::forget(s); - RwLockWriteGuard { - rwlock, - marker: PhantomData, - } + RwLockWriteGuard { rwlock, marker: PhantomData } } /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock. @@ -1007,10 +1122,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, if s.rwlock.raw.try_upgrade() { let rwlock = s.rwlock; mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) + Ok(RwLockWriteGuard { rwlock, marker: PhantomData }) } else { Err(s) } @@ -1075,10 +1187,7 @@ impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableRead s.rwlock.raw.downgrade_upgradable(); let rwlock = s.rwlock; mem::forget(s); - RwLockReadGuard { - rwlock, - marker: PhantomData, - } + RwLockReadGuard { rwlock, marker: PhantomData } } } @@ -1095,10 +1204,7 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar if s.rwlock.raw.try_upgrade_for(timeout) { let rwlock = s.rwlock; mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) + Ok(RwLockWriteGuard { rwlock, marker: PhantomData }) } else { Err(s) } @@ -1117,10 +1223,7 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar if s.rwlock.raw.try_upgrade_until(timeout) { let rwlock = s.rwlock; mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) + Ok(RwLockWriteGuard { rwlock, marker: PhantomData }) } else { Err(s) } @@ -1142,10 +1245,27 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableRead } } +impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug + for RwLockUpgradableReadGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for RwLockUpgradableReadGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress for RwLockUpgradableReadGuard<'a, R, T> -{} +{ +} /// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a /// subfield of the protected data. @@ -1154,8 +1274,8 @@ unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. -#[must_use] -pub struct MappedRwLockReadGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the RwLock will immediately unlock"] +pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { raw: &'a R, data: *const T, marker: PhantomData<&'a T>, @@ -1164,7 +1284,8 @@ pub struct MappedRwLockReadGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockReadGuard<'a, R, T> {} unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Send for MappedRwLockReadGuard<'a, R, T> where R::GuardMarker: Send -{} +{ +} impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { /// Make a new `MappedRwLockReadGuard` for a component of the locked data. @@ -1183,11 +1304,30 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { let raw = s.raw; let data = f(unsafe { &*s.data }); mem::forget(s); - MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - } + MappedRwLockReadGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedRwLockReadGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `MappedRwLockReadGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&T) -> Option<&U>, + { + let raw = s.raw; + let data = match f(unsafe { &*s.data }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedRwLockReadGuard { raw, data, marker: PhantomData }) } } @@ -1226,10 +1366,27 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R } } +impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug + for MappedRwLockReadGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for MappedRwLockReadGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for MappedRwLockReadGuard<'a, R, T> -{} +{ +} /// An RAII write lock guard returned by `RwLockWriteGuard::map`, which can point to a /// subfield of the protected data. @@ -1238,8 +1395,8 @@ unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. -#[must_use] -pub struct MappedRwLockWriteGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { +#[must_use = "if unused the RwLock will immediately unlock"] +pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { raw: &'a R, data: *mut T, marker: PhantomData<&'a mut T>, @@ -1247,10 +1404,12 @@ pub struct MappedRwLockWriteGuard<'a, R: RawRwLock + 'a, T: ?Sized + 'a> { unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockWriteGuard<'a, R, T> -{} +{ +} unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Send for MappedRwLockWriteGuard<'a, R, T> where R::GuardMarker: Send -{} +{ +} impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { /// Make a new `MappedRwLockWriteGuard` for a component of the locked data. @@ -1262,18 +1421,37 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the locked data. #[inline] - pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> + pub fn map(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> where F: FnOnce(&mut T) -> &mut U, { - let raw = orig.raw; - let data = f(unsafe { &mut *orig.data }); - mem::forget(orig); - MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - } + let raw = s.raw; + let data = f(unsafe { &mut *s.data }); + mem::forget(s); + MappedRwLockWriteGuard { raw, data, marker: PhantomData } + } + + /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the + /// locked data. The original guard is return if the closure returns `None`. + /// + /// This operation cannot fail as the `MappedRwLockWriteGuard` passed + /// in already locked the data. + /// + /// This is an associated function that needs to be + /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of + /// the same name on the contents of the locked data. + #[inline] + pub fn try_map(s: Self, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + let raw = s.raw; + let data = match f(unsafe { &mut *s.data }) { + Some(data) => data, + None => return Err(s), + }; + mem::forget(s); + Ok(MappedRwLockWriteGuard { raw, data, marker: PhantomData }) } } @@ -1289,11 +1467,7 @@ impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, let raw = s.raw; let data = s.data; mem::forget(s); - MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - } + MappedRwLockReadGuard { raw, data, marker: PhantomData } } } @@ -1339,7 +1513,24 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, } } +impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug + for MappedRwLockWriteGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display + for MappedRwLockWriteGuard<'a, R, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + #[cfg(feature = "owning_ref")] unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for MappedRwLockWriteGuard<'a, R, T> -{} +{ +} diff --git a/vendor/log/.cargo-checksum.json b/vendor/log/.cargo-checksum.json index 31dc666b23..c9cef5d2c5 100644 --- a/vendor/log/.cargo-checksum.json +++ b/vendor/log/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"817c711701c9925f2494c5a2e09c679efd4026e121395b0167e722eb827eb2bf","Cargo.toml":"86f094aa5d1cea5b682852ec8a80a3cb954fc3d5267bd201e2e956d89b17f4aa","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"ebfbd97d184c4474295e36e30e45779bb40bc7c07610734058dfa272a922927e","appveyor.yml":"d5376a881aef6dc3bed6a6b51f1f1c3801b88fc77a12895f6953190256e965bc","src/lib.rs":"43acb02c1d3440235e464b6ab51e52824a7d604390e278d098054e76e686b798","src/macros.rs":"728a5309f35c84895ff1935c712f57464e2239dddb09b6fd84ff289a66c34b46","src/serde.rs":"a5ae50d6f5ac538a5ca57ee58031a2582afa6989c741574584756632a4131ba7","tests/filters.rs":"6aee024d4594b4fde772e35c5d3318e5aa5d9aa4eaeafb04e4c7c922be4ac837"},"package":"c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"} \ No newline at end of file +{"files":{"CHANGELOG.md":"4a384a648f3c5f9deed5463bbcdb92cf95dfe86d755767c0c21140d0539c1243","Cargo.toml":"cde739d8e087cc2515bc06d8ce327648606575e6dd51b74fb0ffd6a329381ba1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"0a6436eede658249802b63f1e693b28c9f80a2da2697bb80a2677e6c253c3a7d","build.rs":"16a49ad8a5b11a610382f904c72435ce3201b0807c584128c7e61fbb59c76b09","src/kv/error.rs":"296f6af53062a4526bb75eb4dbf955c75aed3b6332c260dc5bd7f0bc68c2d8c7","src/kv/key.rs":"68077f9ad149b28ccdeacd9e95c44c292b68d7fa0823aac5e022e2f3df6120e6","src/kv/mod.rs":"3397573933689b11ca5ad526193166c1e4f665e5692c38cd8fdb63a5aa61f7bf","src/kv/source.rs":"3783ac96b54e24fe6525f9e3cec91425800267f842704d947fea27ee344025a2","src/kv/value/impls.rs":"c8d4cb4e746e7b5a6e1f1993145c2b5309ac556f7ffc757fb80bb10b89bfa40d","src/kv/value/internal.rs":"b7e7d94d018d0207dfb30350a2ce916dc124c48c2e056e7637c159132c707a59","src/kv/value/mod.rs":"a4732af6fb9b3fad8ddf9dd5f9da90689eb9023984ff1f455f871ed32fde4aef","src/kv/value/test.rs":"99e0b87dd8822e7f148a3acfd1dd050718e2aee3ecd9314849076bf043a0a3e9","src/lib.rs":"c594c4a71bff2118e120c9c64e1e2e866dc76489af007965b6c67e57bf1a1797","src/macros.rs":"68cbe1a49a3ac846d6b80d291f427a70dbad0f57dac8beecac7449723293bd99","src/serde.rs":"4677851fba9d43adcddeb94c416af9e06eb70d4fb86e2840256e1edfc4638fef","tests/filters.rs":"90cae6653ba6dc3a462bab2a0b96cb66d5d21882492118bfd6999c0baff1b0e5"},"package":"14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"} \ No newline at end of file diff --git a/vendor/log/CHANGELOG.md b/vendor/log/CHANGELOG.md index edc161783f..e04562b155 100644 --- a/vendor/log/CHANGELOG.md +++ b/vendor/log/CHANGELOG.md @@ -2,6 +2,26 @@ ## [Unreleased] +## [0.4.8] - 2019-07-28 + +### New + +* Support attempting to get `Record` fields as static strings. + +## [0.4.7] - 2019-07-06 + +### New + +* Support for embedded environments with thread-unsafe initialization. +* Initial unstable support for capturing structured data under the `kv_unstable` +feature gate. This new API doesn't affect existing users and may change in future +patches (so those changes may not appear in the changelog until it stabilizes). + +### Improved + +* Docs for using `log` with the 2018 edition. +* Error messages for macros missing arguments. + ## [0.4.6] - 2018-10-27 ### Improved @@ -112,7 +132,9 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.6...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.8...HEAD +[0.4.8]: https://github.com/rust-lang-nursery/log/compare/0.4.7...0.4.8 +[0.4.7]: https://github.com/rust-lang-nursery/log/compare/0.4.6...0.4.7 [0.4.6]: https://github.com/rust-lang-nursery/log/compare/0.4.5...0.4.6 [0.4.5]: https://github.com/rust-lang-nursery/log/compare/0.4.4...0.4.5 [0.4.4]: https://github.com/rust-lang-nursery/log/compare/0.4.3...0.4.4 diff --git a/vendor/log/Cargo.toml b/vendor/log/Cargo.toml index c589af93b5..146060f8fa 100644 --- a/vendor/log/Cargo.toml +++ b/vendor/log/Cargo.toml @@ -12,18 +12,19 @@ [package] name = "log" -version = "0.4.6" +version = "0.4.8" authors = ["The Rust Project Developers"] +build = "build.rs" +exclude = ["rfcs/**/*", "/.travis.yml", "/appveyor.yml"] description = "A lightweight logging facade for Rust\n" -homepage = "https://github.com/rust-lang/log" documentation = "https://docs.rs/log" readme = "README.md" keywords = ["logging"] categories = ["development-tools::debugging"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/log" [package.metadata.docs.rs] -features = ["std", "serde"] +features = ["std", "serde", "kv_unstable_sval"] [[test]] name = "filters" @@ -35,10 +36,21 @@ version = "0.1.2" version = "1.0" optional = true default-features = false + +[dependencies.sval] +version = "0.4.2" +optional = true +default-features = false [dev-dependencies.serde_test] version = "1.0" +[dev-dependencies.sval] +version = "0.4.2" +features = ["test"] + [features] +kv_unstable = [] +kv_unstable_sval = ["kv_unstable", "sval/fmt"] max_level_debug = [] max_level_error = [] max_level_info = [] diff --git a/vendor/log/README.md b/vendor/log/README.md index b7884ad834..5fbcc97012 100644 --- a/vendor/log/README.md +++ b/vendor/log/README.md @@ -3,7 +3,7 @@ log A Rust library providing a lightweight logging *facade*. -[![Build Status](https://travis-ci.org/rust-lang-nursery/log.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/log) +[![Build Status](https://travis-ci.com/rust-lang-nursery/log.svg?branch=master)](https://travis-ci.com/rust-lang-nursery/log) [![Build status](https://ci.appveyor.com/api/projects/status/nopdjmmjt45xcrki?svg=true)](https://ci.appveyor.com/project/alexcrichton/log) [![Latest version](https://img.shields.io/crates/v/log.svg)](https://crates.io/crates/log) [![Documentation](https://docs.rs/log/badge.svg)](https://docs.rs/log) @@ -16,6 +16,13 @@ logging implementation. Libraries can use the logging API provided by this crate, and the consumer of those libraries can choose the logging implementation that is most suitable for its use case. + +## Minimum supported `rustc` + +`1.16.0+` + +This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes. + ## Usage ## In libraries @@ -29,8 +36,7 @@ log = "0.4" ``` ```rust -#[macro_use] -extern crate log; +use log::{info, trace, warn}; pub fn shave_the_yak(yak: &mut Yak) { trace!("Commencing yak shaving"); @@ -50,19 +56,9 @@ pub fn shave_the_yak(yak: &mut Yak) { } ``` -If you use Rust 2018, you can use instead the following code to import the crate macros: - -```rust -use log::{info, trace, warn}; - -pub fn shave_the_yak(yak: &mut Yak) { - // … -} -``` - ## In executables -In order to produce log output executables have to use a logger implementation compatible with the facade. +In order to produce log output, executables have to use a logger implementation compatible with the facade. There are many available implementations to chose from, here are some of the most popular ones: * Simple minimal loggers: @@ -79,6 +75,8 @@ There are many available implementations to chose from, here are some of the mos * [`syslog`](https://docs.rs/syslog/*/syslog/) * [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/) * [`android_log`](https://docs.rs/android_log/*/android_log/) +* For WebAssembly binaries: + * [`console_log`](https://docs.rs/console_log/*/console_log/) Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a diff --git a/vendor/log/appveyor.yml b/vendor/log/appveyor.yml deleted file mode 100644 index eb6786dd11..0000000000 --- a/vendor/log/appveyor.yml +++ /dev/null @@ -1,19 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - - TARGET: i686-pc-windows-msvc - - TARGET: i686-pc-windows-gnu -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - SET PATH=%PATH%;C:\MinGW\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --verbose - - cargo test --verbose --features serde - - cargo test --verbose --features std diff --git a/vendor/log/build.rs b/vendor/log/build.rs new file mode 100644 index 0000000000..6717bf0f70 --- /dev/null +++ b/vendor/log/build.rs @@ -0,0 +1,14 @@ +//! This build script detects target platforms that lack proper support for +//! atomics and sets `cfg` flags accordingly. + +use std::env; + +fn main() { + let target = env::var("TARGET").unwrap(); + + if !target.starts_with("thumbv6") { + println!("cargo:rustc-cfg=atomic_cas"); + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/vendor/log/src/kv/error.rs b/vendor/log/src/kv/error.rs new file mode 100644 index 0000000000..0f5652f923 --- /dev/null +++ b/vendor/log/src/kv/error.rs @@ -0,0 +1,88 @@ +use std::fmt; + +/// An error encountered while working with structured data. +#[derive(Debug)] +pub struct Error { + inner: Inner +} + +#[derive(Debug)] +enum Inner { + #[cfg(feature = "std")] + Boxed(std_support::BoxedError), + Msg(&'static str), + Fmt, +} + +impl Error { + /// Create an error from a message. + pub fn msg(msg: &'static str) -> Self { + Error { + inner: Inner::Msg(msg), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Inner::*; + match &self.inner { + #[cfg(feature = "std")] + &Boxed(ref err) => err.fmt(f), + &Msg(ref msg) => msg.fmt(f), + &Fmt => fmt::Error.fmt(f), + } + } +} + +impl From for Error { + fn from(_: fmt::Error) -> Self { + Error { + inner: Inner::Fmt, + } + } +} + +impl From for fmt::Error { + fn from(_: Error) -> Self { + fmt::Error + } +} + +#[cfg(feature = "std")] +mod std_support { + use super::*; + use std::{error, io}; + + pub(super) type BoxedError = Box; + + impl Error { + /// Create an error from a standard error type. + pub fn boxed(err: E) -> Self + where + E: Into, + { + Error { + inner: Inner::Boxed(err.into()) + } + } + } + + impl error::Error for Error { + fn description(&self) -> &str { + "key values error" + } + } + + impl From for Error { + fn from(err: io::Error) -> Self { + Error::boxed(err) + } + } + + impl From for io::Error { + fn from(err: Error) -> Self { + io::Error::new(io::ErrorKind::Other, err) + } + } +} diff --git a/vendor/log/src/kv/key.rs b/vendor/log/src/kv/key.rs new file mode 100644 index 0000000000..82f1e85e62 --- /dev/null +++ b/vendor/log/src/kv/key.rs @@ -0,0 +1,143 @@ +//! Structured keys. + +use std::fmt; +use std::cmp; +use std::hash; +use std::borrow::Borrow; + +/// A type that can be converted into a [`Key`](struct.Key.html). +pub trait ToKey { + /// Perform the conversion. + fn to_key(&self) -> Key; +} + +impl<'a, T> ToKey for &'a T +where + T: ToKey + ?Sized, +{ + fn to_key(&self) -> Key { + (**self).to_key() + } +} + +impl<'k> ToKey for Key<'k> { + fn to_key(&self) -> Key { + Key { + key: self.key, + } + } +} + +impl ToKey for str { + fn to_key(&self) -> Key { + Key::from_str(self) + } +} + +/// A key in a structured key-value pair. +#[derive(Clone)] +pub struct Key<'k> { + key: &'k str, +} + +impl<'k> Key<'k> { + /// Get a key from a borrowed string. + pub fn from_str(key: &'k str) -> Self { + Key { + key: key, + } + } + + /// Get a borrowed string from this key. + pub fn as_str(&self) -> &str { + self.key + } +} + +impl<'k> fmt::Debug for Key<'k> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.key.fmt(f) + } +} + +impl<'k> fmt::Display for Key<'k> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.key.fmt(f) + } +} + +impl<'k> hash::Hash for Key<'k> { + fn hash(&self, state: &mut H) + where + H: hash::Hasher, + { + self.as_str().hash(state) + } +} + +impl<'k, 'ko> PartialEq> for Key<'k> { + fn eq(&self, other: &Key<'ko>) -> bool { + self.as_str().eq(other.as_str()) + } +} + +impl<'k> Eq for Key<'k> {} + +impl<'k, 'ko> PartialOrd> for Key<'k> { + fn partial_cmp(&self, other: &Key<'ko>) -> Option { + self.as_str().partial_cmp(other.as_str()) + } +} + +impl<'k> Ord for Key<'k> { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.as_str().cmp(other.as_str()) + } +} + +impl<'k> AsRef for Key<'k> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl<'k> Borrow for Key<'k> { + fn borrow(&self) -> &str { + self.as_str() + } +} + +impl<'k> From<&'k str> for Key<'k> { + fn from(s: &'k str) -> Self { + Key::from_str(s) + } +} + +#[cfg(feature = "std")] +mod std_support { + use super::*; + + use std::borrow::Cow; + + impl ToKey for String { + fn to_key(&self) -> Key { + Key::from_str(self) + } + } + + impl<'a> ToKey for Cow<'a, str> { + fn to_key(&self) -> Key { + Key::from_str(self) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn key_from_string() { + assert_eq!("a key", Key::from_str("a key").as_str()); + } +} diff --git a/vendor/log/src/kv/mod.rs b/vendor/log/src/kv/mod.rs new file mode 100644 index 0000000000..17226b4cf6 --- /dev/null +++ b/vendor/log/src/kv/mod.rs @@ -0,0 +1,23 @@ +//! **UNSTABLE:** Structured key-value pairs. +//! +//! This module is unstable and breaking changes may be made +//! at any time. See [the tracking issue](https://github.com/rust-lang-nursery/log/issues/328) +//! for more details. +//! +//! Add the `kv_unstable` feature to your `Cargo.toml` to enable +//! this module: +//! +//! ```toml +//! [dependencies.log] +//! features = ["kv_unstable"] +//! ``` + +mod error; +mod source; +mod key; +pub mod value; + +pub use self::error::Error; +pub use self::source::{Source, Visitor}; +pub use self::key::{Key, ToKey}; +pub use self::value::{Value, ToValue}; diff --git a/vendor/log/src/kv/source.rs b/vendor/log/src/kv/source.rs new file mode 100644 index 0000000000..0538c14f47 --- /dev/null +++ b/vendor/log/src/kv/source.rs @@ -0,0 +1,396 @@ +//! Sources for key-value pairs. + +use std::fmt; +use kv::{Error, Key, ToKey, Value, ToValue}; + +/// A source of key-value pairs. +/// +/// The source may be a single pair, a set of pairs, or a filter over a set of pairs. +/// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data +/// in a source. +pub trait Source { + /// Visit key-value pairs. + /// + /// A source doesn't have to guarantee any ordering or uniqueness of key-value pairs. + /// If the given visitor returns an error then the source may early-return with it, + /// even if there are more key-value pairs. + /// + /// # Implementation notes + /// + /// A source should yield the same key-value pairs to a subsequent visitor unless + /// that visitor itself fails. + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error>; + + /// Get the value for a given key. + /// + /// If the key appears multiple times in the source then which key is returned + /// is implementation specific. + /// + /// # Implementation notes + /// + /// A source that can provide a more efficient implementation of this method + /// should override it. + fn get<'v>(&'v self, key: Key) -> Option> { + struct Get<'k, 'v> { + key: Key<'k>, + found: Option>, + } + + impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + if self.key == key { + self.found = Some(value); + } + + Ok(()) + } + } + + let mut get = Get { + key, + found: None, + }; + + let _ = self.visit(&mut get); + get.found + } + + /// Count the number of key-value pairs that can be visited. + /// + /// # Implementation notes + /// + /// A source that knows the number of key-value pairs upfront may provide a more + /// efficient implementation. + /// + /// A subsequent call to `visit` should yield the same number of key-value pairs + /// to the visitor, unless that visitor fails part way through. + fn count(&self) -> usize { + struct Count(usize); + + impl<'kvs> Visitor<'kvs> for Count { + fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> { + self.0 += 1; + + Ok(()) + } + } + + let mut count = Count(0); + let _ = self.visit(&mut count); + count.0 + } +} + +impl<'a, T> Source for &'a T +where + T: Source + ?Sized, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + Source::visit(&**self, visitor) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + Source::get(&**self, key) + } + + fn count(&self) -> usize { + Source::count(&**self) + } +} + +impl Source for (K, V) +where + K: ToKey, + V: ToValue, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + visitor.visit_pair(self.0.to_key(), self.1.to_value()) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + if self.0.to_key() == key { + Some(self.1.to_value()) + } else { + None + } + } + + fn count(&self) -> usize { + 1 + } +} + +impl Source for [S] +where + S: Source, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + for source in self { + source.visit(visitor)?; + } + + Ok(()) + } + + fn count(&self) -> usize { + self.len() + } +} + +impl Source for Option +where + S: Source, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + if let Some(ref source) = *self { + source.visit(visitor)?; + } + + Ok(()) + } + + fn count(&self) -> usize { + self.as_ref().map(Source::count).unwrap_or(0) + } +} + +/// A visitor for the key-value pairs in a [`Source`](trait.Source.html). +pub trait Visitor<'kvs> { + /// Visit a key-value pair. + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>; +} + +impl<'a, 'kvs, T> Visitor<'kvs> for &'a mut T +where + T: Visitor<'kvs> + ?Sized, +{ + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + (**self).visit_pair(key, value) + } +} + +impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugMap<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.entry(&key, &value); + Ok(()) + } +} + +impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugList<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.entry(&(key, value)); + Ok(()) + } +} + +impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugSet<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.entry(&(key, value)); + Ok(()) + } +} + +impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugTuple<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.field(&key); + self.field(&value); + Ok(()) + } +} + +#[cfg(feature = "std")] +mod std_support { + use super::*; + use std::borrow::Borrow; + use std::collections::{BTreeMap, HashMap}; + use std::hash::{BuildHasher, Hash}; + + impl Source for Box + where + S: Source + ?Sized, + { + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + Source::visit(&**self, visitor) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + Source::get(&**self, key) + } + + fn count(&self) -> usize { + Source::count(&**self) + } + } + + impl Source for Vec + where + S: Source, + { + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + Source::visit(&**self, visitor) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + Source::get(&**self, key) + } + + fn count(&self) -> usize { + Source::count(&**self) + } + } + + impl<'kvs, V> Visitor<'kvs> for Box + where + V: Visitor<'kvs> + ?Sized, + { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + (**self).visit_pair(key, value) + } + } + + impl Source for HashMap + where + K: ToKey + Borrow + Eq + Hash, + V: ToValue, + S: BuildHasher, + { + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + for (key, value) in self { + visitor.visit_pair(key.to_key(), value.to_value())?; + } + Ok(()) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + HashMap::get(self, key.as_str()).map(|v| v.to_value()) + } + + fn count(&self) -> usize { + self.len() + } + } + + impl Source for BTreeMap + where + K: ToKey + Borrow + Ord, + V: ToValue, + { + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + for (key, value) in self { + visitor.visit_pair(key.to_key(), value.to_value())?; + } + Ok(()) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + BTreeMap::get(self, key.as_str()).map(|v| v.to_value()) + } + + fn count(&self) -> usize { + self.len() + } + } + + #[cfg(test)] + mod tests { + use super::*; + use kv::value::test::Token; + use std::collections::{BTreeMap, HashMap}; + + #[test] + fn count() { + assert_eq!(1, Source::count(&Box::new(("a", 1)))); + assert_eq!(2, Source::count(&vec![("a", 1), ("b", 2)])); + } + + #[test] + fn get() { + let source = vec![("a", 1), ("b", 2), ("a", 1)]; + assert_eq!( + Token::I64(1), + Source::get(&source, Key::from_str("a")).unwrap().to_token() + ); + + let source = Box::new(Option::None::<(&str, i32)>); + assert!(Source::get(&source, Key::from_str("a")).is_none()); + } + + #[test] + fn hash_map() { + let mut map = HashMap::new(); + map.insert("a", 1); + map.insert("b", 2); + + assert_eq!(2, Source::count(&map)); + assert_eq!( + Token::I64(1), + Source::get(&map, Key::from_str("a")).unwrap().to_token() + ); + } + + #[test] + fn btree_map() { + let mut map = BTreeMap::new(); + map.insert("a", 1); + map.insert("b", 2); + + assert_eq!(2, Source::count(&map)); + assert_eq!( + Token::I64(1), + Source::get(&map, Key::from_str("a")).unwrap().to_token() + ); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use kv::value::test::Token; + + #[test] + fn source_is_object_safe() { + fn _check(_: &Source) {} + } + + #[test] + fn visitor_is_object_safe() { + fn _check(_: &Visitor) {} + } + + #[test] + fn count() { + struct OnePair { + key: &'static str, + value: i32, + } + + impl Source for OnePair { + fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> { + visitor.visit_pair(self.key.to_key(), self.value.to_value()) + } + } + + assert_eq!(1, Source::count(&("a", 1))); + assert_eq!(2, Source::count(&[("a", 1), ("b", 2)] as &[_])); + assert_eq!(0, Source::count(&Option::None::<(&str, i32)>)); + assert_eq!(1, Source::count(&OnePair { key: "a", value: 1 })); + } + + #[test] + fn get() { + let source = &[("a", 1), ("b", 2), ("a", 1)] as &[_]; + assert_eq!( + Token::I64(1), + Source::get(source, Key::from_str("a")).unwrap().to_token() + ); + assert_eq!( + Token::I64(2), + Source::get(source, Key::from_str("b")).unwrap().to_token() + ); + assert!(Source::get(&source, Key::from_str("c")).is_none()); + + let source = Option::None::<(&str, i32)>; + assert!(Source::get(&source, Key::from_str("a")).is_none()); + } +} diff --git a/vendor/log/src/kv/value/impls.rs b/vendor/log/src/kv/value/impls.rs new file mode 100644 index 0000000000..ea181466b4 --- /dev/null +++ b/vendor/log/src/kv/value/impls.rs @@ -0,0 +1,269 @@ +use std::fmt; + +use super::{ToValue, Value, Primitive}; + +impl ToValue for usize { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: usize) -> Self { + Value::from_primitive(Primitive::Unsigned(value as u64)) + } +} + +impl ToValue for isize { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: isize) -> Self { + Value::from_primitive(Primitive::Signed(value as i64)) + } +} + +impl ToValue for u8 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: u8) -> Self { + Value::from_primitive(Primitive::Unsigned(value as u64)) + } +} + +impl ToValue for u16 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: u16) -> Self { + Value::from_primitive(Primitive::Unsigned(value as u64)) + } +} + +impl ToValue for u32 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: u32) -> Self { + Value::from_primitive(Primitive::Unsigned(value as u64)) + } +} + +impl ToValue for u64 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: u64) -> Self { + Value::from_primitive(Primitive::Unsigned(value)) + } +} + +impl ToValue for i8 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: i8) -> Self { + Value::from_primitive(Primitive::Signed(value as i64)) + } +} + +impl ToValue for i16 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: i16) -> Self { + Value::from_primitive(Primitive::Signed(value as i64)) + } +} + +impl ToValue for i32 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: i32) -> Self { + Value::from_primitive(Primitive::Signed(value as i64)) + } +} + +impl ToValue for i64 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: i64) -> Self { + Value::from_primitive(Primitive::Signed(value)) + } +} + +impl ToValue for f32 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: f32) -> Self { + Value::from_primitive(Primitive::Float(value as f64)) + } +} + +impl ToValue for f64 { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: f64) -> Self { + Value::from_primitive(Primitive::Float(value)) + } +} + +impl ToValue for bool { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: bool) -> Self { + Value::from_primitive(Primitive::Bool(value)) + } +} + +impl ToValue for char { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From for Value<'v> { + fn from(value: char) -> Self { + Value::from_primitive(Primitive::Char(value)) + } +} + +impl<'v> ToValue for &'v str { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From<&'v str> for Value<'v> { + fn from(value: &'v str) -> Self { + Value::from_primitive(Primitive::Str(value)) + } +} + +impl ToValue for () { + fn to_value(&self) -> Value { + Value::from_primitive(Primitive::None) + } +} + +impl ToValue for Option +where + T: ToValue, +{ + fn to_value(&self) -> Value { + match *self { + Some(ref value) => value.to_value(), + None => Value::from_primitive(Primitive::None), + } + } +} + +impl<'v> ToValue for fmt::Arguments<'v> { + fn to_value(&self) -> Value { + Value::from_debug(self) + } +} + +#[cfg(feature = "std")] +mod std_support { + use super::*; + + use std::borrow::Cow; + + impl ToValue for Box + where + T: ToValue + ?Sized, + { + fn to_value(&self) -> Value { + (**self).to_value() + } + } + + impl ToValue for String { + fn to_value(&self) -> Value { + Value::from_primitive(Primitive::Str(&*self)) + } + } + + impl<'v> ToValue for Cow<'v, str> { + fn to_value(&self) -> Value { + Value::from_primitive(Primitive::Str(&*self)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use kv::value::test::Token; + + #[test] + fn test_to_value_display() { + assert_eq!(42u64.to_value().to_string(), "42"); + assert_eq!(42i64.to_value().to_string(), "42"); + assert_eq!(42.01f64.to_value().to_string(), "42.01"); + assert_eq!(true.to_value().to_string(), "true"); + assert_eq!('a'.to_value().to_string(), "'a'"); + assert_eq!(format_args!("a {}", "value").to_value().to_string(), "a value"); + assert_eq!("a loong string".to_value().to_string(), "\"a loong string\""); + assert_eq!(Some(true).to_value().to_string(), "true"); + assert_eq!(().to_value().to_string(), "None"); + assert_eq!(Option::None::.to_value().to_string(), "None"); + } + + #[test] + fn test_to_value_structured() { + assert_eq!(42u64.to_value().to_token(), Token::U64(42)); + assert_eq!(42i64.to_value().to_token(), Token::I64(42)); + assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01)); + assert_eq!(true.to_value().to_token(), Token::Bool(true)); + assert_eq!('a'.to_value().to_token(), Token::Char('a')); + assert_eq!(format_args!("a {}", "value").to_value().to_token(), Token::Str("a value".into())); + assert_eq!("a loong string".to_value().to_token(), Token::Str("a loong string".into())); + assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); + assert_eq!(().to_value().to_token(), Token::None); + assert_eq!(Option::None::.to_value().to_token(), Token::None); + } +} diff --git a/vendor/log/src/kv/value/internal.rs b/vendor/log/src/kv/value/internal.rs new file mode 100644 index 0000000000..5f01a317b1 --- /dev/null +++ b/vendor/log/src/kv/value/internal.rs @@ -0,0 +1,264 @@ +use std::fmt; + +use super::{Fill, Slot, Error}; +use kv; + +// `Visitor` is an internal API for visiting the structure of a value. +// It's not intended to be public (at this stage). + +/// A container for a structured value for a specific kind of visitor. +#[derive(Clone, Copy)] +pub(super) enum Inner<'v> { + /// A simple primitive value that can be copied without allocating. + Primitive(Primitive<'v>), + /// A value that can be filled. + Fill(&'v Fill), + /// A debuggable value. + Debug(&'v fmt::Debug), + /// A displayable value. + Display(&'v fmt::Display), + + #[cfg(feature = "kv_unstable_sval")] + /// A structured value from `sval`. + Sval(&'v sval_support::Value), +} + +impl<'v> Inner<'v> { + pub(super) fn visit(&self, visitor: &mut Visitor) -> Result<(), Error> { + match *self { + Inner::Primitive(value) => match value { + Primitive::Signed(value) => visitor.i64(value), + Primitive::Unsigned(value) => visitor.u64(value), + Primitive::Float(value) => visitor.f64(value), + Primitive::Bool(value) => visitor.bool(value), + Primitive::Char(value) => visitor.char(value), + Primitive::Str(value) => visitor.str(value), + Primitive::None => visitor.none(), + }, + Inner::Fill(value) => value.fill(&mut Slot::new(visitor)), + Inner::Debug(value) => visitor.debug(value), + Inner::Display(value) => visitor.display(value), + + #[cfg(feature = "kv_unstable_sval")] + Inner::Sval(value) => visitor.sval(value), + } + } +} + +/// The internal serialization contract. +pub(super) trait Visitor { + fn debug(&mut self, v: &fmt::Debug) -> Result<(), Error>; + fn display(&mut self, v: &fmt::Display) -> Result<(), Error> { + self.debug(&format_args!("{}", v)) + } + + fn u64(&mut self, v: u64) -> Result<(), Error>; + fn i64(&mut self, v: i64) -> Result<(), Error>; + fn f64(&mut self, v: f64) -> Result<(), Error>; + fn bool(&mut self, v: bool) -> Result<(), Error>; + fn char(&mut self, v: char) -> Result<(), Error>; + fn str(&mut self, v: &str) -> Result<(), Error>; + fn none(&mut self) -> Result<(), Error>; + + #[cfg(feature = "kv_unstable_sval")] + fn sval(&mut self, v: &sval_support::Value) -> Result<(), Error>; +} + +#[derive(Clone, Copy)] +pub(super) enum Primitive<'v> { + Signed(i64), + Unsigned(u64), + Float(f64), + Bool(bool), + Char(char), + Str(&'v str), + None, +} + +mod fmt_support { + use super::*; + + impl<'v> kv::Value<'v> { + /// Get a value from a debuggable type. + pub fn from_debug(value: &'v T) -> Self + where + T: fmt::Debug, + { + kv::Value { + inner: Inner::Debug(value), + } + } + + /// Get a value from a displayable type. + pub fn from_display(value: &'v T) -> Self + where + T: fmt::Display, + { + kv::Value { + inner: Inner::Display(value), + } + } + } + + impl<'v> fmt::Debug for kv::Value<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.visit(&mut FmtVisitor(f))?; + + Ok(()) + } + } + + impl<'v> fmt::Display for kv::Value<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.visit(&mut FmtVisitor(f))?; + + Ok(()) + } + } + + struct FmtVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); + + impl<'a, 'b: 'a> Visitor for FmtVisitor<'a, 'b> { + fn debug(&mut self, v: &fmt::Debug) -> Result<(), Error> { + v.fmt(self.0)?; + + Ok(()) + } + + fn u64(&mut self, v: u64) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn i64(&mut self, v: i64) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn f64(&mut self, v: f64) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn bool(&mut self, v: bool) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn char(&mut self, v: char) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn str(&mut self, v: &str) -> Result<(), Error> { + self.debug(&format_args!("{:?}", v)) + } + + fn none(&mut self) -> Result<(), Error> { + self.debug(&format_args!("None")) + } + + #[cfg(feature = "kv_unstable_sval")] + fn sval(&mut self, v: &sval_support::Value) -> Result<(), Error> { + sval_support::fmt(self.0, v) + } + } +} + +#[cfg(feature = "kv_unstable_sval")] +pub(super) mod sval_support { + use super::*; + + extern crate sval; + + impl<'v> kv::Value<'v> { + /// Get a value from a structured type. + pub fn from_sval(value: &'v T) -> Self + where + T: sval::Value, + { + kv::Value { + inner: Inner::Sval(value), + } + } + } + + impl<'v> sval::Value for kv::Value<'v> { + fn stream(&self, s: &mut sval::value::Stream) -> sval::value::Result { + self.visit(&mut SvalVisitor(s)).map_err(Error::into_sval)?; + + Ok(()) + } + } + + pub(in kv::value) use self::sval::Value; + + pub(super) fn fmt(f: &mut fmt::Formatter, v: &sval::Value) -> Result<(), Error> { + sval::fmt::debug(f, v)?; + Ok(()) + } + + impl Error { + fn from_sval(_: sval::value::Error) -> Self { + Error::msg("`sval` serialization failed") + } + + fn into_sval(self) -> sval::value::Error { + sval::value::Error::msg("`sval` serialization failed") + } + } + + struct SvalVisitor<'a, 'b: 'a>(&'a mut sval::value::Stream<'b>); + + impl<'a, 'b: 'a> Visitor for SvalVisitor<'a, 'b> { + fn debug(&mut self, v: &fmt::Debug) -> Result<(), Error> { + self.0.fmt(format_args!("{:?}", v)).map_err(Error::from_sval) + } + + fn u64(&mut self, v: u64) -> Result<(), Error> { + self.0.u64(v).map_err(Error::from_sval) + } + + fn i64(&mut self, v: i64) -> Result<(), Error> { + self.0.i64(v).map_err(Error::from_sval) + } + + fn f64(&mut self, v: f64) -> Result<(), Error> { + self.0.f64(v).map_err(Error::from_sval) + } + + fn bool(&mut self, v: bool) -> Result<(), Error> { + self.0.bool(v).map_err(Error::from_sval) + } + + fn char(&mut self, v: char) -> Result<(), Error> { + self.0.char(v).map_err(Error::from_sval) + } + + fn str(&mut self, v: &str) -> Result<(), Error> { + self.0.str(v).map_err(Error::from_sval) + } + + fn none(&mut self) -> Result<(), Error> { + self.0.none().map_err(Error::from_sval) + } + + fn sval(&mut self, v: &sval::Value) -> Result<(), Error> { + self.0.any(v).map_err(Error::from_sval) + } + } + + #[cfg(test)] + mod tests { + use super::*; + use kv::value::test::Token; + + #[test] + fn test_from_sval() { + assert_eq!(kv::Value::from_sval(&42u64).to_token(), Token::Sval); + } + + #[test] + fn test_sval_structured() { + let value = kv::Value::from(42u64); + let expected = vec![sval::test::Token::Unsigned(42)]; + + assert_eq!(sval::test::tokens(value), expected); + } + } +} diff --git a/vendor/log/src/kv/value/mod.rs b/vendor/log/src/kv/value/mod.rs new file mode 100644 index 0000000000..1695afbd16 --- /dev/null +++ b/vendor/log/src/kv/value/mod.rs @@ -0,0 +1,155 @@ +//! Structured values. + +use std::fmt; + +mod internal; +mod impls; + +#[cfg(test)] +pub(in kv) mod test; + +pub use kv::Error; + +use self::internal::{Inner, Visitor, Primitive}; + +/// A type that can be converted into a [`Value`](struct.Value.html). +pub trait ToValue { + /// Perform the conversion. + fn to_value(&self) -> Value; +} + +impl<'a, T> ToValue for &'a T +where + T: ToValue + ?Sized, +{ + fn to_value(&self) -> Value { + (**self).to_value() + } +} + +impl<'v> ToValue for Value<'v> { + fn to_value(&self) -> Value { + Value { + inner: self.inner, + } + } +} + +/// A type that requires extra work to convert into a [`Value`](struct.Value.html). +/// +/// This trait is a more advanced initialization API than [`ToValue`](trait.ToValue.html). +/// It's intended for erased values coming from other logging frameworks that may need +/// to perform extra work to determine the concrete type to use. +pub trait Fill { + /// Fill a value. + fn fill(&self, slot: &mut Slot) -> Result<(), Error>; +} + +impl<'a, T> Fill for &'a T +where + T: Fill + ?Sized, +{ + fn fill(&self, slot: &mut Slot) -> Result<(), Error> { + (**self).fill(slot) + } +} + +/// A value slot to fill using the [`Fill`](trait.Fill.html) trait. +pub struct Slot<'a> { + filled: bool, + visitor: &'a mut Visitor, +} + +impl<'a> fmt::Debug for Slot<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Slot").finish() + } +} + +impl<'a> Slot<'a> { + fn new(visitor: &'a mut Visitor) -> Self { + Slot { + visitor, + filled: false, + } + } + + /// Fill the slot with a value. + /// + /// The given value doesn't need to satisfy any particular lifetime constraints. + /// + /// # Panics + /// + /// Calling `fill` more than once will panic. + pub fn fill(&mut self, value: Value) -> Result<(), Error> { + assert!(!self.filled, "the slot has already been filled"); + self.filled = true; + + value.visit(self.visitor) + } +} + +/// A value in a structured key-value pair. +pub struct Value<'v> { + inner: Inner<'v>, +} + +impl<'v> Value<'v> { + /// Get a value from an internal `Visit`. + fn from_primitive(value: Primitive<'v>) -> Self { + Value { + inner: Inner::Primitive(value), + } + } + + /// Get a value from a fillable slot. + pub fn from_fill(value: &'v T) -> Self + where + T: Fill, + { + Value { + inner: Inner::Fill(value), + } + } + + fn visit(&self, visitor: &mut Visitor) -> Result<(), Error> { + self.inner.visit(visitor) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fill_value() { + struct TestFill; + + impl Fill for TestFill { + fn fill(&self, slot: &mut Slot) -> Result<(), Error> { + let dbg: &fmt::Debug = &1; + + slot.fill(Value::from_debug(&dbg)) + } + } + + assert_eq!("1", Value::from_fill(&TestFill).to_string()); + } + + #[test] + #[should_panic] + fn fill_multiple_times_panics() { + struct BadFill; + + impl Fill for BadFill { + fn fill(&self, slot: &mut Slot) -> Result<(), Error> { + slot.fill(42.into())?; + slot.fill(6789.into())?; + + Ok(()) + } + } + + let _ = Value::from_fill(&BadFill).to_string(); + } +} diff --git a/vendor/log/src/kv/value/test.rs b/vendor/log/src/kv/value/test.rs new file mode 100644 index 0000000000..c9c03dc420 --- /dev/null +++ b/vendor/log/src/kv/value/test.rs @@ -0,0 +1,81 @@ +// Test support for inspecting Values + +use std::fmt; +use std::str; + +use super::{Value, Error}; +use super::internal; + +#[derive(Debug, PartialEq)] +pub(in kv) enum Token { + U64(u64), + I64(i64), + F64(f64), + Char(char), + Bool(bool), + Str(String), + None, + + #[cfg(feature = "kv_unstable_sval")] + Sval, +} + +#[cfg(test)] +impl<'v> Value<'v> { + pub(in kv) fn to_token(&self) -> Token { + struct TestVisitor(Option); + + impl internal::Visitor for TestVisitor { + fn debug(&mut self, v: &fmt::Debug) -> Result<(), Error> { + self.0 = Some(Token::Str(format!("{:?}", v))); + Ok(()) + } + + fn u64(&mut self, v: u64) -> Result<(), Error> { + self.0 = Some(Token::U64(v)); + Ok(()) + } + + fn i64(&mut self, v: i64) -> Result<(), Error> { + self.0 = Some(Token::I64(v)); + Ok(()) + } + + fn f64(&mut self, v: f64) -> Result<(), Error> { + self.0 = Some(Token::F64(v)); + Ok(()) + } + + fn bool(&mut self, v: bool) -> Result<(), Error> { + self.0 = Some(Token::Bool(v)); + Ok(()) + } + + fn char(&mut self, v: char) -> Result<(), Error> { + self.0 = Some(Token::Char(v)); + Ok(()) + } + + fn str(&mut self, v: &str) -> Result<(), Error> { + self.0 = Some(Token::Str(v.into())); + Ok(()) + } + + fn none(&mut self) -> Result<(), Error> { + self.0 = Some(Token::None); + Ok(()) + } + + #[cfg(feature = "kv_unstable_sval")] + fn sval(&mut self, _: &internal::sval_support::Value) -> Result<(), Error> { + self.0 = Some(Token::Sval); + Ok(()) + } + } + + let mut visitor = TestVisitor(None); + self.visit(&mut visitor).unwrap(); + + visitor.0.unwrap() + } +} diff --git a/vendor/log/src/lib.rs b/vendor/log/src/lib.rs index af4de3a7f8..c79219dc64 100644 --- a/vendor/log/src/lib.rs +++ b/vendor/log/src/lib.rs @@ -48,14 +48,12 @@ //! //! ### Examples //! -//! ```rust -//! # #![allow(unstable)] -//! #[macro_use] -//! extern crate log; -//! +//! ```edition2018 //! # #[derive(Debug)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } //! # fn find_a_razor() -> Result { Ok(1) } +//! use log::{info, warn}; +//! //! pub fn shave_the_yak(yak: &mut Yak) { //! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak); //! @@ -115,9 +113,7 @@ //! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or //! [`Info`][level_link] levels to stdout: //! -//! ```rust -//! extern crate log; -//! +//! ```edition2018 //! use log::{Record, Level, Metadata}; //! //! struct SimpleLogger; @@ -150,8 +146,7 @@ //! provide a function that wraps a call to [`set_logger`] and //! [`set_max_level`], handling initialization of the logger: //! -//! ```rust -//! # extern crate log; +//! ```edition2018 //! # use log::{Level, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -181,8 +176,7 @@ //! identical to `set_logger` except that it takes a `Box` rather than a //! `&'static Log`: //! -//! ```rust -//! # extern crate log; +//! ```edition2018 //! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -221,6 +215,9 @@ //! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check //! this value before logging a message. By default, no levels are disabled. //! +//! Libraries should avoid using the max level features because they're global and can't be changed +//! once they're set. +//! //! For example, a crate can disable trace level logs in debug builds and trace, debug, and info //! level logs in release builds with the following configuration: //! @@ -270,17 +267,17 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.6" + html_root_url = "https://docs.rs/log/0.4.8" )] #![warn(missing_docs)] #![deny(missing_debug_implementations)] -#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate #![cfg_attr(rustbuild, feature(staged_api, rustc_private))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] -#[cfg(not(feature = "std"))] +#[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; #[macro_use] @@ -292,15 +289,26 @@ use std::error; use std::fmt; use std::mem; use std::str::FromStr; -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +// FIXME: ATOMIC_USIZE_INIT was deprecated in rust 1.34. Silence the +// deprecation warning until our MSRV >= 1.24, where we can use the +// replacement const fn `AtomicUsize::new` +#[allow(deprecated)] +use std::sync::atomic::ATOMIC_USIZE_INIT; #[macro_use] mod macros; mod serde; +#[cfg(feature = "kv_unstable")] +pub mod kv; + // The LOGGER static holds a pointer to the global logger. It is protected by // the STATE static which determines whether LOGGER has been initialized yet. static mut LOGGER: &'static Log = &NopLogger; + +#[allow(deprecated)] static STATE: AtomicUsize = ATOMIC_USIZE_INIT; // There are three different states that we care about: the logger's @@ -310,6 +318,7 @@ const UNINITIALIZED: usize = 0; const INITIALIZING: usize = 1; const INITIALIZED: usize = 2; +#[allow(deprecated)] static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT; static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; @@ -629,7 +638,7 @@ impl FromStr for LevelFilter { impl fmt::Display for LevelFilter { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", LOG_LEVEL_NAMES[*self as usize]) + fmt.pad(LOG_LEVEL_NAMES[*self as usize]) } } @@ -660,6 +669,22 @@ impl LevelFilter { } } +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +enum MaybeStaticStr<'a> { + Static(&'static str), + Borrowed(&'a str), +} + +impl<'a> MaybeStaticStr<'a> { + #[inline] + fn get(&self) -> &'a str { + match *self { + MaybeStaticStr::Static(s) => s, + MaybeStaticStr::Borrowed(s) => s, + } + } +} + /// The "payload" of a log message. /// /// # Use @@ -678,8 +703,7 @@ impl LevelFilter { /// The following example shows a simple logger that displays the level, /// module path, and message of any `Record` that is passed to it. /// -/// ```rust -/// # extern crate log; +/// ```edition2018 /// struct SimpleLogger; /// /// impl log::Log for SimpleLogger { @@ -710,9 +734,28 @@ impl LevelFilter { pub struct Record<'a> { metadata: Metadata<'a>, args: fmt::Arguments<'a>, - module_path: Option<&'a str>, - file: Option<&'a str>, + module_path: Option>, + file: Option>, line: Option, + #[cfg(feature = "kv_unstable")] + key_values: KeyValues<'a>, +} + +// This wrapper type is only needed so we can +// `#[derive(Debug)]` on `Record`. It also +// provides a useful `Debug` implementation for +// the underlying `Source`. +#[cfg(feature = "kv_unstable")] +#[derive(Clone)] +struct KeyValues<'a>(&'a kv::Source); + +#[cfg(feature = "kv_unstable")] +impl<'a> fmt::Debug for KeyValues<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut visitor = f.debug_map(); + self.0.visit(&mut visitor)?; + visitor.finish() + } } impl<'a> Record<'a> { @@ -749,13 +792,31 @@ impl<'a> Record<'a> { /// The module path of the message. #[inline] pub fn module_path(&self) -> Option<&'a str> { - self.module_path + self.module_path.map(|s| s.get()) + } + + /// The module path of the message, if it is a `'static` string. + #[inline] + pub fn module_path_static(&self) -> Option<&'static str> { + match self.module_path { + Some(MaybeStaticStr::Static(s)) => Some(s), + _ => None, + } } /// The source file containing the message. #[inline] pub fn file(&self) -> Option<&'a str> { - self.file + self.file.map(|s| s.get()) + } + + /// The module path of the message, if it is a `'static` string. + #[inline] + pub fn file_static(&self) -> Option<&'static str> { + match self.file { + Some(MaybeStaticStr::Static(s)) => Some(s), + _ => None, + } } /// The line containing the message. @@ -763,6 +824,32 @@ impl<'a> Record<'a> { pub fn line(&self) -> Option { self.line } + + /// The structued key-value pairs associated with the message. + #[cfg(feature = "kv_unstable")] + #[inline] + pub fn key_values(&self) -> &kv::Source { + self.key_values.0 + } + + /// Create a new [`Builder`](struct.Builder.html) based on this record. + #[cfg(feature = "kv_unstable")] + #[inline] + pub fn to_builder(&self) -> RecordBuilder { + RecordBuilder { + record: Record { + metadata: Metadata { + level: self.metadata.level, + target: self.metadata.target, + }, + args: self.args, + module_path: self.module_path, + file: self.file, + line: self.line, + key_values: self.key_values.clone(), + } + } + } } /// Builder for [`Record`](struct.Record.html). @@ -774,7 +861,7 @@ impl<'a> Record<'a> { /// # Examples /// /// -/// ```rust +/// ```edition2018 /// use log::{Level, Record}; /// /// let record = Record::builder() @@ -789,7 +876,7 @@ impl<'a> Record<'a> { /// /// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html): /// -/// ```rust +/// ```edition2018 /// use log::{Record, Level, MetadataBuilder}; /// /// let error_metadata = MetadataBuilder::new() @@ -825,15 +912,28 @@ impl<'a> RecordBuilder<'a> { /// [`Metadata::builder().build()`]: struct.MetadataBuilder.html#method.build #[inline] pub fn new() -> RecordBuilder<'a> { - RecordBuilder { + #[cfg(feature = "kv_unstable")] + return RecordBuilder { record: Record { args: format_args!(""), metadata: Metadata::builder().build(), module_path: None, file: None, line: None, + key_values: KeyValues(&Option::None::<(kv::Key, kv::Value)>), }, - } + }; + + #[cfg(not(feature = "kv_unstable"))] + return RecordBuilder { + record: Record { + args: format_args!(""), + metadata: Metadata::builder().build(), + module_path: None, + file: None, + line: None, + }, + }; } /// Set [`args`](struct.Record.html#method.args). @@ -867,14 +967,28 @@ impl<'a> RecordBuilder<'a> { /// Set [`module_path`](struct.Record.html#method.module_path) #[inline] pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> { - self.record.module_path = path; + self.record.module_path = path.map(MaybeStaticStr::Borrowed); + self + } + + /// Set [`module_path`](struct.Record.html#method.module_path) to a `'static` string + #[inline] + pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> { + self.record.module_path = path.map(MaybeStaticStr::Static); self } /// Set [`file`](struct.Record.html#method.file) #[inline] pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> { - self.record.file = file; + self.record.file = file.map(MaybeStaticStr::Borrowed); + self + } + + /// Set [`file`](struct.Record.html#method.file) to a `'static` string. + #[inline] + pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> { + self.record.file = file.map(MaybeStaticStr::Static); self } @@ -885,6 +999,14 @@ impl<'a> RecordBuilder<'a> { self } + /// Set [`key_values`](struct.Record.html#method.key_values) + #[cfg(feature = "kv_unstable")] + #[inline] + pub fn key_values(&mut self, kvs: &'a kv::Source) -> &mut RecordBuilder<'a> { + self.record.key_values = KeyValues(kvs); + self + } + /// Invoke the builder and return a `Record` #[inline] pub fn build(&self) -> Record<'a> { @@ -910,10 +1032,7 @@ impl<'a> RecordBuilder<'a> { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; -/// # +/// ```edition2018 /// use log::{Record, Level, Metadata}; /// /// struct MyLogger; @@ -967,7 +1086,7 @@ impl<'a> Metadata<'a> { /// /// # Example /// -/// ```rust +/// ```edition2018 /// let target = "myApp"; /// use log::{Level, MetadataBuilder}; /// let metadata = MetadataBuilder::new() @@ -1090,7 +1209,7 @@ pub fn max_level() -> LevelFilter { /// An error is returned if a logger has already been set. /// /// [`set_logger`]: fn.set_logger.html -#[cfg(feature = "std")] +#[cfg(all(feature = "std", atomic_cas))] pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { set_logger_inner(|| unsafe { &*Box::into_raw(logger) }) } @@ -1104,17 +1223,21 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// implementations should provide an initialization method that installs the /// logger internally. /// +/// # Availability +/// +/// This method is available even when the `std` feature is disabled. However, +/// it is currently unavailable on `thumbv6` targets, which lack support for +/// some atomic operations which are used by this function. Even on those +/// targets, [`set_logger_racy`] will be available. +/// /// # Errors /// /// An error is returned if a logger has already been set. /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; -/// # -/// use log::{Record, Level, Metadata, LevelFilter}; +/// ```edition2018 +/// use log::{error, info, warn, Record, Level, Metadata, LevelFilter}; /// /// static MY_LOGGER: MyLogger = MyLogger; /// @@ -1142,10 +1265,14 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// error!("oops"); /// # } /// ``` +/// +/// [`set_logger_racy`]: fn.set_logger_racy.html +#[cfg(atomic_cas)] pub fn set_logger(logger: &'static Log) -> Result<(), SetLoggerError> { set_logger_inner(|| logger) } +#[cfg(atomic_cas)] fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static Log, @@ -1166,6 +1293,40 @@ where } } +/// A thread-unsafe version of [`set_logger`]. +/// +/// This function is available on all platforms, even those that do not have +/// support for atomics that is needed by [`set_logger`]. +/// +/// In almost all cases, [`set_logger`] should be preferred. +/// +/// # Safety +/// +/// This function is only safe to call when no other logger initialization +/// function is called while this function still executes. +/// +/// This can be upheld by (for example) making sure that **there are no other +/// threads**, and (on embedded) that **interrupts are disabled**. +/// +/// It is safe to use other logging functions while this function runs +/// (including all logging macros). +/// +/// [`set_logger`]: fn.set_logger.html +pub unsafe fn set_logger_racy(logger: &'static Log) -> Result<(), SetLoggerError> { + match STATE.load(Ordering::SeqCst) { + UNINITIALIZED => { + LOGGER = logger; + STATE.store(INITIALIZED, Ordering::SeqCst); + Ok(()) + } + INITIALIZING => { + // This is just plain UB, since we were racing another initialization function + unreachable!("set_logger_racy must not be used with other initialization functions") + } + _ => Err(SetLoggerError(())), + } +} + /// The type returned by [`set_logger`] if [`set_logger`] has already been called. /// /// [`set_logger`]: fn.set_logger.html @@ -1227,15 +1388,15 @@ pub fn logger() -> &'static Log { pub fn __private_api_log( args: fmt::Arguments, level: Level, - &(target, module_path, file, line): &(&str, &str, &str, u32), + &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), ) { logger().log( &Record::builder() .args(args) .level(level) .target(target) - .module_path(Some(module_path)) - .file(Some(file)) + .module_path_static(Some(module_path)) + .file_static(Some(file)) .line(Some(line)) .build(), ); @@ -1466,4 +1627,42 @@ mod tests { assert_eq!(record_test.file(), Some("bar")); assert_eq!(record_test.line(), Some(30)); } + + #[test] + #[cfg(feature = "kv_unstable")] + fn test_record_key_values_builder() { + use super::Record; + use kv::{self, Visitor}; + + struct TestVisitor { + seen_pairs: usize, + } + + impl<'kvs> Visitor<'kvs> for TestVisitor { + fn visit_pair( + &mut self, + _: kv::Key<'kvs>, + _: kv::Value<'kvs> + ) -> Result<(), kv::Error> { + self.seen_pairs += 1; + Ok(()) + } + } + + let kvs: &[(&str, i32)] = &[ + ("a", 1), + ("b", 2) + ]; + let record_test = Record::builder() + .key_values(&kvs) + .build(); + + let mut visitor = TestVisitor { + seen_pairs: 0, + }; + + record_test.key_values().visit(&mut visitor).unwrap(); + + assert_eq!(2, visitor.seen_pairs); + } } diff --git a/vendor/log/src/macros.rs b/vendor/log/src/macros.rs index 06ce65a576..bb40b71072 100644 --- a/vendor/log/src/macros.rs +++ b/vendor/log/src/macros.rs @@ -15,10 +15,8 @@ /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; -/// use log::Level; +/// ```edition2018 +/// use log::{log, Level}; /// /// # fn main() { /// let data = (42, "Forty-two"); @@ -48,9 +46,9 @@ macro_rules! log { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 +/// use log::error; +/// /// # fn main() { /// let (err_info, port) = ("No connection", 22); /// @@ -60,11 +58,11 @@ macro_rules! log { /// ``` #[macro_export(local_inner_macros)] macro_rules! error { - (target: $target:expr, $($arg:tt)*) => ( - log!(target: $target, $crate::Level::Error, $($arg)*); + (target: $target:expr, $($arg:tt)+) => ( + log!(target: $target, $crate::Level::Error, $($arg)+); ); - ($($arg:tt)*) => ( - log!($crate::Level::Error, $($arg)*); + ($($arg:tt)+) => ( + log!($crate::Level::Error, $($arg)+); ) } @@ -72,9 +70,9 @@ macro_rules! error { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 +/// use log::warn; +/// /// # fn main() { /// let warn_description = "Invalid Input"; /// @@ -84,11 +82,11 @@ macro_rules! error { /// ``` #[macro_export(local_inner_macros)] macro_rules! warn { - (target: $target:expr, $($arg:tt)*) => ( - log!(target: $target, $crate::Level::Warn, $($arg)*); + (target: $target:expr, $($arg:tt)+) => ( + log!(target: $target, $crate::Level::Warn, $($arg)+); ); - ($($arg:tt)*) => ( - log!($crate::Level::Warn, $($arg)*); + ($($arg:tt)+) => ( + log!($crate::Level::Warn, $($arg)+); ) } @@ -96,9 +94,9 @@ macro_rules! warn { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 +/// use log::info; +/// /// # fn main() { /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; @@ -110,11 +108,11 @@ macro_rules! warn { /// ``` #[macro_export(local_inner_macros)] macro_rules! info { - (target: $target:expr, $($arg:tt)*) => ( - log!(target: $target, $crate::Level::Info, $($arg)*); + (target: $target:expr, $($arg:tt)+) => ( + log!(target: $target, $crate::Level::Info, $($arg)+); ); - ($($arg:tt)*) => ( - log!($crate::Level::Info, $($arg)*); + ($($arg:tt)+) => ( + log!($crate::Level::Info, $($arg)+); ) } @@ -122,9 +120,9 @@ macro_rules! info { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 +/// use log::debug; +/// /// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; @@ -135,11 +133,11 @@ macro_rules! info { /// ``` #[macro_export(local_inner_macros)] macro_rules! debug { - (target: $target:expr, $($arg:tt)*) => ( - log!(target: $target, $crate::Level::Debug, $($arg)*); + (target: $target:expr, $($arg:tt)+) => ( + log!(target: $target, $crate::Level::Debug, $($arg)+); ); - ($($arg:tt)*) => ( - log!($crate::Level::Debug, $($arg)*); + ($($arg:tt)+) => ( + log!($crate::Level::Debug, $($arg)+); ) } @@ -147,9 +145,9 @@ macro_rules! debug { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 +/// use log::trace; +/// /// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; @@ -162,11 +160,11 @@ macro_rules! debug { /// ``` #[macro_export(local_inner_macros)] macro_rules! trace { - (target: $target:expr, $($arg:tt)*) => ( - log!(target: $target, $crate::Level::Trace, $($arg)*); + (target: $target:expr, $($arg:tt)+) => ( + log!(target: $target, $crate::Level::Trace, $($arg)+); ); - ($($arg:tt)*) => ( - log!($crate::Level::Trace, $($arg)*); + ($($arg:tt)+) => ( + log!($crate::Level::Trace, $($arg)+); ) } @@ -178,10 +176,9 @@ macro_rules! trace { /// /// # Examples /// -/// ```rust -/// # #[macro_use] -/// # extern crate log; +/// ```edition2018 /// use log::Level::Debug; +/// use log::{debug, log_enabled}; /// /// # fn foo() { /// if log_enabled!(Debug) { diff --git a/vendor/log/src/serde.rs b/vendor/log/src/serde.rs index 176f9f4112..efc9f14a40 100644 --- a/vendor/log/src/serde.rs +++ b/vendor/log/src/serde.rs @@ -1,9 +1,11 @@ #![cfg(feature = "serde")] extern crate serde; +use self::serde::de::{ + Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess, + Visitor, +}; use self::serde::ser::{Serialize, Serializer}; -use self::serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, EnumAccess, - Unexpected, VariantAccess, Error}; use {Level, LevelFilter, LOG_LEVEL_NAMES}; diff --git a/vendor/log/tests/filters.rs b/vendor/log/tests/filters.rs index 84449ccfe8..e4d21a87fa 100644 --- a/vendor/log/tests/filters.rs +++ b/vendor/log/tests/filters.rs @@ -1,8 +1,8 @@ #[macro_use] extern crate log; +use log::{Level, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; -use log::{Level, LevelFilter, Log, Record, Metadata}; #[cfg(feature = "std")] use log::set_boxed_logger; @@ -30,7 +30,9 @@ impl Log for Logger { } fn main() { - let me = Arc::new(State { last_log: Mutex::new(None) }); + let me = Arc::new(State { + last_log: Mutex::new(None), + }); let a = me.clone(); set_boxed_logger(Box::new(Logger(me))).unwrap(); @@ -56,7 +58,11 @@ fn test(a: &State, filter: LevelFilter) { last(&a, t(Level::Trace, filter)); fn t(lvl: Level, filter: LevelFilter) -> Option { - if lvl <= filter { Some(lvl) } else { None } + if lvl <= filter { + Some(lvl) + } else { + None + } } } diff --git a/vendor/once_cell/.cargo-checksum.json b/vendor/once_cell/.cargo-checksum.json new file mode 100644 index 0000000000..4fb43e4967 --- /dev/null +++ b/vendor/once_cell/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"aa9c40e39ea2e8ddc863922779bc7774f597d7bc3500646e2c78c39d97c5a942","Cargo.lock":"c717b65413fd5c5a1405076417835557456b34202cbab9804aec9430de9ff43e","Cargo.toml":"cfc77947f29edcab661993974dbd90bbcca801e4041e590a6015f40ae807f0a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"be4ea928065420dba72c551d8c565844e28760b33168f8baa00b50505d0713db","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"90541b093ed1d1cbb73f4097ff02cf80657e28264d281d6a31d96a708fdfea90","examples/reentrant_init_deadlocks.rs":"735005c65e2926a4cd210ad385f50927a8b73e009838fee682e0a5700ca84dd2","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","src/imp_pl.rs":"686ab515374e152622e9c47206e26f96bf063f22de9ea6fb4b4306d20427cc7a","src/imp_std.rs":"4c0ceb6b4af03f9328ffe1f014d42d8a2179745b22d4d943e151ef4fccbf84ab","src/lib.rs":"2fd7509427cc1f6306c3f0b90925034bc85188b0924d8dd2803ca67525c31fde","tests/test.rs":"f5a57efd00dcba2a337e48da1b485f228ca61cd72b4e2f2405407c7eab0bcd1d"},"package":"d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"} \ No newline at end of file diff --git a/vendor/once_cell/CHANGELOG.md b/vendor/once_cell/CHANGELOG.md new file mode 100644 index 0000000000..f2ba01e12f --- /dev/null +++ b/vendor/once_cell/CHANGELOG.md @@ -0,0 +1,87 @@ +# Changelog + +## 1.1.0 + +- implement `Default` for `Lazy`: it creates an empty `Lazy` which is initialized with `T::default` on first access. +- add `OnceCell::get_mut`. + +## 1.0.2 + +- actually add `#![no_std]` attribute if std feature is not enabled. + +## 1.0.1 + +- fix unsoundness in `Lazy` if the initializing function panics. Thanks [@xfix](https://github.com/xfix)! +- implement `RefUnwindSafe` for `Lazy`. +- share more code between `std` and `parking_lot` implementations. +- add F.A.Q section to the docs. + +## 1.0.0 + +- remove `parking_lot` from the list of default features. +- add `std` default feature. Without `std`, only `unsync` module is supported. +- implement `Eq` for `OnceCell`. +- fix wrong `Sync` bound on `sync::Lazy`. +- run the whole test suite with miri. + +## 0.2.7 + +- New implementation of `sync::OnceCell` if `parking_lot` feature is disabled. + It now employs a hand-rolled variant of `std::sync::Once`. +- `sync::OnceCell::get_or_try_init` works without `parking_lot` as well! +- document the effects of `parking_lot` feature: same performance but smaller types. + +## 0.2.6 + +- Updated `Lazy`'s `Deref` impl to requires only `FnOnce` instead of `Fn` + +## 0.2.5 + +- `Lazy` requires only `FnOnce` instead of `Fn` + +## 0.2.4 + +- nicer `fmt::Debug` implementation + +## 0.2.3 + +- update `parking_lot` to `0.9.0` +- fix stacked borrows violation in `unsync::OnceCell::get` +- implement `Clone` for `sync::OnceCell where T: Clone` + +## 0.2.2 + +- add `OnceCell::into_inner` which consumes a cell and returns an option + +## 0.2.1 + +- implement `sync::OnceCell::get_or_try_init` if `parking_lot` feature is enabled +- switch internal `unsafe` implementation of `sync::OnceCell` from `Once` to `Mutex` +- `sync::OnceCell::get_or_init` is twice as fast if cell is already initialized +- implement `std::panic::RefUnwindSafe` and `std::panic::UnwindSafe` for `OnceCell` +- better document behavior around panics + +## 0.2.0 + +- MSRV is now 1.31.1 +- `Lazy::new` and `OnceCell::new` are now const-fns +- `unsync_lazy` and `sync_lazy` macros are removed + +## 0.1.8 + +- update crossbeam-utils to 0.6 +- enable bors-ng + +## 0.1.7 + +- cells implement `PartialEq` and `From` +- MSRV is down to 1.24.1 +- update `parking_lot` to `0.7.1` + +## 0.1.6 + +- `unsync::OnceCell` is `Clone` if `T` is `Clone`. + +## 0.1.5 + +- No changelog until this point :( diff --git a/vendor/once_cell/Cargo.lock b/vendor/once_cell/Cargo.lock new file mode 100644 index 0000000000..e313cb9175 --- /dev/null +++ b/vendor/once_cell/Cargo.lock @@ -0,0 +1,197 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "once_cell" +version = "1.1.0" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" +"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/once_cell/Cargo.toml b/vendor/once_cell/Cargo.toml new file mode 100644 index 0000000000..86668e4836 --- /dev/null +++ b/vendor/once_cell/Cargo.toml @@ -0,0 +1,61 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "once_cell" +version = "1.1.0" +authors = ["Aleksey Kladov "] +exclude = ["*.png", "*.svg", "/Cargo.lock.min", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"] +description = "Single assignment cells and lazy values." +documentation = "https://docs.rs/once_cell" +readme = "README.md" +keywords = ["lazy", "static"] +categories = ["rust-patterns", "memory-management"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/matklad/once_cell" + +[[example]] +name = "reentrant_init_deadlocks" +required-features = ["std"] + +[[example]] +name = "bench" +required-features = ["std"] + +[[example]] +name = "bench_vs_lazy_static" +required-features = ["std"] + +[[example]] +name = "lazy_static" +required-features = ["std"] + +[[example]] +name = "regex" +required-features = ["std"] +[dependencies.parking_lot] +version = "0.9.0" +optional = true +default_features = false +[dev-dependencies.crossbeam-utils] +version = "0.6.0" + +[dev-dependencies.lazy_static] +version = "1.0.0" + +[dev-dependencies.regex] +version = "1.2.0" + +[features] +default = ["std"] +std = [] diff --git a/vendor/hashbrown-0.4.0/LICENSE-APACHE b/vendor/once_cell/LICENSE-APACHE similarity index 100% rename from vendor/hashbrown-0.4.0/LICENSE-APACHE rename to vendor/once_cell/LICENSE-APACHE diff --git a/vendor/syn/LICENSE-MIT b/vendor/once_cell/LICENSE-MIT similarity index 100% rename from vendor/syn/LICENSE-MIT rename to vendor/once_cell/LICENSE-MIT diff --git a/vendor/once_cell/README.md b/vendor/once_cell/README.md new file mode 100644 index 0000000000..f00b42d18b --- /dev/null +++ b/vendor/once_cell/README.md @@ -0,0 +1,53 @@ +

once_cell

+ + +[![Build Status](https://travis-ci.org/matklad/once_cell.svg?branch=master)](https://travis-ci.org/matklad/once_cell) +[![Crates.io](https://img.shields.io/crates/v/once_cell.svg)](https://crates.io/crates/once_cell) +[![API reference](https://docs.rs/once_cell/badge.svg)](https://docs.rs/once_cell/) + +# Overview + +`once_cell` provides two new cell-like types, `unsync::OnceCell` and `sync::OnceCell`. `OnceCell` +might store arbitrary non-`Copy` types, can be assigned to at most once and provide direct access +to the stored contents. In a nutshell, API looks *roughly* like this: + +```rust +impl OnceCell { + fn new() -> OnceCell { ... } + fn set(&self, value: T) -> Result<(), T> { ... } + fn get(&self) -> Option<&T> { ... } +} +``` + +Note that, like with `RefCell` and `Mutex`, the `set` method requires only a shared reference. +Because of the single assignment restriction `get` can return an `&T` instead of `Ref` +or `MutexGuard`. + +`once_cell` also has a `Lazy` type, build on top of `OnceCell` which provides the same API as +the `lazy_static!` macro, but without using any macros: + +```rust +use std::{sync::Mutex, collections::HashMap}; +use once_cell::sync::Lazy; + +static GLOBAL_DATA: Lazy>> = Lazy::new(|| { + let mut m = HashMap::new(); + m.insert(13, "Spica".to_string()); + m.insert(74, "Hoyten".to_string()); + Mutex::new(m) +}); + +fn main() { + println!("{:?}", GLOBAL_DATA.lock().unwrap()); +} +``` + +More patterns and use-cases are in the [docs](https://docs.rs/once_cell/)! + +# Related crates + +* [double-checked-cell](https://github.com/niklasf/double-checked-cell) +* [lazy-init](https://crates.io/crates/lazy-init) +* [lazycell](https://crates.io/crates/lazycell) +* [mitochondria](https://crates.io/crates/mitochondria) +* [lazy_static](https://crates.io/crates/lazy_static) diff --git a/vendor/once_cell/examples/bench.rs b/vendor/once_cell/examples/bench.rs new file mode 100644 index 0000000000..e6801258a1 --- /dev/null +++ b/vendor/once_cell/examples/bench.rs @@ -0,0 +1,28 @@ +use std::mem::size_of; + +use once_cell::sync::OnceCell; + +const N_THREADS: usize = 32; +const N_ROUNDS: usize = 100_000_000; + +static CELL: OnceCell = OnceCell::new(); + +fn main() { + let start = std::time::Instant::now(); + let threads = + (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); + for thread in threads { + thread.join().unwrap(); + } + println!("{:?}", start.elapsed()); + println!("size_of::>() = {:?}", size_of::>()); + println!("size_of::>() = {:?}", size_of::>()); + println!("size_of::>() = {:?}", size_of::>()); +} + +fn thread_main(i: usize) { + for _ in 0..N_ROUNDS { + let &value = CELL.get_or_init(|| i); + assert!(value < N_THREADS) + } +} diff --git a/vendor/once_cell/examples/bench_vs_lazy_static.rs b/vendor/once_cell/examples/bench_vs_lazy_static.rs new file mode 100644 index 0000000000..c23b0124e4 --- /dev/null +++ b/vendor/once_cell/examples/bench_vs_lazy_static.rs @@ -0,0 +1,51 @@ +use lazy_static::lazy_static; +use once_cell::sync::Lazy; + +const N_THREADS: usize = 32; +const N_ROUNDS: usize = 100_000_000; + +static ONCE_CELL: Lazy> = Lazy::new(|| vec!["Spica".to_string(), "Hoyten".to_string()]); + +lazy_static! { + static ref LAZY_STATIC: Vec = vec!["Spica".to_string(), "Hoyten".to_string()]; +} + +fn main() { + let once_cell = { + let start = std::time::Instant::now(); + let threads = (0..N_THREADS) + .map(|_| std::thread::spawn(move || thread_once_cell())) + .collect::>(); + for thread in threads { + thread.join().unwrap(); + } + start.elapsed() + }; + let lazy_static = { + let start = std::time::Instant::now(); + let threads = (0..N_THREADS) + .map(|_| std::thread::spawn(move || thread_lazy_static())) + .collect::>(); + for thread in threads { + thread.join().unwrap(); + } + start.elapsed() + }; + + println!("once_cell: {:?}", once_cell); + println!("lazy_static: {:?}", lazy_static); +} + +fn thread_once_cell() { + for _ in 0..N_ROUNDS { + let len = ONCE_CELL.len(); + assert_eq!(len, 2) + } +} + +fn thread_lazy_static() { + for _ in 0..N_ROUNDS { + let len = LAZY_STATIC.len(); + assert_eq!(len, 2) + } +} diff --git a/vendor/once_cell/examples/lazy_static.rs b/vendor/once_cell/examples/lazy_static.rs new file mode 100644 index 0000000000..f0505609b0 --- /dev/null +++ b/vendor/once_cell/examples/lazy_static.rs @@ -0,0 +1,36 @@ +extern crate once_cell; + +use once_cell::sync::{Lazy, OnceCell}; +use std::collections::HashMap; + +static HASHMAP: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + m.insert(0, "foo"); + m.insert(1, "bar"); + m.insert(2, "baz"); + m +}); + +// Same, but completely without macros +fn hashmap() -> &'static HashMap { + static INSTANCE: OnceCell> = OnceCell::new(); + INSTANCE.get_or_init(|| { + let mut m = HashMap::new(); + m.insert(0, "foo"); + m.insert(1, "bar"); + m.insert(2, "baz"); + m + }) +} + +fn main() { + // First access to `HASHMAP` initializes it + println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap()); + + // Any further access to `HASHMAP` just returns the computed value + println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap()); + + // The same works for function-style: + assert_eq!(hashmap().get(&0), Some(&"foo")); + assert_eq!(hashmap().get(&0), Some(&"bar")); +} diff --git a/vendor/once_cell/examples/reentrant_init_deadlocks.rs b/vendor/once_cell/examples/reentrant_init_deadlocks.rs new file mode 100644 index 0000000000..bad2bc3f41 --- /dev/null +++ b/vendor/once_cell/examples/reentrant_init_deadlocks.rs @@ -0,0 +1,7 @@ +fn main() { + let cell = once_cell::sync::OnceCell::::new(); + cell.get_or_init(|| { + cell.get_or_init(|| 1); + 2 + }); +} diff --git a/vendor/once_cell/examples/regex.rs b/vendor/once_cell/examples/regex.rs new file mode 100644 index 0000000000..4c4c2ea6b8 --- /dev/null +++ b/vendor/once_cell/examples/regex.rs @@ -0,0 +1,49 @@ +use std::{str::FromStr, time::Instant}; + +use regex::Regex; + +macro_rules! regex { + ($re:literal $(,)?) => {{ + static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + RE.get_or_init(|| regex::Regex::new($re).unwrap()) + }}; +} + +fn slow() { + let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; + + let mut total = 0; + for _ in 0..1000 { + let re = Regex::new( + r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, + ) + .unwrap(); + let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); + total += size; + } + println!("{}", total); +} + +fn fast() { + let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; + + let mut total = 0; + for _ in 0..1000 { + let re: &Regex = regex!( + r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, + ); + let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); + total += size; + } + println!("{}", total); +} + +fn main() { + let t = Instant::now(); + slow(); + println!("slow: {:?}", t.elapsed()); + + let t = Instant::now(); + fast(); + println!("fast: {:?}", t.elapsed()); +} diff --git a/vendor/once_cell/src/imp_pl.rs b/vendor/once_cell/src/imp_pl.rs new file mode 100644 index 0000000000..b5e95e5b14 --- /dev/null +++ b/vendor/once_cell/src/imp_pl.rs @@ -0,0 +1,100 @@ +use std::{ + cell::UnsafeCell, + panic::{RefUnwindSafe, UnwindSafe}, + sync::atomic::{AtomicBool, Ordering}, +}; + +use parking_lot::{lock_api::RawMutex as _RawMutex, RawMutex}; + +pub(crate) struct OnceCell { + mutex: Mutex, + is_initialized: AtomicBool, + pub(crate) value: UnsafeCell>, +} + +// Why do we need `T: Send`? +// Thread A creates a `OnceCell` and shares it with +// scoped thread B, which fills the cell, which is +// then destroyed by A. That is, destructor observes +// a sent value. +unsafe impl Sync for OnceCell {} +unsafe impl Send for OnceCell {} + +impl RefUnwindSafe for OnceCell {} +impl UnwindSafe for OnceCell {} + +impl OnceCell { + pub(crate) const fn new() -> OnceCell { + OnceCell { + mutex: Mutex::new(), + is_initialized: AtomicBool::new(false), + value: UnsafeCell::new(None), + } + } + + /// Safety: synchronizes with store to value via Release/Acquire. + #[inline] + pub(crate) fn is_initialized(&self) -> bool { + self.is_initialized.load(Ordering::Acquire) + } + + /// Safety: synchronizes with store to value via `is_initialized` or mutex + /// lock/unlock, writes value only once because of the mutex. + #[cold] + pub(crate) fn initialize(&self, f: F) -> Result<(), E> + where + F: FnOnce() -> Result, + { + let _guard = self.mutex.lock(); + if !self.is_initialized() { + // We are calling user-supplied function and need to be careful. + // - if it returns Err, we unlock mutex and return without touching anything + // - if it panics, we unlock mutex and propagate panic without touching anything + // - if it calls `set` or `get_or_try_init` re-entrantly, we get a deadlock on + // mutex, which is important for safety. We *could* detect this and panic, + // but that is more complicated + // - finally, if it returns Ok, we store the value and store the flag with + // `Release`, which synchronizes with `Acquire`s. + let value = f()?; + let slot: &mut Option = unsafe { &mut *self.value.get() }; + debug_assert!(slot.is_none()); + *slot = Some(value); + self.is_initialized.store(true, Ordering::Release); + } + Ok(()) + } +} + +/// Wrapper around parking_lot's `RawMutex` which has `const fn` new. +struct Mutex { + inner: RawMutex, +} + +impl Mutex { + const fn new() -> Mutex { + Mutex { inner: RawMutex::INIT } + } + + fn lock(&self) -> MutexGuard<'_> { + self.inner.lock(); + MutexGuard { inner: &self.inner } + } +} + +struct MutexGuard<'a> { + inner: &'a RawMutex, +} + +impl Drop for MutexGuard<'_> { + fn drop(&mut self) { + self.inner.unlock(); + } +} + +#[test] +#[cfg(pointer_width = "64")] +fn test_size() { + use std::mem::size_of; + + assert_eq!(size_of::>, 2 * size_of::); +} diff --git a/vendor/once_cell/src/imp_std.rs b/vendor/once_cell/src/imp_std.rs new file mode 100644 index 0000000000..bf53b92441 --- /dev/null +++ b/vendor/once_cell/src/imp_std.rs @@ -0,0 +1,333 @@ +// There's a lot of scary concurrent code in this module, but it is copied from +// `std::sync::Once` with two changes: +// * no poisoning +// * init function can fail + +use std::{ + cell::UnsafeCell, + marker::PhantomData, + panic::{RefUnwindSafe, UnwindSafe}, + ptr, + sync::atomic::{AtomicBool, AtomicUsize, Ordering}, + thread::{self, Thread}, +}; + +#[derive(Debug)] +pub(crate) struct OnceCell { + // This `state` word is actually an encoded version of just a pointer to a + // `Waiter`, so we add the `PhantomData` appropriately. + state: AtomicUsize, + _marker: PhantomData<*mut Waiter>, + // FIXME: switch to `std::mem::MaybeUninit` once we are ready to bump MSRV + // that far. It was stabilized in 1.36.0, so, if you are reading this and + // it's higher than 1.46.0 outside, please send a PR! ;) (and to the same + // for `Lazy`, while we are at it). + pub(crate) value: UnsafeCell>, +} + +// Why do we need `T: Send`? +// Thread A creates a `OnceCell` and shares it with +// scoped thread B, which fills the cell, which is +// then destroyed by A. That is, destructor observes +// a sent value. +unsafe impl Sync for OnceCell {} +unsafe impl Send for OnceCell {} + +impl RefUnwindSafe for OnceCell {} +impl UnwindSafe for OnceCell {} + +// Three states that a OnceCell can be in, encoded into the lower bits of `state` in +// the OnceCell structure. +const INCOMPLETE: usize = 0x0; +const RUNNING: usize = 0x1; +const COMPLETE: usize = 0x2; + +// Mask to learn about the state. All other bits are the queue of waiters if +// this is in the RUNNING state. +const STATE_MASK: usize = 0x3; + +// Representation of a node in the linked list of waiters in the RUNNING state. +struct Waiter { + thread: Option, + signaled: AtomicBool, + next: *mut Waiter, +} + +// Helper struct used to clean up after a closure call with a `Drop` +// implementation to also run on panic. +struct Finish<'a> { + failed: bool, + my_state: &'a AtomicUsize, +} + +impl OnceCell { + pub(crate) const fn new() -> OnceCell { + OnceCell { + state: AtomicUsize::new(INCOMPLETE), + _marker: PhantomData, + value: UnsafeCell::new(None), + } + } + + /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst). + #[inline] + pub(crate) fn is_initialized(&self) -> bool { + // An `Acquire` load is enough because that makes all the initialization + // operations visible to us, and, this being a fast path, weaker + // ordering helps with performance. This `Acquire` synchronizes with + // `SeqCst` operations on the slow path. + self.state.load(Ordering::Acquire) == COMPLETE + } + + /// Safety: synchronizes with store to value via SeqCst read from state, + /// writes value only once because we never get to INCOMPLETE state after a + /// successful write. + #[cold] + pub(crate) fn initialize(&self, f: F) -> Result<(), E> + where + F: FnOnce() -> Result, + { + let mut f = Some(f); + let mut res: Result<(), E> = Ok(()); + let slot = &self.value; + initialize_inner(&self.state, &mut || { + let f = f.take().unwrap(); + match f() { + Ok(value) => { + unsafe { *slot.get() = Some(value) }; + true + } + Err(e) => { + res = Err(e); + false + } + } + }); + res + } +} + +// Note: this is intentionally monomorphic +fn initialize_inner(my_state: &AtomicUsize, init: &mut dyn FnMut() -> bool) -> bool { + // This cold path uses SeqCst consistently because the + // performance difference really does not matter there, and + // SeqCst minimizes the chances of something going wrong. + let mut state = my_state.load(Ordering::SeqCst); + + 'outer: loop { + match state { + // If we're complete, then there's nothing to do, we just + // jettison out as we shouldn't run the closure. + COMPLETE => return true, + + // Otherwise if we see an incomplete state we will attempt to + // move ourselves into the RUNNING state. If we succeed, then + // the queue of waiters starts at null (all 0 bits). + INCOMPLETE => { + let old = my_state.compare_and_swap(state, RUNNING, Ordering::SeqCst); + if old != state { + state = old; + continue; + } + + // Run the initialization routine, letting it know if we're + // poisoned or not. The `Finish` struct is then dropped, and + // the `Drop` implementation here is responsible for waking + // up other waiters both in the normal return and panicking + // case. + let mut complete = Finish { failed: true, my_state }; + let success = init(); + // Difference from std: abort if `init` errored. + complete.failed = !success; + return success; + } + + // All other values we find should correspond to the RUNNING + // state with an encoded waiter list in the more significant + // bits. We attempt to enqueue ourselves by moving us to the + // head of the list and bail out if we ever see a state that's + // not RUNNING. + _ => { + assert!(state & STATE_MASK == RUNNING); + let mut node = Waiter { + thread: Some(thread::current()), + signaled: AtomicBool::new(false), + next: ptr::null_mut(), + }; + let me = &mut node as *mut Waiter as usize; + assert!(me & STATE_MASK == 0); + + while state & STATE_MASK == RUNNING { + node.next = (state & !STATE_MASK) as *mut Waiter; + let old = my_state.compare_and_swap(state, me | RUNNING, Ordering::SeqCst); + if old != state { + state = old; + continue; + } + + // Once we've enqueued ourselves, wait in a loop. + // Afterwards reload the state and continue with what we + // were doing from before. + while !node.signaled.load(Ordering::SeqCst) { + thread::park(); + } + state = my_state.load(Ordering::SeqCst); + continue 'outer; + } + } + } + } +} + +impl Drop for Finish<'_> { + fn drop(&mut self) { + // Swap out our state with however we finished. We should only ever see + // an old state which was RUNNING. + let queue = if self.failed { + // Difference from std: flip back to INCOMPLETE rather than POISONED. + self.my_state.swap(INCOMPLETE, Ordering::SeqCst) + } else { + self.my_state.swap(COMPLETE, Ordering::SeqCst) + }; + assert_eq!(queue & STATE_MASK, RUNNING); + + // Decode the RUNNING to a list of waiters, then walk that entire list + // and wake them up. Note that it is crucial that after we store `true` + // in the node it can be free'd! As a result we load the `thread` to + // signal ahead of time and then unpark it after the store. + unsafe { + let mut queue = (queue & !STATE_MASK) as *mut Waiter; + while !queue.is_null() { + let next = (*queue).next; + let thread = (*queue).thread.take().unwrap(); + (*queue).signaled.store(true, Ordering::SeqCst); + thread.unpark(); + queue = next; + } + } + } +} + +// These test are snatched from std as well. +#[cfg(test)] +mod tests { + use std::panic; + #[cfg(not(miri))] // miri doesn't support threads + use std::{sync::mpsc::channel, thread}; + + use super::OnceCell; + + impl OnceCell { + fn init(&self, f: impl FnOnce() -> T) { + enum Void {} + let _ = self.initialize(|| Ok::(f())); + } + } + + #[test] + fn smoke_once() { + static O: OnceCell<()> = OnceCell::new(); + let mut a = 0; + O.init(|| a += 1); + assert_eq!(a, 1); + O.init(|| a += 1); + assert_eq!(a, 1); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support threads + fn stampede_once() { + static O: OnceCell<()> = OnceCell::new(); + static mut RUN: bool = false; + + let (tx, rx) = channel(); + for _ in 0..10 { + let tx = tx.clone(); + thread::spawn(move || { + for _ in 0..4 { + thread::yield_now() + } + unsafe { + O.init(|| { + assert!(!RUN); + RUN = true; + }); + assert!(RUN); + } + tx.send(()).unwrap(); + }); + } + + unsafe { + O.init(|| { + assert!(!RUN); + RUN = true; + }); + assert!(RUN); + } + + for _ in 0..10 { + rx.recv().unwrap(); + } + } + + #[test] + #[cfg(not(miri))] // miri doesn't support panics + fn poison_bad() { + static O: OnceCell<()> = OnceCell::new(); + + // poison the once + let t = panic::catch_unwind(|| { + O.init(|| panic!()); + }); + assert!(t.is_err()); + + // we can subvert poisoning, however + let mut called = false; + O.init(|| { + called = true; + }); + assert!(called); + + // once any success happens, we stop propagating the poison + O.init(|| {}); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support panics + fn wait_for_force_to_finish() { + static O: OnceCell<()> = OnceCell::new(); + + // poison the once + let t = panic::catch_unwind(|| { + O.init(|| panic!()); + }); + assert!(t.is_err()); + + // make sure someone's waiting inside the once via a force + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + let t1 = thread::spawn(move || { + O.init(|| { + tx1.send(()).unwrap(); + rx2.recv().unwrap(); + }); + }); + + rx1.recv().unwrap(); + + // put another waiter on the once + let t2 = thread::spawn(|| { + let mut called = false; + O.init(|| { + called = true; + }); + assert!(!called); + }); + + tx2.send(()).unwrap(); + + assert!(t1.join().is_ok()); + assert!(t2.join().is_ok()); + } +} diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs new file mode 100644 index 0000000000..133e475d7f --- /dev/null +++ b/vendor/once_cell/src/lib.rs @@ -0,0 +1,920 @@ +/*! +# Overview + +`once_cell` provides two new cell-like types, `unsync::OnceCell` and `sync::OnceCell`. `OnceCell` +might store arbitrary non-`Copy` types, can be assigned to at most once and provide direct access +to the stored contents. In a nutshell, API looks *roughly* like this: + +```rust,ignore +impl OnceCell { + fn new() -> OnceCell { ... } + fn set(&self, value: T) -> Result<(), T> { ... } + fn get(&self) -> Option<&T> { ... } +} +``` + +Note that, like with `RefCell` and `Mutex`, the `set` method requires only a shared reference. +Because of the single assignment restriction `get` can return an `&T` instead of `Ref` +or `MutexGuard`. + +The `sync` flavor is thread-safe (that is, implements [`Sync`]) trait, while the `unsync` one is not. + +[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html + +# Patterns + +`OnceCell` might be useful for a variety of patterns. + +## Safe Initialization of global data + +```rust +use std::{env, io}; + +use once_cell::sync::OnceCell; + +#[derive(Debug)] +pub struct Logger { + // ... +} +static INSTANCE: OnceCell = OnceCell::new(); + +impl Logger { + pub fn global() -> &'static Logger { + INSTANCE.get().expect("logger is not initialized") + } + + fn from_cli(args: env::Args) -> Result { + // ... +# Ok(Logger {}) + } +} + +fn main() { + let logger = Logger::from_cli(env::args()).unwrap(); + INSTANCE.set(logger).unwrap(); + // use `Logger::global()` from now on +} +``` + +## Lazy initialized global data + +This is essentially `lazy_static!` macro, but without a macro. + +```rust +use std::{sync::Mutex, collections::HashMap}; + +use once_cell::sync::OnceCell; + +fn global_data() -> &'static Mutex> { + static INSTANCE: OnceCell>> = OnceCell::new(); + INSTANCE.get_or_init(|| { + let mut m = HashMap::new(); + m.insert(13, "Spica".to_string()); + m.insert(74, "Hoyten".to_string()); + Mutex::new(m) + }) +} +``` + +There are also `sync::Lazy` and `unsync::Lazy` convenience types to streamline this pattern: + +```rust +use std::{sync::Mutex, collections::HashMap}; +use once_cell::sync::Lazy; + +static GLOBAL_DATA: Lazy>> = Lazy::new(|| { + let mut m = HashMap::new(); + m.insert(13, "Spica".to_string()); + m.insert(74, "Hoyten".to_string()); + Mutex::new(m) +}); + +fn main() { + println!("{:?}", GLOBAL_DATA.lock().unwrap()); +} +``` + +## General purpose lazy evaluation + +Unlike `lazy_static!`, `Lazy` works with local variables. + +```rust +use once_cell::unsync::Lazy; + +fn main() { + let ctx = vec![1, 2, 3]; + let thunk = Lazy::new(|| { + ctx.iter().sum::() + }); + assert_eq!(*thunk, 6); +} +``` + +If you need a lazy field in a struct, you probably should use `OnceCell` +directly, because that will allow you to access `self` during initialization. + +```rust +use std::{fs, path::PathBuf}; + +use once_cell::unsync::OnceCell; + +struct Ctx { + config_path: PathBuf, + config: OnceCell, +} + +impl Ctx { + pub fn get_config(&self) -> Result<&str, std::io::Error> { + let cfg = self.config.get_or_try_init(|| { + fs::read_to_string(&self.config_path) + })?; + Ok(cfg.as_str()) + } +} +``` + +## Building block + +Naturally, it is possible to build other abstractions on top of `OnceCell`. +For example, this is a `regex!` macro which takes a string literal and returns an +*expression* that evaluates to a `&'static Regex`: + +``` +macro_rules! regex { + ($re:literal $(,)?) => {{ + static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + RE.get_or_init(|| regex::Regex::new($re).unwrap()) + }}; +} +``` + +This macro can be useful to avoid "compile regex on every loop iteration" problem. + +# Comparison with std + +|`!Sync` types | Access Mode | Drawbacks | +|----------------------|------------------------|-----------------------------------------------| +|`Cell` | `T` | requires `T: Copy` for `get` | +|`RefCel` | `RefMut` / `Ref` | may panic at runtime | +|`unsync::OnceCell` | `&T` | assignable only once | + +|`Sync` types | Access Mode | Drawbacks | +|----------------------|------------------------|-----------------------------------------------| +|`AtomicT` | `T` | works only with certain `Copy` types | +|`Mutex` | `MutexGuard` | may deadlock at runtime, may block the thread | +|`sync::OnceCell` | `&T` | assignable only once, may block the thread | + +Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls +itself. However, because the assignment can happen only once, such cases should be more rare than +equivalents with `RefCell` and `Mutex`. + +# Minimum Supported `rustc` Version + +This crate's minimum supported `rustc` version is `1.31.1`. + +If only `std` feature is enabled, MSRV will be updated conservatively. +When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable. +In both cases, increasing MSRV is *not* considered a semver-breaking change. + +# Implementation details + +Implementation is based on [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) +and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and `std::sync::Once`. In some sense, +`once_cell` just streamlines and unifies those APIs. + +To implement a sync flavor of `OnceCell`, this crates uses either a custom re-implementation of +`std::sync::Once` or `parking_lot::Mutex`. This is controlled by the `parking_lot` feature, which +is enabled by default. Performance is the same for both cases, but `parking_lot` based `OnceCell` +is smaller by up to 16 bytes. + +This crate uses unsafe. + +# F.A.Q. + +**Should I use lazy_static or once_cell?** + +To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static` +and should be preferred. + +Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with +`#![no_std]`. + +`lazy_static` has received significantly more real world testing, but `once_cell` is also a widely +used crate. + +**Should I use sync or unsync flavor?** + +Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where +`sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy +to switch between the two if code becomes multi-threaded later. + +At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which +might be easier to debug than a deadlock. + +# Related crates + +* [double-checked-cell](https://github.com/niklasf/double-checked-cell) +* [lazy-init](https://crates.io/crates/lazy-init) +* [lazycell](https://crates.io/crates/lazycell) +* [mitochondria](https://crates.io/crates/mitochondria) +* [lazy_static](https://crates.io/crates/lazy_static) + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +#[cfg(feature = "parking_lot")] +#[path = "imp_pl.rs"] +mod imp; + +#[cfg(feature = "std")] +#[cfg(not(feature = "parking_lot"))] +#[path = "imp_std.rs"] +mod imp; + +pub mod unsync { + use core::{ + cell::{Cell, UnsafeCell}, + fmt, + ops::Deref, + }; + + #[cfg(feature = "std")] + use std::panic::{RefUnwindSafe, UnwindSafe}; + + /// A cell which can be written to only once. Not thread safe. + /// + /// Unlike `:td::cell::RefCell`, a `OnceCell` provides simple `&` + /// references to the contents. + /// + /// # Example + /// ``` + /// use once_cell::unsync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert!(cell.get().is_none()); + /// + /// let value: &String = cell.get_or_init(|| { + /// "Hello, World!".to_string() + /// }); + /// assert_eq!(value, "Hello, World!"); + /// assert!(cell.get().is_some()); + /// ``` + pub struct OnceCell { + // Invariant: written to at most once. + inner: UnsafeCell>, + } + + // Similarly to a `Sync` bound on `sync::OnceCell`, we can use + // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`, + // by initializing the cell in closure and extracting the value in the + // `Drop`. + #[cfg(feature = "std")] + impl RefUnwindSafe for OnceCell {} + #[cfg(feature = "std")] + impl UnwindSafe for OnceCell {} + + impl Default for OnceCell { + fn default() -> Self { + Self::new() + } + } + + impl fmt::Debug for OnceCell { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.get() { + Some(v) => f.debug_tuple("OnceCell").field(v).finish(), + None => f.write_str("OnceCell(Uninit)"), + } + } + } + + impl Clone for OnceCell { + fn clone(&self) -> OnceCell { + let res = OnceCell::new(); + if let Some(value) = self.get() { + match res.set(value.clone()) { + Ok(()) => (), + Err(_) => unreachable!(), + } + } + res + } + } + + impl PartialEq for OnceCell { + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } + } + + impl Eq for OnceCell {} + + impl From for OnceCell { + fn from(value: T) -> Self { + OnceCell { inner: UnsafeCell::new(Some(value)) } + } + } + + impl OnceCell { + /// Creates a new empty cell. + pub const fn new() -> OnceCell { + OnceCell { inner: UnsafeCell::new(None) } + } + + /// Gets the reference to the underlying value. + /// + /// Returns `None` if the cell is empty. + pub fn get(&self) -> Option<&T> { + // Safe due to `inner`'s invariant + unsafe { &*self.inner.get() }.as_ref() + } + + /// Gets the mutable reference to the underlying value. + /// + /// Returns `None` if the cell is empty. + pub fn get_mut(&mut self) -> Option<&mut T> { + // Safe because we have unique access + unsafe { &mut *self.inner.get() }.as_mut() + } + + /// Sets the contents of this cell to `value`. + /// + /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was + /// full. + /// + /// # Example + /// ``` + /// use once_cell::unsync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert!(cell.get().is_none()); + /// + /// assert_eq!(cell.set(92), Ok(())); + /// assert_eq!(cell.set(62), Err(62)); + /// + /// assert!(cell.get().is_some()); + /// ``` + pub fn set(&self, value: T) -> Result<(), T> { + let slot = unsafe { &*self.inner.get() }; + if slot.is_some() { + return Err(value); + } + let slot = unsafe { &mut *self.inner.get() }; + // This is the only place where we set the slot, no races + // due to reentrancy/concurrency are possible, and we've + // checked that slot is currently `None`, so this write + // maintains the `inner`'s invariant. + *slot = Some(value); + Ok(()) + } + + /// Gets the contents of the cell, initializing it with `f` + /// if the cell was empty. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. Doing + /// so results in a panic. + /// + /// # Example + /// ``` + /// use once_cell::unsync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// let value = cell.get_or_init(|| 92); + /// assert_eq!(value, &92); + /// let value = cell.get_or_init(|| unreachable!()); + /// assert_eq!(value, &92); + /// ``` + pub fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + enum Void {} + match self.get_or_try_init(|| Ok::(f())) { + Ok(val) => val, + Err(void) => match void {}, + } + } + + /// Gets the contents of the cell, initializing it with `f` if + /// the cell was empty. If the cell was empty and `f` failed, an + /// error is returned. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. Doing + /// so results in a panic. + /// + /// # Example + /// ``` + /// use once_cell::unsync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); + /// assert!(cell.get().is_none()); + /// let value = cell.get_or_try_init(|| -> Result { + /// Ok(92) + /// }); + /// assert_eq!(value, Ok(&92)); + /// assert_eq!(cell.get(), Some(&92)) + /// ``` + pub fn get_or_try_init(&self, f: F) -> Result<&T, E> + where + F: FnOnce() -> Result, + { + if let Some(val) = self.get() { + return Ok(val); + } + let val = f()?; + assert!(self.set(val).is_ok(), "reentrant init"); + Ok(self.get().unwrap()) + } + + /// Consumes the `OnceCell`, returning the wrapped value. + /// + /// Returns `None` if the cell was empty. + /// + /// # Examples + /// + /// ``` + /// use once_cell::unsync::OnceCell; + /// + /// let cell: OnceCell = OnceCell::new(); + /// assert_eq!(cell.into_inner(), None); + /// + /// let cell = OnceCell::new(); + /// cell.set("hello".to_string()).unwrap(); + /// assert_eq!(cell.into_inner(), Some("hello".to_string())); + /// ``` + pub fn into_inner(self) -> Option { + // Because `into_inner` takes `self` by value, the compiler statically verifies + // that it is not currently borrowed. So it is safe to move out `Option`. + self.inner.into_inner() + } + } + + /// A value which is initialized on the first access. + /// + /// # Example + /// ``` + /// use once_cell::unsync::Lazy; + /// + /// let lazy: Lazy = Lazy::new(|| { + /// println!("initializing"); + /// 92 + /// }); + /// println!("ready"); + /// println!("{}", *lazy); + /// println!("{}", *lazy); + /// + /// // Prints: + /// // ready + /// // initializing + /// // 92 + /// // 92 + /// ``` + pub struct Lazy T> { + cell: OnceCell, + init: Cell>, + } + + #[cfg(feature = "std")] + impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} + + impl fmt::Debug for Lazy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() + } + } + + impl Lazy { + /// Creates a new lazy value with the given initializing function. + /// + /// # Example + /// ``` + /// # fn main() { + /// use once_cell::unsync::Lazy; + /// + /// let hello = "Hello, World!".to_string(); + /// + /// let lazy = Lazy::new(|| hello.to_uppercase()); + /// + /// assert_eq!(&*lazy, "HELLO, WORLD!"); + /// # } + /// ``` + pub const fn new(init: F) -> Lazy { + Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } + } + } + + impl T> Lazy { + /// Forces the evaluation of this lazy value and returns a reference to + /// the result. + /// + /// This is equivalent to the `Deref` impl, but is explicit. + /// + /// # Example + /// ``` + /// use once_cell::unsync::Lazy; + /// + /// let lazy = Lazy::new(|| 92); + /// + /// assert_eq!(Lazy::force(&lazy), &92); + /// assert_eq!(&*lazy, &92); + /// ``` + pub fn force(this: &Lazy) -> &T { + this.cell.get_or_init(|| match this.init.take() { + Some(f) => f(), + None => panic!("Lazy instance has previously been poisoned"), + }) + } + } + + impl T> Deref for Lazy { + type Target = T; + fn deref(&self) -> &T { + Lazy::force(self) + } + } + + impl Default for Lazy { + /// Creates a new lazy value using `Default` as the initializing function. + fn default() -> Lazy { + Lazy::new(T::default) + } + } +} + +#[cfg(feature = "std")] +pub mod sync { + use std::{cell::Cell, fmt, hint::unreachable_unchecked, panic::RefUnwindSafe}; + + use crate::imp::OnceCell as Imp; + + /// A thread-safe cell which can be written to only once. + /// + /// Unlike `std::sync::Mutex`, a `OnceCell` provides simple `&` references + /// to the contents. + /// + /// # Example + /// ``` + /// use once_cell::sync::OnceCell; + /// + /// static CELL: OnceCell = OnceCell::new(); + /// assert!(CELL.get().is_none()); + /// + /// std::thread::spawn(|| { + /// let value: &String = CELL.get_or_init(|| { + /// "Hello, World!".to_string() + /// }); + /// assert_eq!(value, "Hello, World!"); + /// }).join().unwrap(); + /// + /// let value: Option<&String> = CELL.get(); + /// assert!(value.is_some()); + /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); + /// ``` + pub struct OnceCell(Imp); + + impl Default for OnceCell { + fn default() -> OnceCell { + OnceCell::new() + } + } + + impl fmt::Debug for OnceCell { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.get() { + Some(v) => f.debug_tuple("OnceCell").field(v).finish(), + None => f.write_str("OnceCell(Uninit)"), + } + } + } + + impl Clone for OnceCell { + fn clone(&self) -> OnceCell { + let res = OnceCell::new(); + if let Some(value) = self.get() { + match res.set(value.clone()) { + Ok(()) => (), + Err(_) => unreachable!(), + } + } + res + } + } + + impl From for OnceCell { + fn from(value: T) -> Self { + let cell = Self::new(); + cell.get_or_init(|| value); + cell + } + } + + impl PartialEq for OnceCell { + fn eq(&self, other: &OnceCell) -> bool { + self.get() == other.get() + } + } + + impl Eq for OnceCell {} + + impl OnceCell { + /// Creates a new empty cell. + pub const fn new() -> OnceCell { + OnceCell(Imp::new()) + } + + /// Gets the reference to the underlying value. + /// + /// Returns `None` if the cell is empty, or being initialized. This + /// method never blocks. + pub fn get(&self) -> Option<&T> { + if self.0.is_initialized() { + // Safe b/c checked is_initialize + Some(unsafe { self.get_unchecked() }) + } else { + None + } + } + + /// Gets the mutable reference to the underlying value. + /// + /// Returns `None` if the cell is empty. + pub fn get_mut(&mut self) -> Option<&mut T> { + // Safe b/c we have a unique access. + unsafe { &mut *self.0.value.get() }.as_mut() + } + + /// Safety to call if guarded by `initialize`, `is_initialized` + /// + /// Implementations of those functions in `imp` must provide proper + /// synchronization and write-once property + unsafe fn get_unchecked(&self) -> &T { + let slot: &Option = &*self.0.value.get(); + match slot { + Some(value) => value, + // This unsafe does improve performance, see `examples/bench`. + None => { + debug_assert!(false); + unreachable_unchecked() + } + } + } + + /// Sets the contents of this cell to `value`. + /// + /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was + /// full. + /// + /// # Example + /// ``` + /// use once_cell::sync::OnceCell; + /// + /// static CELL: OnceCell = OnceCell::new(); + /// + /// fn main() { + /// assert!(CELL.get().is_none()); + /// + /// std::thread::spawn(|| { + /// assert_eq!(CELL.set(92), Ok(())); + /// }).join().unwrap(); + /// + /// assert_eq!(CELL.set(62), Err(62)); + /// assert_eq!(CELL.get(), Some(&92)); + /// } + /// ``` + pub fn set(&self, value: T) -> Result<(), T> { + let mut value = Some(value); + self.get_or_init(|| value.take().unwrap()); + match value { + None => Ok(()), + Some(value) => Err(value), + } + } + + /// Gets the contents of the cell, initializing it with `f` if the cell + /// was empty. + /// + /// Many threads may call `get_or_init` concurrently with different + /// initializing functions, but it is guaranteed that only one function + /// will be executed. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. The + /// exact outcome is unspecified. Current implementation deadlocks, but + /// this may be changed to a panic in the future. + /// + /// # Example + /// ``` + /// use once_cell::sync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// let value = cell.get_or_init(|| 92); + /// assert_eq!(value, &92); + /// let value = cell.get_or_init(|| unreachable!()); + /// assert_eq!(value, &92); + /// ``` + pub fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + enum Void {} + match self.get_or_try_init(|| Ok::(f())) { + Ok(val) => val, + Err(void) => match void {}, + } + } + + /// Gets the contents of the cell, initializing it with `f` if + /// the cell was empty. If the cell was empty and `f` failed, an + /// error is returned. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and + /// the cell remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. + /// The exact outcome is unspecified. Current implementation + /// deadlocks, but this may be changed to a panic in the future. + /// + /// # Example + /// ``` + /// use once_cell::sync::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); + /// assert!(cell.get().is_none()); + /// let value = cell.get_or_try_init(|| -> Result { + /// Ok(92) + /// }); + /// assert_eq!(value, Ok(&92)); + /// assert_eq!(cell.get(), Some(&92)) + /// ``` + pub fn get_or_try_init(&self, f: F) -> Result<&T, E> + where + F: FnOnce() -> Result, + { + // Fast path check + if let Some(value) = self.get() { + return Ok(value); + } + self.0.initialize(f)?; + + // Safe b/c called initialize + debug_assert!(self.0.is_initialized()); + Ok(unsafe { self.get_unchecked() }) + } + + /// Consumes the `OnceCell`, returning the wrapped value. Returns + /// `None` if the cell was empty. + /// + /// # Examples + /// + /// ``` + /// use once_cell::sync::OnceCell; + /// + /// let cell: OnceCell = OnceCell::new(); + /// assert_eq!(cell.into_inner(), None); + /// + /// let cell = OnceCell::new(); + /// cell.set("hello".to_string()).unwrap(); + /// assert_eq!(cell.into_inner(), Some("hello".to_string())); + /// ``` + pub fn into_inner(self) -> Option { + // Because `into_inner` takes `self` by value, the compiler statically verifies + // that it is not currently borrowed. So it is safe to move out `Option`. + self.0.value.into_inner() + } + } + + /// A value which is initialized on the first access. + /// + /// This type is thread-safe and can be used in statics: + /// + /// # Example + /// ``` + /// use std::collections::HashMap; + /// + /// use once_cell::sync::Lazy; + /// + /// static HASHMAP: Lazy> = Lazy::new(|| { + /// println!("initializing"); + /// let mut m = HashMap::new(); + /// m.insert(13, "Spica".to_string()); + /// m.insert(74, "Hoyten".to_string()); + /// m + /// }); + /// + /// fn main() { + /// println!("ready"); + /// std::thread::spawn(|| { + /// println!("{:?}", HASHMAP.get(&13)); + /// }).join().unwrap(); + /// println!("{:?}", HASHMAP.get(&74)); + /// + /// // Prints: + /// // ready + /// // initializing + /// // Some("Spica") + /// // Some("Hoyten") + /// } + /// ``` + pub struct Lazy T> { + cell: OnceCell, + init: Cell>, + } + + impl fmt::Debug for Lazy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() + } + } + + // We never create a `&F` from a `&Lazy` so it is fine + // to not impl `Sync` for `F` + // we do create a `&mut Option` in `force`, but this is + // properly synchronized, so it only happens once + // so it also does not contribute to this impl. + unsafe impl Sync for Lazy where OnceCell: Sync {} + // auto-derived `Send` impl is OK. + + #[cfg(feature = "std")] + impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} + + impl Lazy { + /// Creates a new lazy value with the given initializing + /// function. + pub const fn new(f: F) -> Lazy { + Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) } + } + } + + impl T> Lazy { + /// Forces the evaluation of this lazy value and + /// returns a reference to result. This is equivalent + /// to the `Deref` impl, but is explicit. + /// + /// # Example + /// ``` + /// use once_cell::sync::Lazy; + /// + /// let lazy = Lazy::new(|| 92); + /// + /// assert_eq!(Lazy::force(&lazy), &92); + /// assert_eq!(&*lazy, &92); + /// ``` + pub fn force(this: &Lazy) -> &T { + this.cell.get_or_init(|| match this.init.take() { + Some(f) => f(), + None => panic!("Lazy instance has previously been poisoned"), + }) + } + } + + impl T> ::std::ops::Deref for Lazy { + type Target = T; + fn deref(&self) -> &T { + Lazy::force(self) + } + } + + impl Default for Lazy { + /// Creates a new lazy value using `Default` as the initializing function. + fn default() -> Lazy { + Lazy::new(T::default) + } + } + + /// ```compile_fail + /// struct S(*mut ()); + /// unsafe impl Sync for S {} + /// + /// fn share(_: &T) {} + /// share(&once_cell::sync::OnceCell::::new()); + /// ``` + /// + /// ```compile_fail + /// struct S(*mut ()); + /// unsafe impl Sync for S {} + /// + /// fn share(_: &T) {} + /// share(&once_cell::sync::Lazy::::new(|| unimplemented!())); + /// ``` + fn _dummy() {} +} diff --git a/vendor/once_cell/tests/test.rs b/vendor/once_cell/tests/test.rs new file mode 100644 index 0000000000..a21673e8c8 --- /dev/null +++ b/vendor/once_cell/tests/test.rs @@ -0,0 +1,521 @@ +mod unsync { + use core::{ + cell::Cell, + sync::atomic::{AtomicUsize, Ordering::SeqCst}, + }; + + use once_cell::unsync::{Lazy, OnceCell}; + + #[test] + fn once_cell() { + let c = OnceCell::new(); + assert!(c.get().is_none()); + c.get_or_init(|| 92); + assert_eq!(c.get(), Some(&92)); + + c.get_or_init(|| panic!("Kabom!")); + assert_eq!(c.get(), Some(&92)); + } + + #[test] + fn once_cell_get_mut() { + let mut c = OnceCell::new(); + assert!(c.get_mut().is_none()); + c.set(90).unwrap(); + *c.get_mut().unwrap() += 2; + assert_eq!(c.get_mut(), Some(&mut 92)); + } + + #[test] + fn once_cell_drop() { + static DROP_CNT: AtomicUsize = AtomicUsize::new(0); + struct Dropper; + impl Drop for Dropper { + fn drop(&mut self) { + DROP_CNT.fetch_add(1, SeqCst); + } + } + + let x = OnceCell::new(); + x.get_or_init(|| Dropper); + assert_eq!(DROP_CNT.load(SeqCst), 0); + drop(x); + assert_eq!(DROP_CNT.load(SeqCst), 1); + } + + #[test] + fn unsync_once_cell_drop_empty() { + let x = OnceCell::::new(); + drop(x); + } + + #[test] + fn clone() { + let s = OnceCell::new(); + let c = s.clone(); + assert!(c.get().is_none()); + + s.set("hello".to_string()).unwrap(); + let c = s.clone(); + assert_eq!(c.get().map(String::as_str), Some("hello")); + } + + #[test] + fn from_impl() { + assert_eq!(OnceCell::from("value").get(), Some(&"value")); + assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); + } + + #[test] + fn partialeq_impl() { + assert!(OnceCell::from("value") == OnceCell::from("value")); + assert!(OnceCell::from("foo") != OnceCell::from("bar")); + + assert!(OnceCell::::new() == OnceCell::new()); + assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); + } + + #[test] + fn into_inner() { + let cell: OnceCell = OnceCell::new(); + assert_eq!(cell.into_inner(), None); + let cell = OnceCell::new(); + cell.set("hello".to_string()).unwrap(); + assert_eq!(cell.into_inner(), Some("hello".to_string())); + } + + #[test] + fn debug_impl() { + let cell = OnceCell::new(); + assert_eq!(format!("{:?}", cell), "OnceCell(Uninit)"); + cell.set("hello".to_string()).unwrap(); + assert_eq!(format!("{:?}", cell), "OnceCell(\"hello\")"); + } + + #[test] + fn lazy_new() { + let called = Cell::new(0); + let x = Lazy::new(|| { + called.set(called.get() + 1); + 92 + }); + + assert_eq!(called.get(), 0); + + let y = *x - 30; + assert_eq!(y, 62); + assert_eq!(called.get(), 1); + + let y = *x - 30; + assert_eq!(y, 62); + assert_eq!(called.get(), 1); + } + + #[test] + fn lazy_default() { + static CALLED: AtomicUsize = AtomicUsize::new(0); + + struct Foo(u8); + impl Default for Foo { + fn default() -> Self { + CALLED.fetch_add(1, SeqCst); + Foo(42) + } + } + + let lazy: Lazy> = <_>::default(); + + assert_eq!(CALLED.load(SeqCst), 0); + + assert_eq!(lazy.lock().unwrap().0, 42); + assert_eq!(CALLED.load(SeqCst), 1); + + lazy.lock().unwrap().0 = 21; + + assert_eq!(lazy.lock().unwrap().0, 21); + assert_eq!(CALLED.load(SeqCst), 1); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support panics + #[cfg(feature = "std")] + fn lazy_poisoning() { + let x: Lazy = Lazy::new(|| panic!("kaboom")); + for _ in 0..2 { + let res = std::panic::catch_unwind(|| x.len()); + assert!(res.is_err()); + } + } + + #[test] + fn aliasing_in_get() { + let x = once_cell::unsync::OnceCell::new(); + x.set(42).unwrap(); + let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option` --+ + let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option` | + println!("{}", at_x); // <------- up until here ---------------------------+ + } +} + +#[cfg(feature = "std")] +mod sync { + use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + + use once_cell::sync::{Lazy, OnceCell}; + + #[cfg(not(miri))] // miri doesn't support threads + mod scope { + pub(super) use crossbeam_utils::thread::scope; + } + + #[cfg(miri)] + mod scope { + pub(super) struct Scope; + + #[cfg(miri)] + impl Scope { + pub(super) fn spawn(&self, f: impl FnOnce(())) { + f(()); + } + } + + #[cfg(miri)] + pub(super) fn scope(f: impl FnOnce(&Scope)) -> Result<(), ()> { + f(&Scope); + Ok(()) + } + } + + use scope::scope; + + #[test] + fn once_cell() { + let c = OnceCell::new(); + assert!(c.get().is_none()); + scope(|s| { + s.spawn(|_| { + c.get_or_init(|| 92); + assert_eq!(c.get(), Some(&92)); + }); + }) + .unwrap(); + c.get_or_init(|| panic!("Kabom!")); + assert_eq!(c.get(), Some(&92)); + } + + #[test] + fn once_cell_get_mut() { + let mut c = OnceCell::new(); + assert!(c.get_mut().is_none()); + c.set(90).unwrap(); + *c.get_mut().unwrap() += 2; + assert_eq!(c.get_mut(), Some(&mut 92)); + } + + #[test] + fn once_cell_drop() { + static DROP_CNT: AtomicUsize = AtomicUsize::new(0); + struct Dropper; + impl Drop for Dropper { + fn drop(&mut self) { + DROP_CNT.fetch_add(1, SeqCst); + } + } + + let x = OnceCell::new(); + scope(|s| { + s.spawn(|_| { + x.get_or_init(|| Dropper); + assert_eq!(DROP_CNT.load(SeqCst), 0); + drop(x); + }); + }) + .unwrap(); + assert_eq!(DROP_CNT.load(SeqCst), 1); + } + + #[test] + fn once_cell_drop_empty() { + let x = OnceCell::::new(); + drop(x); + } + + #[test] + fn clone() { + let s = OnceCell::new(); + let c = s.clone(); + assert!(c.get().is_none()); + + s.set("hello".to_string()).unwrap(); + let c = s.clone(); + assert_eq!(c.get().map(String::as_str), Some("hello")); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support panics + fn get_or_try_init() { + let cell: OnceCell = OnceCell::new(); + assert!(cell.get().is_none()); + + let res = + std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); + assert!(res.is_err()); + assert!(cell.get().is_none()); + + assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); + + assert_eq!( + cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), + Ok(&"hello".to_string()) + ); + assert_eq!(cell.get(), Some(&"hello".to_string())); + } + + #[test] + fn from_impl() { + assert_eq!(OnceCell::from("value").get(), Some(&"value")); + assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); + } + + #[test] + fn partialeq_impl() { + assert!(OnceCell::from("value") == OnceCell::from("value")); + assert!(OnceCell::from("foo") != OnceCell::from("bar")); + + assert!(OnceCell::::new() == OnceCell::new()); + assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); + } + + #[test] + fn into_inner() { + let cell: OnceCell = OnceCell::new(); + assert_eq!(cell.into_inner(), None); + let cell = OnceCell::new(); + cell.set("hello".to_string()).unwrap(); + assert_eq!(cell.into_inner(), Some("hello".to_string())); + } + + #[test] + fn debug_impl() { + let cell = OnceCell::new(); + assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)"); + cell.set(vec!["hello", "world"]).unwrap(); + assert_eq!( + format!("{:#?}", cell), + r#"OnceCell( + [ + "hello", + "world", + ], +)"# + ); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support processes + fn reentrant_init() { + let examples_dir = { + let mut exe = std::env::current_exe().unwrap(); + exe.pop(); + exe.pop(); + exe.push("examples"); + exe + }; + let bin = examples_dir + .join("reentrant_init_deadlocks") + .with_extension(std::env::consts::EXE_EXTENSION); + let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() }; + std::thread::sleep(std::time::Duration::from_secs(2)); + let status = guard.child.try_wait().unwrap(); + assert!(status.is_none()); + + struct Guard { + child: std::process::Child, + } + + impl Drop for Guard { + fn drop(&mut self) { + let _ = self.child.kill(); + } + } + } + + #[test] + fn lazy_new() { + let called = AtomicUsize::new(0); + let x = Lazy::new(|| { + called.fetch_add(1, SeqCst); + 92 + }); + + assert_eq!(called.load(SeqCst), 0); + + scope(|s| { + s.spawn(|_| { + let y = *x - 30; + assert_eq!(y, 62); + assert_eq!(called.load(SeqCst), 1); + }); + }) + .unwrap(); + + let y = *x - 30; + assert_eq!(y, 62); + assert_eq!(called.load(SeqCst), 1); + } + + #[test] + fn lazy_default() { + static CALLED: AtomicUsize = AtomicUsize::new(0); + + struct Foo(u8); + impl Default for Foo { + fn default() -> Self { + CALLED.fetch_add(1, SeqCst); + Foo(42) + } + } + + let lazy: Lazy> = <_>::default(); + + assert_eq!(CALLED.load(SeqCst), 0); + + assert_eq!(lazy.lock().unwrap().0, 42); + assert_eq!(CALLED.load(SeqCst), 1); + + lazy.lock().unwrap().0 = 21; + + assert_eq!(lazy.lock().unwrap().0, 21); + assert_eq!(CALLED.load(SeqCst), 1); + } + + #[test] + #[cfg(not(miri))] // leaks memory + fn static_lazy() { + static XS: Lazy> = Lazy::new(|| { + let mut xs = Vec::new(); + xs.push(1); + xs.push(2); + xs.push(3); + xs + }); + scope(|s| { + s.spawn(|_| { + assert_eq!(&*XS, &vec![1, 2, 3]); + }); + }) + .unwrap(); + assert_eq!(&*XS, &vec![1, 2, 3]); + } + + #[test] + #[cfg(not(miri))] // leaks memory + fn static_lazy_via_fn() { + fn xs() -> &'static Vec { + static XS: OnceCell> = OnceCell::new(); + XS.get_or_init(|| { + let mut xs = Vec::new(); + xs.push(1); + xs.push(2); + xs.push(3); + xs + }) + } + assert_eq!(xs(), &vec![1, 2, 3]); + } + + #[test] + #[cfg(not(miri))] // miri doesn't support panics + fn lazy_poisoning() { + let x: Lazy = Lazy::new(|| panic!("kaboom")); + for _ in 0..2 { + let res = std::panic::catch_unwind(|| x.len()); + assert!(res.is_err()); + } + } + + #[test] + fn once_cell_is_sync_send() { + fn assert_traits() {} + assert_traits::>(); + assert_traits::>(); + } + + #[test] + #[cfg(not(miri))] // leaks memory + fn eval_once_macro() { + macro_rules! eval_once { + (|| -> $ty:ty { + $($body:tt)* + }) => {{ + static ONCE_CELL: OnceCell<$ty> = OnceCell::new(); + fn init() -> $ty { + $($body)* + } + ONCE_CELL.get_or_init(init) + }}; + } + + let fib: &'static Vec = eval_once! { + || -> Vec { + let mut res = vec![1, 1]; + for i in 0..10 { + let next = res[i] + res[i + 1]; + res.push(next); + } + res + } + }; + assert_eq!(fib[5], 8) + } + + #[test] + #[cfg(not(miri))] // deadlocks without real threads + fn once_cell_does_not_leak_partially_constructed_boxes() { + let n_tries = 100; + let n_readers = 10; + let n_writers = 3; + const MSG: &str = "Hello, World"; + + for _ in 0..n_tries { + let cell: OnceCell = OnceCell::new(); + scope(|scope| { + for _ in 0..n_readers { + scope.spawn(|_| loop { + if let Some(msg) = cell.get() { + assert_eq!(msg, MSG); + break; + } + }); + } + for _ in 0..n_writers { + scope.spawn(|_| cell.set(MSG.to_owned())); + } + }) + .unwrap() + } + } + + #[test] + #[cfg(not(miri))] // miri doesn't support Barrier + fn get_does_not_block() { + use std::sync::Barrier; + + let cell = OnceCell::new(); + let barrier = Barrier::new(2); + scope(|scope| { + scope.spawn(|_| { + cell.get_or_init(|| { + barrier.wait(); + barrier.wait(); + "hello".to_string() + }); + }); + barrier.wait(); + assert_eq!(cell.get(), None); + barrier.wait(); + }) + .unwrap(); + assert_eq!(cell.get(), Some(&"hello".to_string())); + } +} diff --git a/vendor/owning_ref/.cargo-checksum.json b/vendor/owning_ref/.cargo-checksum.json deleted file mode 100644 index aeedd0a028..0000000000 --- a/vendor/owning_ref/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"d6033830eecd6112eb61e775f848ab6c7ee76822ee1d7f8786b34e6e71f45b7b","LICENSE":"90bc15ed094593083fd129fdd1a03607be80fe8839c5564616a5961ab7f7a194","README.md":"e18ff10a148a8316e89bbe9f45cb57657170abe1a19154f8a5c968d529fe895e","src/lib.rs":"5d8857eee0de9863c3b6fce98732427cc1868a5ec3f0e3ce652ec011391aa842"},"package":"cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"} \ No newline at end of file diff --git a/vendor/owning_ref/Cargo.toml b/vendor/owning_ref/Cargo.toml deleted file mode 100644 index 24edb378f7..0000000000 --- a/vendor/owning_ref/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "owning_ref" -version = "0.3.3" -authors = ["Marvin Löbel "] -license = "MIT" - -description = "A library for creating references that carry their owner with them." -readme = "README.md" -documentation = "http://kimundi.github.io/owning-ref-rs/owning_ref/index.html" - -repository = "https://github.com/Kimundi/owning-ref-rs" -keywords = ["reference", "sibling", "field", "owning"] - -[dependencies] -stable_deref_trait = "1.0.0" diff --git a/vendor/owning_ref/README.md b/vendor/owning_ref/README.md deleted file mode 100644 index c4c74f1f9a..0000000000 --- a/vendor/owning_ref/README.md +++ /dev/null @@ -1,67 +0,0 @@ -owning-ref-rs -============== - -A library for creating references that carry their owner with them. - -This can sometimes be useful because Rust borrowing rules normally prevent -moving a type that has been moved from. For example, this kind of code gets rejected: - -```rust -fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { - let v = vec![1, 2, 3, 4]; - let s = &v[1..3]; - (v, s) -} -``` - -This library enables this safe usage by keeping the owner and the reference -bundled together in a wrapper type that ensure that lifetime constraint: - -```rust -fn return_owned_and_referenced() -> OwningRef, [u8]> { - let v = vec![1, 2, 3, 4]; - let or = OwningRef::new(v); - let or = or.map(|v| &v[1..3]); - or -} -``` - -[![Travis-CI Status](https://travis-ci.org/Kimundi/owning-ref-rs.png?branch=master)](https://travis-ci.org/Kimundi/owning-ref-rs) - -# Getting Started - -[owning-ref-rs is available on crates.io](https://crates.io/crates/owning_ref). -It is recommended to look there for the newest released version, as well as links to the newest builds of the docs. - -At the point of the last update of this README, the latest published version could be used like this: - -Add the following dependency to your Cargo manifest... - -```toml -[dependencies] -owning_ref = "0.3" -``` - -...and see the [docs](http://kimundi.github.io/owning-ref-rs/owning_ref/index.html) for how to use it. - -# Example - -```rust -extern crate owning_ref; -use owning_ref::BoxRef; - -fn main() { - // Create an array owned by a Box. - let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; - - // Transfer into a BoxRef. - let arr: BoxRef<[i32]> = BoxRef::new(arr); - assert_eq!(&*arr, &[1, 2, 3, 4]); - - // We can slice the array without losing ownership or changing type. - let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); - assert_eq!(&*arr, &[2, 3]); - - // Also works for Arc, Rc, String and Vec! -} -``` diff --git a/vendor/owning_ref/src/lib.rs b/vendor/owning_ref/src/lib.rs deleted file mode 100644 index 21ed086571..0000000000 --- a/vendor/owning_ref/src/lib.rs +++ /dev/null @@ -1,1891 +0,0 @@ -#![warn(missing_docs)] - -/*! -# An owning reference. - -This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` -that enables it to bundle a reference together with the owner of the data it points to. -This allows moving and dropping of a `OwningRef` without needing to recreate the reference. - -This can sometimes be useful because Rust borrowing rules normally prevent -moving a type that has been moved from. For example, this kind of code gets rejected: - -```rust,ignore -fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { - let v = vec![1, 2, 3, 4]; - let s = &v[1..3]; - (v, s) -} -``` - -Even though, from a memory-layout point of view, this can be entirely safe -if the new location of the vector still lives longer than the lifetime `'a` -of the reference because the backing allocation of the vector does not change. - -This library enables this safe usage by keeping the owner and the reference -bundled together in a wrapper type that ensure that lifetime constraint: - -```rust -# extern crate owning_ref; -# use owning_ref::OwningRef; -# fn main() { -fn return_owned_and_referenced() -> OwningRef, [u8]> { - let v = vec![1, 2, 3, 4]; - let or = OwningRef::new(v); - let or = or.map(|v| &v[1..3]); - or -} -# } -``` - -It works by requiring owner types to dereference to stable memory locations -and preventing mutable access to root containers, which in practice requires heap allocation -as provided by `Box`, `Rc`, etc. - -Also provided are typedefs for common owner type combinations, -which allow for less verbose type signatures. For example, `BoxRef` instead of `OwningRef, T>`. - -The crate also provides the more advanced `OwningHandle` type, -which allows more freedom in bundling a dependent handle object -along with the data it depends on, at the cost of some unsafe needed in the API. -See the documentation around `OwningHandle` for more details. - -# Examples - -## Basics - -``` -extern crate owning_ref; -use owning_ref::BoxRef; - -fn main() { - // Create an array owned by a Box. - let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; - - // Transfer into a BoxRef. - let arr: BoxRef<[i32]> = BoxRef::new(arr); - assert_eq!(&*arr, &[1, 2, 3, 4]); - - // We can slice the array without losing ownership or changing type. - let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); - assert_eq!(&*arr, &[2, 3]); - - // Also works for Arc, Rc, String and Vec! -} -``` - -## Caching a reference to a struct field - -``` -extern crate owning_ref; -use owning_ref::BoxRef; - -fn main() { - struct Foo { - tag: u32, - x: u16, - y: u16, - z: u16, - } - let foo = Foo { tag: 1, x: 100, y: 200, z: 300 }; - - let or = BoxRef::new(Box::new(foo)).map(|foo| { - match foo.tag { - 0 => &foo.x, - 1 => &foo.y, - 2 => &foo.z, - _ => panic!(), - } - }); - - assert_eq!(*or, 200); -} -``` - -## Caching a reference to an entry in a vector - -``` -extern crate owning_ref; -use owning_ref::VecRef; - -fn main() { - let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]); - assert_eq!(*v, 4); -} -``` - -## Caching a subslice of a String - -``` -extern crate owning_ref; -use owning_ref::StringRef; - -fn main() { - let s = StringRef::new("hello world".to_owned()) - .map(|s| s.split(' ').nth(1).unwrap()); - - assert_eq!(&*s, "world"); -} -``` - -## Reference counted slices that share ownership of the backing storage - -``` -extern crate owning_ref; -use owning_ref::RcRef; -use std::rc::Rc; - -fn main() { - let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>); - assert_eq!(&*rc, &[1, 2, 3, 4]); - - let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]); - let rc_b = rc.clone().map(|s| &s[1..3]); - let rc_c = rc.clone().map(|s| &s[2..4]); - assert_eq!(&*rc_a, &[1, 2]); - assert_eq!(&*rc_b, &[2, 3]); - assert_eq!(&*rc_c, &[3, 4]); - - let rc_c_a = rc_c.clone().map(|s| &s[1]); - assert_eq!(&*rc_c_a, &4); -} -``` - -## Atomic reference counted slices that share ownership of the backing storage - -``` -extern crate owning_ref; -use owning_ref::ArcRef; -use std::sync::Arc; - -fn main() { - use std::thread; - - fn par_sum(rc: ArcRef<[i32]>) -> i32 { - if rc.len() == 0 { - return 0; - } else if rc.len() == 1 { - return rc[0]; - } - let mid = rc.len() / 2; - let left = rc.clone().map(|s| &s[..mid]); - let right = rc.map(|s| &s[mid..]); - - let left = thread::spawn(move || par_sum(left)); - let right = thread::spawn(move || par_sum(right)); - - left.join().unwrap() + right.join().unwrap() - } - - let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]); - let rc: ArcRef<[i32]> = rc.into(); - - assert_eq!(par_sum(rc), 10); -} -``` - -## References into RAII locks - -``` -extern crate owning_ref; -use owning_ref::RefRef; -use std::cell::{RefCell, Ref}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - // Also works with Mutex and RwLock - - let refref = { - let refref = RefRef::new(refcell.borrow()).map(|x| &x.3); - assert_eq!(*refref, 4); - - // We move the RAII lock and the reference to one of - // the subfields in the data it guards here: - refref - }; - - assert_eq!(*refref, 4); - - drop(refref); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 4)); -} -``` - -## Mutable reference - -When the owned container implements `DerefMut`, it is also possible to make -a _mutable owning reference_. (E.g. with `Box`, `RefMut`, `MutexGuard`) - -``` -extern crate owning_ref; -use owning_ref::RefMutRefMut; -use std::cell::{RefCell, RefMut}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - - let mut refmut_refmut = { - let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3); - assert_eq!(*refmut_refmut, 4); - *refmut_refmut *= 2; - - refmut_refmut - }; - - assert_eq!(*refmut_refmut, 8); - *refmut_refmut *= 2; - - drop(refmut_refmut); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 16)); -} -``` -*/ - -extern crate stable_deref_trait; -pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress}; - -/// An owning reference. -/// -/// This wraps an owner `O` and a reference `&T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRef { - owner: O, - reference: *const T, -} - -/// An mutable owning reference. -/// -/// This wraps an owner `O` and a reference `&mut T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRefMut { - owner: O, - reference: *mut T, -} - -/// Helper trait for an erased concrete type an owner dereferences to. -/// This is used in form of a trait object for keeping -/// something around to (virtually) call the destructor. -pub trait Erased {} -impl Erased for T {} - -/// Helper trait for erasing the concrete type of what an owner derferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -pub unsafe trait IntoErased<'a> { - /// Owner with the dereference type substituted to `Erased`. - type Erased; - /// Perform the type erasure. - fn into_erased(self) -> Self::Erased; -} - -///////////////////////////////////////////////////////////////////////////// -// OwningRef -///////////////////////////////////////////////////////////////////////////// - -impl OwningRef { - /// Creates a new owning reference from a owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new(42)); - /// assert_eq!(*owning_ref, 42); - /// } - /// ``` - pub fn new(o: O) -> Self - where O: StableAddress, - O: Deref, - { - OwningRef { - reference: &*o, - owner: o, - } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(o: O) -> Self - where O: Deref, - { - OwningRef { - reference: &*o, - owner: o, - } - } - - /// Converts `self` into a new owning reference that points at something reachable - /// from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(self, f: F) -> OwningRef - where O: StableAddress, - F: FnOnce(&T) -> &U - { - OwningRef { - reference: f(&self), - owner: self.owner, - } - } - - /// Tries to convert `self` into a new owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(self, f: F) -> Result, E> - where O: StableAddress, - F: FnOnce(&T) -> Result<&U, E> - { - Ok(OwningRef { - reference: f(&self)?, - owner: self.owner, - }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRef - where O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P - { - OwningRef { - reference: self.reference, - owner: f(self.owner), - } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRef` - /// to a `OwningRef, T>`. - pub fn map_owner_box(self) -> OwningRef, T> { - OwningRef { - reference: self.reference, - owner: Box::new(self.owner), - } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::{OwningRef, Erased}; - /// - /// fn main() { - /// // NB: Using the concrete types here for explicitnes. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_a: OwningRef, [i32; 4]> - /// = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_b: OwningRef>, Vec<(i32, bool)>> - /// = OwningRef::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_a: OwningRef, i32> - /// = owning_ref_a.map(|a| &a[0]); - /// - /// let owning_ref_b: OwningRef>, i32> - /// = owning_ref_b.map(|a| &a[1].0); - /// - /// let owning_refs: [OwningRef, i32>; 2] - /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs[0], 1); - /// assert_eq!(*owning_refs[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRef - where O: IntoErased<'a>, - { - OwningRef { - reference: self.reference, - owner: self.owner.into_erased(), - } - } - - // TODO: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -impl OwningRefMut { - /// Creates a new owning reference from a owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new(42)); - /// assert_eq!(*owning_ref_mut, 42); - /// } - /// ``` - pub fn new(mut o: O) -> Self - where O: StableAddress, - O: DerefMut, - { - OwningRefMut { - reference: &mut *o, - owner: o, - } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(mut o: O) -> Self - where O: DerefMut, - { - OwningRefMut { - reference: &mut *o, - owner: o, - } - } - - /// Converts `self` into a new _shared_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(mut self, f: F) -> OwningRef - where O: StableAddress, - F: FnOnce(&mut T) -> &U - { - OwningRef { - reference: f(&mut self), - owner: self.owner, - } - } - - /// Converts `self` into a new _mutable_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]); - /// assert_eq!(*owning_ref_mut, 3); - /// } - /// ``` - pub fn map_mut(mut self, f: F) -> OwningRefMut - where O: StableAddress, - F: FnOnce(&mut T) -> &mut U - { - OwningRefMut { - reference: f(&mut self), - owner: self.owner, - } - } - - /// Tries to convert `self` into a new _shared_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(mut self, f: F) -> Result, E> - where O: StableAddress, - F: FnOnce(&mut T) -> Result<&U, E> - { - Ok(OwningRef { - reference: f(&mut self)?, - owner: self.owner, - }) - } - - /// Tries to convert `self` into a new _mutable_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| { - /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref_mut.unwrap(), 3); - /// } - /// ``` - pub fn try_map_mut(mut self, f: F) -> Result, E> - where O: StableAddress, - F: FnOnce(&mut T) -> Result<&mut U, E> - { - Ok(OwningRefMut { - reference: f(&mut self)?, - owner: self.owner, - }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRefMut - where O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P - { - OwningRefMut { - reference: self.reference, - owner: f(self.owner), - } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRefMut` - /// to a `OwningRefMut, T>`. - pub fn map_owner_box(self) -> OwningRefMut, T> { - OwningRefMut { - reference: self.reference, - owner: Box::new(self.owner), - } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::{OwningRefMut, Erased}; - /// - /// fn main() { - /// // NB: Using the concrete types here for explicitnes. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> - /// = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_mut_b: OwningRefMut>, Vec<(i32, bool)>> - /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_mut_a: OwningRefMut, i32> - /// = owning_ref_mut_a.map_mut(|a| &mut a[0]); - /// - /// let owning_ref_mut_b: OwningRefMut>, i32> - /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0); - /// - /// let owning_refs_mut: [OwningRefMut, i32>; 2] - /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs_mut[0], 1); - /// assert_eq!(*owning_refs_mut[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRefMut - where O: IntoErased<'a>, - { - OwningRefMut { - reference: self.reference, - owner: self.owner.into_erased(), - } - } - - // TODO: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -///////////////////////////////////////////////////////////////////////////// -// OwningHandle -///////////////////////////////////////////////////////////////////////////// - -use std::ops::{Deref, DerefMut}; - -/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows -/// consumers to pass around an owned object and a dependent reference, -/// `OwningHandle` contains an owned object and a dependent _object_. -/// -/// `OwningHandle` can encapsulate a `RefMut` along with its associated -/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. -/// However, the API is completely generic and there are no restrictions on -/// what types of owning and dependent objects may be used. -/// -/// `OwningHandle` is created by passing an owner object (which dereferences -/// to a stable address) along with a callback which receives a pointer to -/// that stable location. The callback may then dereference the pointer and -/// mint a dependent object, with the guarantee that the returned object will -/// not outlive the referent of the pointer. -/// -/// Since the callback needs to dereference a raw pointer, it requires `unsafe` -/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is -/// implemented for common data structures. Types that implement `ToHandle` can -/// be wrapped into an `OwningHandle` without passing a callback. -pub struct OwningHandle - where O: StableAddress, H: Deref, -{ - handle: H, - _owner: O, -} - -impl Deref for OwningHandle - where O: StableAddress, H: Deref, -{ - type Target = H::Target; - fn deref(&self) -> &H::Target { - self.handle.deref() - } -} - -unsafe impl StableAddress for OwningHandle - where O: StableAddress, H: StableAddress, -{} - -impl DerefMut for OwningHandle - where O: StableAddress, H: DerefMut, -{ - fn deref_mut(&mut self) -> &mut H::Target { - self.handle.deref_mut() - } -} - -/// Trait to implement the conversion of owner to handle for common types. -pub trait ToHandle { - /// The type of handle to be encapsulated by the OwningHandle. - type Handle: Deref; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle(x: *const Self) -> Self::Handle; -} - -/// Trait to implement the conversion of owner to mutable handle for common types. -pub trait ToHandleMut { - /// The type of handle to be encapsulated by the OwningHandle. - type HandleMut: DerefMut; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// mutable handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut; -} - -impl OwningHandle - where O: StableAddress, O::Target: ToHandle, H: Deref, -{ - /// Create a new `OwningHandle` for a type that implements `ToHandle`. For types - /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts - /// a callback to perform the conversion. - pub fn new(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) }) - } -} - -impl OwningHandle - where O: StableAddress, O::Target: ToHandleMut, H: DerefMut, -{ - /// Create a new mutable `OwningHandle` for a type that implements `ToHandleMut`. - pub fn new_mut(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) }) - } -} - -impl OwningHandle - where O: StableAddress, H: Deref, -{ - /// Create a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn new_with_fn(o: O, f: F) -> Self - where F: FnOnce(*const O::Target) -> H - { - let h: H; - { - h = f(o.deref() as *const O::Target); - } - - OwningHandle { - handle: h, - _owner: o, - } - } - - /// Create a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn try_new(o: O, f: F) -> Result - where F: FnOnce(*const O::Target) -> Result - { - let h: H; - { - h = f(o.deref() as *const O::Target)?; - } - - Ok(OwningHandle { - handle: h, - _owner: o, - }) - } -} - -///////////////////////////////////////////////////////////////////////////// -// std traits -///////////////////////////////////////////////////////////////////////////// - -use std::convert::From; -use std::fmt::{self, Debug}; -use std::marker::{Send, Sync}; -use std::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering}; -use std::hash::{Hash, Hasher}; -use std::borrow::Borrow; - -impl Deref for OwningRef { - type Target = T; - - fn deref(&self) -> &T { - unsafe { - &*self.reference - } - } -} - -impl Deref for OwningRefMut { - type Target = T; - - fn deref(&self) -> &T { - unsafe { - &*self.reference - } - } -} - -impl DerefMut for OwningRefMut { - fn deref_mut(&mut self) -> &mut T { - unsafe { - &mut *self.reference - } - } -} - -unsafe impl StableAddress for OwningRef {} - -impl AsRef for OwningRef { - fn as_ref(&self) -> &T { - &*self - } -} - -impl AsRef for OwningRefMut { - fn as_ref(&self) -> &T { - &*self - } -} - -impl AsMut for OwningRefMut { - fn as_mut(&mut self) -> &mut T { - &mut *self - } -} - -impl Borrow for OwningRef { - fn borrow(&self) -> &T { - &*self - } -} - -impl From for OwningRef - where O: StableAddress, - O: Deref, -{ - fn from(owner: O) -> Self { - OwningRef::new(owner) - } -} - -impl From for OwningRefMut - where O: StableAddress, - O: DerefMut -{ - fn from(owner: O) -> Self { - OwningRefMut::new(owner) - } -} - -impl From> for OwningRef - where O: StableAddress, - O: DerefMut -{ - fn from(other: OwningRefMut) -> Self { - OwningRef { - owner: other.owner, - reference: other.reference, - } - } -} - -// ^ FIXME: Is a Into impl for calling into_inner() possible as well? - -impl Debug for OwningRef - where O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, - "OwningRef {{ owner: {:?}, reference: {:?} }}", - self.owner(), - &**self) - } -} - -impl Debug for OwningRefMut - where O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, - "OwningRefMut {{ owner: {:?}, reference: {:?} }}", - self.owner(), - &**self) - } -} - -impl Clone for OwningRef - where O: CloneStableAddress, -{ - fn clone(&self) -> Self { - OwningRef { - owner: self.owner.clone(), - reference: self.reference, - } - } -} - -unsafe impl CloneStableAddress for OwningRef - where O: CloneStableAddress {} - -unsafe impl Send for OwningRef - where O: Send, for<'a> (&'a T): Send {} -unsafe impl Sync for OwningRef - where O: Sync, for<'a> (&'a T): Sync {} - -unsafe impl Send for OwningRefMut - where O: Send, for<'a> (&'a mut T): Send {} -unsafe impl Sync for OwningRefMut - where O: Sync, for<'a> (&'a mut T): Sync {} - -impl Debug for Erased { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "",) - } -} - -impl PartialEq for OwningRef where T: PartialEq { - fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) - } -} - -impl Eq for OwningRef where T: Eq {} - -impl PartialOrd for OwningRef where T: PartialOrd { - fn partial_cmp(&self, other: &Self) -> Option { - (&*self as &T).partial_cmp(&*other as &T) - } -} - -impl Ord for OwningRef where T: Ord { - fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) - } -} - -impl Hash for OwningRef where T: Hash { - fn hash(&self, state: &mut H) { - (&*self as &T).hash(state); - } -} - -impl PartialEq for OwningRefMut where T: PartialEq { - fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) - } -} - -impl Eq for OwningRefMut where T: Eq {} - -impl PartialOrd for OwningRefMut where T: PartialOrd { - fn partial_cmp(&self, other: &Self) -> Option { - (&*self as &T).partial_cmp(&*other as &T) - } -} - -impl Ord for OwningRefMut where T: Ord { - fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) - } -} - -impl Hash for OwningRefMut where T: Hash { - fn hash(&self, state: &mut H) { - (&*self as &T).hash(state); - } -} - -///////////////////////////////////////////////////////////////////////////// -// std types integration and convenience type defs -///////////////////////////////////////////////////////////////////////////// - -use std::boxed::Box; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; -use std::cell::{Ref, RefCell, RefMut}; - -impl ToHandle for RefCell { - type Handle = Ref<'static, T>; - unsafe fn to_handle(x: *const Self) -> Self::Handle { (*x).borrow() } -} - -impl ToHandleMut for RefCell { - type HandleMut = RefMut<'static, T>; - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { (*x).borrow_mut() } -} - -// NB: Implementing ToHandle{,Mut} for Mutex and RwLock requires a decision -// about which handle creation to use (i.e. read() vs try_read()) as well as -// what to do with error results. - -/// Typedef of a owning reference that uses a `Box` as the owner. -pub type BoxRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `Vec` as the owner. -pub type VecRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `String` as the owner. -pub type StringRef = OwningRef; - -/// Typedef of a owning reference that uses a `Rc` as the owner. -pub type RcRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `Arc` as the owner. -pub type ArcRef = OwningRef, U>; - -/// Typedef of a owning reference that uses a `Ref` as the owner. -pub type RefRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RefMut` as the owner. -pub type RefMutRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RwLockReadGuard` as the owner. -pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses a `Box` as the owner. -pub type BoxRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `Vec` as the owner. -pub type VecRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `String` as the owner. -pub type StringRefMut = OwningRefMut; - -/// Typedef of a mutable owning reference that uses a `RefMut` as the owner. -pub type RefMutRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef, U>; - -unsafe impl<'a, T: 'a> IntoErased<'a> for Box { - type Erased = Box; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Rc { - type Erased = Rc; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { - type Erased = Arc; - fn into_erased(self) -> Self::Erased { - self - } -} - -/// Typedef of a owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRef = OwningRef, U>; -/// Typedef of a owning reference that uses an erased `Rc` as the owner. -pub type ErasedRcRef = OwningRef, U>; -/// Typedef of a owning reference that uses an erased `Arc` as the owner. -pub type ErasedArcRef = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRefMut = OwningRefMut, U>; - -#[cfg(test)] -mod tests { - mod owning_ref { - use super::super::OwningRef; - use super::super::{RcRef, BoxRef, Erased, ErasedBoxRef}; - use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; - use std::hash::{Hash, Hasher}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::rc::Rc; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRef, ()> = OwningRef::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn into() { - let or: OwningRef, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &x.0); - assert_eq!(&*or, &42); - - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRef<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_chained() { - let or: BoxRef = Box::new(example().1).into(); - let or: BoxRef<_, str> = or.map(|x| &x[1..5]); - let or: BoxRef<_, str> = or.map(|x| &x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRef::new(Box::new(example().1)) - .map(|x| &x[..5]) - .map(|x| &x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn owner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRef = BoxRef::new(Box::new(example())) - .map(|x| &x.1[..]); - - let o2: BoxRef = BoxRef::new(Box::new(example().1)) - .map(|x| &x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn non_static_erased_owner() { - let foo = [413, 612]; - let bar = &foo; - - let o: BoxRef<&[i32; 2]> = Box::new(bar).into(); - let o: BoxRef<&[i32; 2], i32> = o.map(|a: &&[i32; 2]| &a[0]); - let o: BoxRef = o.erase_owner(); - - assert_eq!(*o, 413); - } - - #[test] - fn raii_locks() { - use super::super::{RefRef, RefMutRef}; - use std::cell::RefCell; - use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefRef::new(a.borrow()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RefCell::new(1); - let a = { - let a = RefMutRef::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRef::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockReadGuardRef::new(a.read().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRef::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key = RcRef::::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); - - hash.insert(key.clone().map(|s| &s[..3]), 42); - hash.insert(key.clone().map(|s| &s[4..]), 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRef, [u8]> - = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> - = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = unsafe {a.map_owner(Rc::new)}; - let d: OwningRef>, [u8]> = unsafe {b.map_owner(Rc::new)}; - - let e: OwningRef, [u8]> = c.erase_owner(); - let f: OwningRef, [u8]> = d.erase_owner(); - - let _g = e.clone(); - let _h = f.clone(); - } - - #[test] - fn total_erase_box() { - let a: OwningRef, [u8]> - = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> - = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = a.map_owner_box(); - let d: OwningRef>, [u8]> = b.map_owner_box(); - - let _e: OwningRef, [u8]> = c.erase_owner(); - let _f: OwningRef, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok(); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err(); - } - } - - mod owning_handle { - use super::super::OwningHandle; - use super::super::RcRef; - use std::rc::Rc; - use std::cell::RefCell; - use std::sync::Arc; - use std::sync::RwLock; - - #[test] - fn owning_handle() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_ok() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - Ok(unsafe { - x.as_ref() - }.unwrap().borrow_mut()) - }).unwrap(); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_err() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - if false { - return Ok(unsafe { - x.as_ref() - }.unwrap().borrow_mut()) - } - Err(()) - }); - assert!(handle.is_err()); - } - - #[test] - fn nested() { - use std::cell::RefCell; - use std::sync::{Arc, RwLock}; - - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - - #[test] - fn owning_handle_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::new(cell_ref); - assert_eq!(*handle, 2); - } - - #[test] - fn owning_handle_mut_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_mut(cell_ref); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn owning_handle_safe_2() { - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - } - - mod owning_ref_mut { - use super::super::{OwningRefMut, BoxRefMut, Erased, ErasedBoxRefMut}; - use super::super::BoxRef; - use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; - use std::hash::{Hash, Hasher}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn new_deref_mut() { - let mut or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&mut *or, &mut ()); - } - - #[test] - fn mutate() { - let mut or: OwningRefMut, usize> = OwningRefMut::new(Box::new(0)); - assert_eq!(&*or, &0); - *or = 1; - assert_eq!(&*or, &1); - } - - #[test] - fn into() { - let or: OwningRefMut, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_mut_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_static_ref() { - static mut MUT_S: [u8; 5] = *b"hello"; - - let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); - assert_eq!(&*or, b"hello"); - } - - #[test] - fn map_mut_chained() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..5]) - .map_mut(|x| &mut x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn try_map_mut() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); - assert_eq!(&*or.unwrap(), "ello"); - - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|_| Err(())); - assert!(or.is_err()); - } - - #[test] - fn owner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, - "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRefMut = BoxRefMut::new(Box::new(example())) - .map_mut(|x| &mut x.1[..]); - - let o2: BoxRefMut = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn non_static_erased_owner() { - let mut foo = [413, 612]; - let bar = &mut foo; - - let o: BoxRefMut<&mut [i32; 2]> = Box::new(bar).into(); - let o: BoxRefMut<&mut [i32; 2], i32> = o.map_mut(|a: &mut &mut [i32; 2]| &mut a[0]); - let o: BoxRefMut = o.erase_owner(); - - assert_eq!(*o, 413); - } - - #[test] - fn raii_locks() { - use super::super::RefMutRefMut; - use std::cell::RefCell; - use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefMutRefMut::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRefMut::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key1 = BoxRefMut::::new(Box::new("foo".to_string())).map(|s| &s[..]); - let key2 = BoxRefMut::::new(Box::new("bar".to_string())).map(|s| &s[..]); - - hash.insert(key1, 42); - hash.insert(key2, 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRefMut, [u8]> - = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> - = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = unsafe {a.map_owner(Box::new)}; - let d: OwningRefMut>, [u8]> = unsafe {b.map_owner(Box::new)}; - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn total_erase_box() { - let a: OwningRefMut, [u8]> - = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> - = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = a.map_owner_box(); - let d: OwningRefMut>, [u8]> = b.map_owner_box(); - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_ok(); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_err(); - } - - #[test] - fn try_map3() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok(); - } - - #[test] - fn try_map4() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err(); - } - - #[test] - fn into_owning_ref() { - use super::super::BoxRef; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<()> = or.into(); - assert_eq!(&*or, &()); - } - - struct Foo { - u: u32, - } - struct Bar { - f: Foo, - } - - #[test] - fn ref_mut() { - use std::cell::RefCell; - - let a = RefCell::new(Bar { f: Foo { u: 42 } }); - let mut b = OwningRefMut::new(a.borrow_mut()); - assert_eq!(b.f.u, 42); - b.f.u = 43; - let mut c = b.map_mut(|x| &mut x.f); - assert_eq!(c.u, 43); - c.u = 44; - let mut d = c.map_mut(|x| &mut x.u); - assert_eq!(*d, 44); - *d = 45; - assert_eq!(*d, 45); - } - } -} diff --git a/vendor/parking_lot/.cargo-checksum.json b/vendor/parking_lot/.cargo-checksum.json index 57e8d3e26d..bf0a89b503 100644 --- a/vendor/parking_lot/.cargo-checksum.json +++ b/vendor/parking_lot/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"f9a9c82373818d32816c42e0f127f6f14a64d37925f02041c10c66a528e0d454","Cargo.toml":"5cc50b68f3a7a4a61c78fb216a7b5e3e7426d1e3e6f55149ec4d9e35a5e27e94","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"0840b0fe8613d0336800633c48bde4352f80a97a0e85910e1e0d2914d81109cc","appveyor.yml":"a0525637948083d463186164cddbfde87c2d371029ea538a35d2b2c7129a348f","src/condvar.rs":"24cb08be64fb45323a71c8a06de0d3ef7a991f76aca8911e4d39f105003a4dbc","src/deadlock.rs":"8916c2e2820bfd3a55860ddb9f1b907888406b68cdae2b7a2093c825d28f3b99","src/elision.rs":"f55cb93d29b20d8908cde523428fec32503224e7c9ca7bf1475475bc4c1f6202","src/lib.rs":"db6f074b1c35d60116c0b13b25cce6bb497bb680d340058bb942a1427c6b4d4e","src/mutex.rs":"637590d99bf310194171e4bc2d4f23c23e9a5cbf680f383873e2106cfd1e1390","src/once.rs":"02e92cf50e4d81cb9dfc459c9742d8bc2db72f53296f28b38fa81fa1eec0fea6","src/raw_mutex.rs":"ce66c9e9abc5d6f12a1969a369dc8374854e92a33114d6c068752ce36312a562","src/raw_rwlock.rs":"0c996433cf6445fcf3071b19fba1b7d96b0d039435afdb5c6eb5bed88a37f6c2","src/remutex.rs":"b75c9e98bb82e2dec607d3b4cee54daf60f91deea454d337f85416291a6ccc96","src/rwlock.rs":"946214fca407049d5b33cda41d146478f5884bd722bbc441085af7a887922618","src/util.rs":"b69018d1cb4f02c0c4ea068e51d4dbf8a1ae1a3996c3c911a309c3dd05a2c250"},"package":"ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"} \ No newline at end of file +{"files":{"CHANGELOG.md":"d338e1af7a55941072de9e34e2537da86351b55e09f483f4214f63606f1dcad6","Cargo.toml":"d14378cc93973e6b478ee13195f149a2549791bcc61dbd26df45577e1f86cdf9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"e9af35881a3de707d5e60a15918119e88f7716a09dabe9da7960aa3191e6e7d9","appveyor.yml":"fa41673db7146f34d601a5977d77fe81fd29da706b5981cfd68ce79affd7a667","build.rs":"4ed00d73d71057bcdf6c186559468927fc130fd65cfd806ee5d46d28540bc653","src/condvar.rs":"275f05affa456117f255ccc3de3277c1174e470f307563da0d166915d4a2f68e","src/deadlock.rs":"081dbf009539b113f67ad0a1abd7af889dad684a47aa1a7dc00ae91f08975ef6","src/elision.rs":"ee8735e8695dc90ccc16002a229d5b64ba4e1c867c77f551b8715a1958faaeac","src/lib.rs":"eda1ae488e72f1d514cb7bc19600d3948cb69423a9d68738acd12565346461ec","src/mutex.rs":"e3a48933b7e19d26eab4b5f44ed4e9bcb069b57cdd4a0569d1e65f6c3839b766","src/once.rs":"155694841d62c54b8b489916f14cad887a86138000f3a6925c8d70a4a5711283","src/raw_mutex.rs":"5797de689e5c89eae2b45a4bf15bd42a01345aed0770c56f65846daee083588a","src/raw_rwlock.rs":"f13ff54a30d2fb53f95ab565db4e478f20f0a2b85b2b75f4392dc80e34f5f270","src/remutex.rs":"b62e72028b6d168650a9c3fb9375b3690225126b055a8874a7989b5f8dcb6605","src/rwlock.rs":"b0c92f2c602d13213a5e03f16ecda70dec7ea1d256cc99e4a3d6e2adad1afdd4","src/util.rs":"35f1c1930fb30fca0ceab5e0d68d8c418c7f0bb5b6ac6f21d6019986a3046cca"},"package":"f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"} \ No newline at end of file diff --git a/vendor/parking_lot/CHANGELOG.md b/vendor/parking_lot/CHANGELOG.md index ee8725180f..2090ca71be 100644 --- a/vendor/parking_lot/CHANGELOG.md +++ b/vendor/parking_lot/CHANGELOG.md @@ -1,26 +1,60 @@ -0.7.1 (2019-01-01) -================== +## parking_lot 0.9.0, parking_lot_core 0.6.0, lock_api 0.3.1 (2019-07-14) + +- The minimum supported rust version (MSRV) is now 1.32. This was primarily + increased for testing with the latest _rand_ crate. Rust 1.31 may continue to + work for normal use of these releases. +- Re-export lock_api (0.3.1) from parking_lot (#150) +- Removed (non-dev) dependency on rand crate for fairness mechanism, by + including a simple xorshift PRNG in core (#144) +- Android now uses the futex-based ThreadParker. (#140) +- Fixed CloudABI ThreadParker. (#140) +- Fix race condition in lock_api::ReentrantMutex (da16c2c7) + +## lock_api 0.3.0 (2019-07-03, _yanked_) + +- Use NonZeroUsize in GetThreadId::nonzero_thread_id (#148) +- Debug assert lock_count in ReentrantMutex (#148) +- Tag as `unsafe` and document some internal methods (#148) +- This release was _yanked_ due to a regression in ReentrantMutex (da16c2c7) + +## parking_lot 0.8.1 (2019-07-03, _yanked_) + +- Re-export lock_api (0.3.0) from parking_lot (#150) +- This release was _yanked_ from crates.io due to unexpected breakage (#156) + +## parking_lot 0.8.0, parking_lot_core 0.5.0, lock_api 0.2.0 (2019-05-04) + +- Fix race conditions in deadlock detection. +- Support for more platforms by adding ThreadParker implementations for + Wasm, Redox, SGX and CloudABI. +- Drop support for older Rust. parking_lot now requires 1.31 and is a + Rust 2018 edition crate (#122). +- Disable the owning_ref feature by default. +- Fix was_last_thread value in the timeout callback of park() (#129). +- Support single byte Mutex/Once on stable Rust when compiler is at least + version 1.34. +- Make Condvar::new and Once::new const fns on stable Rust and remove + ONCE_INIT (#134). +- Add optional Serde support (#135). + +## parking_lot 0.7.1 (2019-01-01) - Fixed potential deadlock when upgrading a RwLock. - Fixed overflow panic on very long timeouts (#111). -0.7.0 (2018-11-20) -================== +## parking_lot 0.7.0, parking_lot_core 0.4.0 (2018-11-26) - Return if or how many threads were notified from `Condvar::notify_*` -0.6.3 (2018-07-18) -================== +## parking_lot 0.6.3 (2018-07-18) - Export `RawMutex`, `RawRwLock` and `RawThreadId`. -0.6.2 (2018-06-18) -================== +## parking_lot 0.6.2 (2018-06-18) - Enable `lock_api/nightly` feature from `parking_lot/nightly` (#79) -0.6.1 (2018-06-08) -================== +## parking_lot 0.6.1 (2018-06-08) Added missing typedefs for mapped lock guards: @@ -29,16 +63,15 @@ Added missing typedefs for mapped lock guards: - `MappedRwLockReadGuard` - `MappedRwLockWriteGuard` -0.6.0 (2018-06-08) -================== +## parking_lot 0.6.0 (2018-06-08) This release moves most of the code for type-safe `Mutex` and `RwLock` types into a separate crate called `lock_api`. This new crate is compatible with -`no_std` and provides `Mutex` and `RwLock` type-safe wrapper types from a -raw mutex type which implements the `RawMutex` or `RawRwLock` trait. The API -provided by the wrapper types can be extended by implementing more traits on the -raw mutex type which provide more functionality (e.g. `RawMutexTimed`). See the -crate documentation for more details. +`no_std` and provides `Mutex` and `RwLock` type-safe wrapper types from a raw +mutex type which implements the `RawMutex` or `RawRwLock` trait. The API +provided by the wrapper types can be extended by implementing more traits on +the raw mutex type which provide more functionality (e.g. `RawMutexTimed`). See +the crate documentation for more details. There are also several major changes: diff --git a/vendor/parking_lot/Cargo.toml b/vendor/parking_lot/Cargo.toml index 19a73ca8fe..4843960c2c 100644 --- a/vendor/parking_lot/Cargo.toml +++ b/vendor/parking_lot/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,8 +11,9 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "parking_lot" -version = "0.7.1" +version = "0.9.0" authors = ["Amanieu d'Antras "] description = "More compact and efficient implementations of the standard synchronization primitives." readme = "README.md" @@ -21,15 +22,24 @@ categories = ["concurrency"] license = "Apache-2.0/MIT" repository = "https://github.com/Amanieu/parking_lot" [dependencies.lock_api] -version = "0.1" +version = "0.3.1" [dependencies.parking_lot_core] -version = "0.4" -[dev-dependencies.rand] version = "0.6" +[dev-dependencies.bincode] +version = "1.1.3" + +[dev-dependencies.lazy_static] +version = "1.0" + +[dev-dependencies.rand] +version = "0.7" +[build-dependencies.rustc_version] +version = "0.2" [features] deadlock_detection = ["parking_lot_core/deadlock_detection"] -default = ["owning_ref"] +default = [] nightly = ["parking_lot_core/nightly", "lock_api/nightly"] owning_ref = ["lock_api/owning_ref"] +serde = ["lock_api/serde"] diff --git a/vendor/parking_lot/README.md b/vendor/parking_lot/README.md index a8f339ae82..fb49272aa6 100644 --- a/vendor/parking_lot/README.md +++ b/vendor/parking_lot/README.md @@ -68,6 +68,9 @@ in the Rust standard library: can be enabled via the `deadlock_detection` feature. 17. `RwLock` supports atomically upgrading an "upgradable" read lock into a write lock. +18. Optional support for [serde](https://docs.serde.rs/serde/). Enable via the + feature `serde`. **NOTE!** this support is for `Mutex`, `ReentrantMutex`, + and `RwLock` only; `Condvar` and `Once` are not currently supported. ## The parking lot @@ -99,7 +102,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -parking_lot = "0.6" +parking_lot = "0.9" ``` and this to your crate root: @@ -112,7 +115,7 @@ To enable nightly-only features, add this to your `Cargo.toml` instead: ```toml [dependencies] -parking_lot = {version = "0.6", features = ["nightly"]} +parking_lot = {version = "0.9", features = ["nightly"]} ``` The experimental deadlock detector can be enabled with the @@ -124,7 +127,7 @@ changes to the core API do not cause breaking changes for users of `parking_lot` ## Minimum Rust version -The current minimum required Rust version is 1.24. Any change to this is +The current minimum required Rust version is 1.32. Any change to this is considered a breaking change and will require a major version bump. ## License diff --git a/vendor/parking_lot/appveyor.yml b/vendor/parking_lot/appveyor.yml index 83498db310..734a893973 100644 --- a/vendor/parking_lot/appveyor.yml +++ b/vendor/parking_lot/appveyor.yml @@ -2,28 +2,58 @@ environment: TRAVIS_CARGO_NIGHTLY_FEATURE: nightly RUST_TEST_THREADS: 1 matrix: - - TARGET: nightly-x86_64-pc-windows-msvc - - TARGET: nightly-i686-pc-windows-msvc - - TARGET: nightly-x86_64-pc-windows-gnu - - TARGET: nightly-i686-pc-windows-gnu - - TARGET: 1.24.0-x86_64-pc-windows-msvc - - TARGET: 1.24.0-i686-pc-windows-msvc - - TARGET: 1.24.0-x86_64-pc-windows-gnu - - TARGET: 1.24.0-i686-pc-windows-gnu + - TARGET: x86_64-pc-windows-msvc + MSYSTEM: MINGW64 + CPU: x86_64 + TOOLCHAIN: nightly + FEATURES: nightly + - TARGET: i686-pc-windows-msvc + MSYSTEM: MINGW32 + CPU: i686 + TOOLCHAIN: nightly + FEATURES: nightly + - TARGET: x86_64-pc-windows-gnu + MSYSTEM: MINGW64 + CPU: x86_64 + TOOLCHAIN: nightly + FEATURES: nightly + - TARGET: i686-pc-windows-gnu + MSYSTEM: MINGW32 + CPU: i686 + TOOLCHAIN: nightly + FEATURES: nightly + - TARGET: x86_64-pc-windows-msvc + MSYSTEM: MINGW64 + CPU: x86_64 + TOOLCHAIN: 1.32.0 + - TARGET: i686-pc-windows-msvc + MSYSTEM: MINGW32 + CPU: i686 + TOOLCHAIN: 1.32.0 + - TARGET: x86_64-pc-windows-gnu + MSYSTEM: MINGW64 + CPU: x86_64 + TOOLCHAIN: 1.32.0 + - TARGET: i686-pc-windows-gnu + MSYSTEM: MINGW32 + CPU: i686 + TOOLCHAIN: 1.32.0 install: - - SET PATH=C:\Python27;C:\Python27\Scripts;%PATH%;%APPDATA%\Python\Scripts - - pip install "travis-cargo<0.2" --user - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust-install.exe" - - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null - - ps: $env:PATH="$env:PATH;C:\rust\bin" + - set PATH=C:\msys64\%MSYSTEM%\bin;c:\msys64\usr\bin;%PATH% + - pacman --noconfirm -Syu mingw-w64-%CPU%-make + - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init.exe -y --default-host %TARGET% --default-toolchain %TOOLCHAIN% + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - rustc -vV - cargo -vV build_script: - - travis-cargo build + - cargo build --features "%FEATURES%" test_script: - - travis-cargo test - - travis-cargo --only nightly test -- --features=deadlock_detection - - travis-cargo doc + - cargo test --all --features "%FEATURES%" + - cargo doc --all + - cd benchmark + - cargo run --release --bin mutex -- 2 1 0 1 2 + - cargo run --release --bin rwlock -- 1 1 1 0 1 2 diff --git a/vendor/parking_lot/build.rs b/vendor/parking_lot/build.rs new file mode 100644 index 0000000000..17e76f1562 --- /dev/null +++ b/vendor/parking_lot/build.rs @@ -0,0 +1,8 @@ +use rustc_version::{version, Version}; + +fn main() { + if version().unwrap() >= Version::parse("1.34.0").unwrap() { + println!("cargo:rustc-cfg=has_sized_atomics"); + println!("cargo:rustc-cfg=has_checked_instant"); + } +} diff --git a/vendor/parking_lot/src/condvar.rs b/vendor/parking_lot/src/condvar.rs index cb85e885d4..341a5d681a 100644 --- a/vendor/parking_lot/src/condvar.rs +++ b/vendor/parking_lot/src/condvar.rs @@ -5,15 +5,16 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use deadlock; +use crate::mutex::MutexGuard; +use crate::raw_mutex::{RawMutex, TOKEN_HANDOFF, TOKEN_NORMAL}; +use crate::{deadlock, util}; +use core::{ + fmt, ptr, + sync::atomic::{AtomicPtr, Ordering}, +}; use lock_api::RawMutex as RawMutexTrait; -use mutex::MutexGuard; use parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN}; -use raw_mutex::{RawMutex, TOKEN_HANDOFF, TOKEN_NORMAL}; -use std::sync::atomic::{AtomicPtr, Ordering}; use std::time::{Duration, Instant}; -use std::{fmt, ptr}; -use util; /// A type indicating whether a timed wait on a condition variable returned /// due to a time out or not. @@ -88,22 +89,9 @@ pub struct Condvar { impl Condvar { /// Creates a new condition variable which is ready to be waited on and /// notified. - #[cfg(feature = "nightly")] #[inline] pub const fn new() -> Condvar { - Condvar { - state: AtomicPtr::new(ptr::null_mut()), - } - } - - /// Creates a new condition variable which is ready to be waited on and - /// notified. - #[cfg(not(feature = "nightly"))] - #[inline] - pub fn new() -> Condvar { - Condvar { - state: AtomicPtr::new(ptr::null_mut()), - } + Condvar { state: AtomicPtr::new(ptr::null_mut()) } } /// Wakes up one blocked thread on this condvar. @@ -141,7 +129,6 @@ impl Condvar { } #[cold] - #[inline(never)] fn notify_one_slow(&self, mutex: *mut RawMutex) -> bool { unsafe { // Unpark one thread and requeue the rest onto the mutex @@ -203,7 +190,6 @@ impl Condvar { } #[cold] - #[inline(never)] fn notify_all_slow(&self, mutex: *mut RawMutex) -> usize { unsafe { // Unpark one thread and requeue the rest onto the mutex @@ -263,7 +249,7 @@ impl Condvar { /// This function will panic if another thread is waiting on the `Condvar` /// with a different `Mutex` object. #[inline] - pub fn wait(&self, mutex_guard: &mut MutexGuard) { + pub fn wait(&self, mutex_guard: &mut MutexGuard<'_, T>) { self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, None); } @@ -293,13 +279,10 @@ impl Condvar { #[inline] pub fn wait_until( &self, - mutex_guard: &mut MutexGuard, + mutex_guard: &mut MutexGuard<'_, T>, timeout: Instant, ) -> WaitTimeoutResult { - self.wait_until_internal( - unsafe { MutexGuard::mutex(mutex_guard).raw() }, - Some(timeout), - ) + self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, Some(timeout)) } // This is a non-generic function to reduce the monomorphization cost of @@ -397,7 +380,7 @@ impl Condvar { #[inline] pub fn wait_for( &self, - mutex_guard: &mut MutexGuard, + mutex_guard: &mut MutexGuard<'_, T>, timeout: Duration, ) -> WaitTimeoutResult { let deadline = util::to_deadline(timeout); @@ -413,18 +396,18 @@ impl Default for Condvar { } impl fmt::Debug for Condvar { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Condvar { .. }") } } #[cfg(test)] mod tests { + use crate::{Condvar, Mutex, MutexGuard}; use std::sync::mpsc::channel; use std::sync::Arc; use std::thread; use std::time::{Duration, Instant}; - use {Condvar, Mutex}; #[test] fn smoke() { @@ -590,10 +573,8 @@ mod tests { let _g = m2.lock(); c2.notify_one(); }); - let timeout_res = c.wait_until( - &mut g, - Instant::now() + Duration::from_millis(u32::max_value() as u64), - ); + let timeout_res = + c.wait_until(&mut g, Instant::now() + Duration::from_millis(u32::max_value() as u64)); assert!(!timeout_res.timed_out()); drop(g); } @@ -668,10 +649,35 @@ mod tests { let mut g = m.lock(); while !c.notify_one() { // Wait for the thread to get into wait() - ::MutexGuard::bump(&mut g); + MutexGuard::bump(&mut g); } // The thread should have been requeued to the mutex, which we wake up now. drop(g); t.join().unwrap(); } + + #[test] + fn test_issue_129() { + let locks = Arc::new((Mutex::new(()), Condvar::new())); + + let (tx, rx) = channel(); + for _ in 0..4 { + let locks = locks.clone(); + let tx = tx.clone(); + thread::spawn(move || { + let mut guard = locks.0.lock(); + locks.1.wait(&mut guard); + locks.1.wait_for(&mut guard, Duration::from_millis(1)); + locks.1.notify_one(); + tx.send(()).unwrap(); + }); + } + + thread::sleep(Duration::from_millis(100)); + locks.1.notify_one(); + + for _ in 0..4 { + assert_eq!(rx.recv_timeout(Duration::from_millis(500)), Ok(())); + } + } } diff --git a/vendor/parking_lot/src/deadlock.rs b/vendor/parking_lot/src/deadlock.rs index ef7d6196f4..810edf1fde 100644 --- a/vendor/parking_lot/src/deadlock.rs +++ b/vendor/parking_lot/src/deadlock.rs @@ -40,10 +40,15 @@ pub(crate) use parking_lot_core::deadlock::{acquire_resource, release_resource}; #[cfg(test)] #[cfg(feature = "deadlock_detection")] mod tests { + use crate::{Mutex, ReentrantMutex, RwLock}; use std::sync::{Arc, Barrier}; use std::thread::{self, sleep}; use std::time::Duration; - use {Mutex, ReentrantMutex, RwLock}; + + // We need to serialize these tests since deadlock detection uses global state + lazy_static::lazy_static! { + static ref DEADLOCK_DETECTION_LOCK: Mutex<()> = Mutex::new(()); + } fn check_deadlock() -> bool { use parking_lot_core::deadlock::check_deadlock; @@ -52,6 +57,8 @@ mod tests { #[test] fn test_mutex_deadlock() { + let _guard = DEADLOCK_DETECTION_LOCK.lock(); + let m1: Arc> = Default::default(); let m2: Arc> = Default::default(); let m3: Arc> = Default::default(); @@ -95,6 +102,8 @@ mod tests { #[test] fn test_mutex_deadlock_reentrant() { + let _guard = DEADLOCK_DETECTION_LOCK.lock(); + let m1: Arc> = Default::default(); assert!(!check_deadlock()); @@ -112,6 +121,8 @@ mod tests { #[test] fn test_remutex_deadlock() { + let _guard = DEADLOCK_DETECTION_LOCK.lock(); + let m1: Arc> = Default::default(); let m2: Arc> = Default::default(); let m3: Arc> = Default::default(); @@ -158,6 +169,8 @@ mod tests { #[test] fn test_rwlock_deadlock() { + let _guard = DEADLOCK_DETECTION_LOCK.lock(); + let m1: Arc> = Default::default(); let m2: Arc> = Default::default(); let m3: Arc> = Default::default(); @@ -199,8 +212,11 @@ mod tests { assert!(!check_deadlock()); } + #[cfg(rwlock_deadlock_detection_not_supported)] #[test] fn test_rwlock_deadlock_reentrant() { + let _guard = DEADLOCK_DETECTION_LOCK.lock(); + let m1: Arc> = Default::default(); assert!(!check_deadlock()); diff --git a/vendor/parking_lot/src/elision.rs b/vendor/parking_lot/src/elision.rs index b1201ee988..10d45f9fbf 100644 --- a/vendor/parking_lot/src/elision.rs +++ b/vendor/parking_lot/src/elision.rs @@ -12,26 +12,20 @@ pub trait AtomicElisionExt { type IntType; // Perform a compare_exchange and start a transaction - fn elision_acquire( - &self, - current: Self::IntType, - new: Self::IntType, - ) -> Result; - // Perform a compare_exchange and end a transaction - fn elision_release( + fn elision_compare_exchange_acquire( &self, current: Self::IntType, new: Self::IntType, ) -> Result; + + // Perform a fetch_sub and end a transaction + fn elision_fetch_sub_release(&self, val: Self::IntType) -> Self::IntType; } // Indicates whether the target architecture supports lock elision #[inline] pub fn have_elision() -> bool { - cfg!(all( - feature = "nightly", - any(target_arch = "x86", target_arch = "x86_64"), - )) + cfg!(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"),)) } // This implementation is never actually called because it is guarded by @@ -41,22 +35,23 @@ impl AtomicElisionExt for AtomicUsize { type IntType = usize; #[inline] - fn elision_acquire(&self, _: usize, _: usize) -> Result { + fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result { unreachable!(); } #[inline] - fn elision_release(&self, _: usize, _: usize) -> Result { + fn elision_fetch_sub_release(&self, _: usize) -> usize { unreachable!(); } } -#[cfg(all(feature = "nightly", target_arch = "x86"))] +#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; + #[cfg(target_pointer_width = "32")] #[inline] - fn elision_acquire(&self, current: usize, new: usize) -> Result { + fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result { unsafe { let prev: usize; asm!("xacquire; lock; cmpxchgl $2, $1" @@ -64,114 +59,47 @@ impl AtomicElisionExt for AtomicUsize { : "r" (new), "{eax}" (current) : "memory" : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } - } - } - - #[inline] - fn elision_release(&self, current: usize, new: usize) -> Result { - unsafe { - let prev: usize; - asm!("xrelease; lock; cmpxchgl $2, $1" - : "={eax}" (prev), "+*m" (self) - : "r" (new), "{eax}" (current) - : "memory" - : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } - } - } -} - -#[cfg(all( - feature = "nightly", - target_arch = "x86_64", - target_pointer_width = "32" -))] -impl AtomicElisionExt for AtomicUsize { - type IntType = usize; - - #[inline] - fn elision_acquire(&self, current: usize, new: usize) -> Result { - unsafe { - let prev: usize; - asm!("xacquire; lock; cmpxchgl $2, $1" - : "={rax}" (prev), "+*m" (self) - : "r" (new), "{rax}" (current) - : "memory" - : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } + if prev == current { Ok(prev) } else { Err(prev) } } } - + #[cfg(target_pointer_width = "64")] #[inline] - fn elision_release(&self, current: usize, new: usize) -> Result { + fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result { unsafe { let prev: usize; - asm!("xrelease; lock; cmpxchgl $2, $1" + asm!("xacquire; lock; cmpxchgq $2, $1" : "={rax}" (prev), "+*m" (self) : "r" (new), "{rax}" (current) : "memory" : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } + if prev == current { Ok(prev) } else { Err(prev) } } } -} - -#[cfg(all( - feature = "nightly", - target_arch = "x86_64", - target_pointer_width = "64" -))] -impl AtomicElisionExt for AtomicUsize { - type IntType = usize; + #[cfg(target_pointer_width = "32")] #[inline] - fn elision_acquire(&self, current: usize, new: usize) -> Result { + fn elision_fetch_sub_release(&self, val: usize) -> usize { unsafe { let prev: usize; - asm!("xacquire; lock; cmpxchgq $2, $1" - : "={rax}" (prev), "+*m" (self) - : "r" (new), "{rax}" (current) + asm!("xrelease; lock; xaddl $2, $1" + : "=r" (prev), "+*m" (self) + : "0" (val.wrapping_neg()) : "memory" : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } + prev } } - + #[cfg(target_pointer_width = "64")] #[inline] - fn elision_release(&self, current: usize, new: usize) -> Result { + fn elision_fetch_sub_release(&self, val: usize) -> usize { unsafe { let prev: usize; - asm!("xrelease; lock; cmpxchgq $2, $1" - : "={rax}" (prev), "+*m" (self) - : "r" (new), "{rax}" (current) + asm!("xrelease; lock; xaddq $2, $1" + : "=r" (prev), "+*m" (self) + : "0" (val.wrapping_neg()) : "memory" : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } + prev } } } diff --git a/vendor/parking_lot/src/lib.rs b/vendor/parking_lot/src/lib.rs index e8cd726e72..6272a9a731 100644 --- a/vendor/parking_lot/src/lib.rs +++ b/vendor/parking_lot/src/lib.rs @@ -10,13 +10,8 @@ //! standard library. It also provides a `ReentrantMutex` type. #![warn(missing_docs)] -#![cfg_attr(feature = "nightly", feature(const_fn))] -#![cfg_attr(feature = "nightly", feature(integer_atomics))] +#![warn(rust_2018_idioms)] #![cfg_attr(feature = "nightly", feature(asm))] -#![cfg_attr(feature = "nightly", feature(time_checked_add))] - -extern crate lock_api; -extern crate parking_lot_core; mod condvar; mod elision; @@ -33,13 +28,16 @@ pub mod deadlock; #[cfg(not(feature = "deadlock_detection"))] mod deadlock; -pub use condvar::{Condvar, WaitTimeoutResult}; -pub use mutex::{MappedMutexGuard, Mutex, MutexGuard}; -pub use once::{Once, OnceState, ONCE_INIT}; -pub use raw_mutex::RawMutex; -pub use raw_rwlock::RawRwLock; -pub use remutex::{MappedReentrantMutexGuard, RawThreadId, ReentrantMutex, ReentrantMutexGuard}; -pub use rwlock::{ +pub use ::lock_api as lock_api; +pub use self::condvar::{Condvar, WaitTimeoutResult}; +pub use self::mutex::{MappedMutexGuard, Mutex, MutexGuard}; +pub use self::once::{Once, OnceState}; +pub use self::raw_mutex::RawMutex; +pub use self::raw_rwlock::RawRwLock; +pub use self::remutex::{ + MappedReentrantMutexGuard, RawThreadId, ReentrantMutex, ReentrantMutexGuard, +}; +pub use self::rwlock::{ MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard, }; diff --git a/vendor/parking_lot/src/mutex.rs b/vendor/parking_lot/src/mutex.rs index 0e26570a82..4f88e58362 100644 --- a/vendor/parking_lot/src/mutex.rs +++ b/vendor/parking_lot/src/mutex.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use crate::raw_mutex::RawMutex; use lock_api; -use raw_mutex::RawMutex; /// A mutual exclusion primitive useful for protecting shared data /// @@ -69,7 +69,7 @@ use raw_mutex::RawMutex; /// /// let (tx, rx) = channel(); /// for _ in 0..10 { -/// let (data, tx) = (data.clone(), tx.clone()); +/// let (data, tx) = (Arc::clone(&data), tx.clone()); /// thread::spawn(move || { /// // The shared state can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread @@ -105,11 +105,14 @@ pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>; #[cfg(test)] mod tests { + use crate::{Condvar, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; use std::sync::Arc; use std::thread; - use {Condvar, Mutex}; + + #[cfg(feature = "serde")] + use bincode::{deserialize, serialize}; struct Packet(Arc<(Mutex, Condvar)>); @@ -284,16 +287,20 @@ mod tests { let mutex = Mutex::new(vec![0u8, 10]); assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }"); - assert_eq!( - format!("{:#?}", mutex), - "Mutex { - data: [ - 0, - 10 - ] -}" - ); let _lock = mutex.lock(); - assert_eq!(format!("{:?}", mutex), "Mutex { }"); + assert_eq!(format!("{:?}", mutex), "Mutex { data: }"); + } + + #[cfg(feature = "serde")] + #[test] + fn test_serde() { + let contents: Vec = vec![0, 1, 2]; + let mutex = Mutex::new(contents.clone()); + + let serialized = serialize(&mutex).unwrap(); + let deserialized: Mutex> = deserialize(&serialized).unwrap(); + + assert_eq!(*(mutex.lock()), *(deserialized.lock())); + assert_eq!(contents, *(deserialized.lock())); } } diff --git a/vendor/parking_lot/src/once.rs b/vendor/parking_lot/src/once.rs index 33b7572ab2..fa7c1c1b60 100644 --- a/vendor/parking_lot/src/once.rs +++ b/vendor/parking_lot/src/once.rs @@ -5,21 +5,21 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::sync::atomic::{fence, Ordering}; -#[cfg(feature = "nightly")] -use std::sync::atomic::{AtomicU8, ATOMIC_U8_INIT}; -#[cfg(feature = "nightly")] +use crate::util::UncheckedOptionExt; +#[cfg(has_sized_atomics)] +use core::sync::atomic::AtomicU8; +#[cfg(not(has_sized_atomics))] +use core::sync::atomic::AtomicUsize as AtomicU8; +use core::{ + fmt, mem, + sync::atomic::{fence, Ordering}, +}; +use parking_lot_core::{self, SpinWait, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; + +#[cfg(has_sized_atomics)] type U8 = u8; -#[cfg(not(feature = "nightly"))] -use std::sync::atomic::AtomicUsize as AtomicU8; -#[cfg(not(feature = "nightly"))] -use std::sync::atomic::ATOMIC_USIZE_INIT as ATOMIC_U8_INIT; -#[cfg(not(feature = "nightly"))] +#[cfg(not(has_sized_atomics))] type U8 = usize; -use parking_lot_core::{self, SpinWait, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; -use std::fmt; -use std::mem; -use util::UncheckedOptionExt; const DONE_BIT: U8 = 1; const POISON_BIT: U8 = 2; @@ -81,9 +81,9 @@ impl OnceState { /// # Examples /// /// ``` -/// use parking_lot::{Once, ONCE_INIT}; +/// use parking_lot::Once; /// -/// static START: Once = ONCE_INIT; +/// static START: Once = Once::new(); /// /// START.call_once(|| { /// // run initialization here @@ -91,22 +91,11 @@ impl OnceState { /// ``` pub struct Once(AtomicU8); -/// Initialization value for static `Once` values. -pub const ONCE_INIT: Once = Once(ATOMIC_U8_INIT); - impl Once { /// Creates a new `Once` value. - #[cfg(feature = "nightly")] #[inline] pub const fn new() -> Once { - Once(ATOMIC_U8_INIT) - } - - /// Creates a new `Once` value. - #[cfg(not(feature = "nightly"))] - #[inline] - pub fn new() -> Once { - Once(ATOMIC_U8_INIT) + Once(AtomicU8::new(0)) } /// Returns the current state of this `Once`. @@ -141,10 +130,10 @@ impl Once { /// # Examples /// /// ``` - /// use parking_lot::{Once, ONCE_INIT}; + /// use parking_lot::Once; /// /// static mut VAL: usize = 0; - /// static INIT: Once = ONCE_INIT; + /// static INIT: Once = Once::new(); /// /// // Accessing a `static mut` is unsafe much of the time, but if we do so /// // in a synchronized fashion (e.g. write once or read all) then we're @@ -205,9 +194,7 @@ impl Once { } let mut f = Some(f); - self.call_once_slow(true, &mut |state| unsafe { - f.take().unchecked_unwrap()(state) - }); + self.call_once_slow(true, &mut |state| unsafe { f.take().unchecked_unwrap()(state) }); } // This is a non-generic function to reduce the monomorphization cost of @@ -222,8 +209,7 @@ impl Once { // currently no way to take an `FnOnce` and call it via virtual dispatch // without some allocation overhead. #[cold] - #[inline(never)] - fn call_once_slow(&self, ignore_poison: bool, f: &mut FnMut(OnceState)) { + fn call_once_slow(&self, ignore_poison: bool, f: &mut dyn FnMut(OnceState)) { let mut spinwait = SpinWait::new(); let mut state = self.0.load(Ordering::Relaxed); loop { @@ -317,11 +303,7 @@ impl Once { // At this point we have the lock, so run the closure. Make sure we // properly clean up if the closure panicks. let guard = PanicGuard(self); - let once_state = if state & POISON_BIT != 0 { - OnceState::Poisoned - } else { - OnceState::New - }; + let once_state = if state & POISON_BIT != 0 { OnceState::Poisoned } else { OnceState::New }; f(once_state); mem::forget(guard); @@ -344,24 +326,21 @@ impl Default for Once { } impl fmt::Debug for Once { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Once") - .field("state", &self.state()) - .finish() + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Once").field("state", &self.state()).finish() } } #[cfg(test)] mod tests { - #[cfg(feature = "nightly")] + use crate::Once; use std::panic; use std::sync::mpsc::channel; use std::thread; - use {Once, ONCE_INIT}; #[test] fn smoke_once() { - static O: Once = ONCE_INIT; + static O: Once = Once::new(); let mut a = 0; O.call_once(|| a += 1); assert_eq!(a, 1); @@ -371,7 +350,7 @@ mod tests { #[test] fn stampede_once() { - static O: Once = ONCE_INIT; + static O: Once = Once::new(); static mut RUN: bool = false; let (tx, rx) = channel(); @@ -405,10 +384,9 @@ mod tests { } } - #[cfg(feature = "nightly")] #[test] fn poison_bad() { - static O: Once = ONCE_INIT; + static O: Once = Once::new(); // poison the once let t = panic::catch_unwind(|| { @@ -434,10 +412,9 @@ mod tests { O.call_once(|| {}); } - #[cfg(feature = "nightly")] #[test] fn wait_for_force_to_finish() { - static O: Once = ONCE_INIT; + static O: Once = Once::new(); // poison the once let t = panic::catch_unwind(|| { @@ -475,14 +452,8 @@ mod tests { #[test] fn test_once_debug() { - static O: Once = ONCE_INIT; + static O: Once = Once::new(); assert_eq!(format!("{:?}", O), "Once { state: New }"); - assert_eq!( - format!("{:#?}", O), - "Once { - state: New -}" - ); } } diff --git a/vendor/parking_lot/src/raw_mutex.rs b/vendor/parking_lot/src/raw_mutex.rs index 4b5f7625a5..5d0933e575 100644 --- a/vendor/parking_lot/src/raw_mutex.rs +++ b/vendor/parking_lot/src/raw_mutex.rs @@ -5,22 +5,20 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::sync::atomic::Ordering; -#[cfg(feature = "nightly")] -use std::sync::atomic::{AtomicU8, ATOMIC_U8_INIT}; -#[cfg(feature = "nightly")] -type U8 = u8; -#[cfg(not(feature = "nightly"))] -use std::sync::atomic::AtomicUsize as AtomicU8; -#[cfg(not(feature = "nightly"))] -use std::sync::atomic::ATOMIC_USIZE_INIT as ATOMIC_U8_INIT; -#[cfg(not(feature = "nightly"))] -type U8 = usize; -use deadlock; +use crate::{deadlock, util}; +#[cfg(has_sized_atomics)] +use core::sync::atomic::AtomicU8; +#[cfg(not(has_sized_atomics))] +use core::sync::atomic::AtomicUsize as AtomicU8; +use core::{sync::atomic::Ordering, time::Duration}; use lock_api::{GuardNoSend, RawMutex as RawMutexTrait, RawMutexFair, RawMutexTimed}; use parking_lot_core::{self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN}; -use std::time::{Duration, Instant}; -use util; +use std::time::Instant; + +#[cfg(has_sized_atomics)] +type U8 = u8; +#[cfg(not(has_sized_atomics))] +type U8 = usize; // UnparkToken used to indicate that that the target thread should attempt to // lock the mutex again as soon as it is unparked. @@ -39,9 +37,7 @@ pub struct RawMutex { } unsafe impl RawMutexTrait for RawMutex { - const INIT: RawMutex = RawMutex { - state: ATOMIC_U8_INIT, - }; + const INIT: RawMutex = RawMutex { state: AtomicU8::new(0) }; type GuardMarker = GuardNoSend; @@ -82,10 +78,7 @@ unsafe impl RawMutexTrait for RawMutex { #[inline] fn unlock(&self) { unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() + if self.state.compare_exchange(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed).is_ok() { return; } @@ -97,10 +90,7 @@ unsafe impl RawMutexFair for RawMutex { #[inline] fn unlock_fair(&self) { unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() + if self.state.compare_exchange(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed).is_ok() { return; } @@ -184,7 +174,6 @@ impl RawMutex { } #[cold] - #[inline(never)] fn lock_slow(&self, timeout: Option) -> bool { let mut spinwait = SpinWait::new(); let mut state = self.state.load(Ordering::Relaxed); @@ -263,17 +252,7 @@ impl RawMutex { } #[cold] - #[inline(never)] fn unlock_slow(&self, force_fair: bool) { - // Unlock directly if there are no parked threads - if self - .state - .compare_exchange(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - return; - } - // Unpark one thread and leave the parked bit set if there might // still be parked threads on this address. unsafe { @@ -304,7 +283,6 @@ impl RawMutex { } #[cold] - #[inline(never)] fn bump_slow(&self) { unsafe { deadlock::release_resource(self as *const _ as usize) }; self.unlock_slow(true); diff --git a/vendor/parking_lot/src/raw_rwlock.rs b/vendor/parking_lot/src/raw_rwlock.rs index de700669f1..afe0c4a052 100644 --- a/vendor/parking_lot/src/raw_rwlock.rs +++ b/vendor/parking_lot/src/raw_rwlock.rs @@ -5,38 +5,55 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use deadlock; -use elision::{have_elision, AtomicElisionExt}; +use crate::elision::{have_elision, AtomicElisionExt}; +use crate::raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL}; +use crate::util; +use core::{ + cell::Cell, + sync::atomic::{AtomicUsize, Ordering}, +}; use lock_api::{ GuardNoSend, RawRwLock as RawRwLockTrait, RawRwLockDowngrade, RawRwLockFair, RawRwLockRecursive, RawRwLockRecursiveTimed, RawRwLockTimed, RawRwLockUpgrade, RawRwLockUpgradeDowngrade, RawRwLockUpgradeFair, RawRwLockUpgradeTimed, }; -use parking_lot_core::{self, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult}; -use raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL}; -use std::cell::Cell; -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; +use parking_lot_core::{ + self, deadlock, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult, UnparkToken, +}; use std::time::{Duration, Instant}; -use util; - -const PARKED_BIT: usize = 0b001; -const UPGRADING_BIT: usize = 0b010; -// A shared guard acquires a single guard resource -const SHARED_GUARD: usize = 0b100; -const GUARD_COUNT_MASK: usize = !(SHARED_GUARD - 1); -// An exclusive lock acquires all of guard resource (i.e. it is exclusive) -const EXCLUSIVE_GUARD: usize = GUARD_COUNT_MASK; -// An upgradable lock acquires just over half of the guard resource -// This should be (GUARD_COUNT_MASK + SHARED_GUARD) >> 1, however this might -// overflow, so we shift before adding (which is okay since the least -// significant bit is zero for both GUARD_COUNT_MASK and SHARED_GUARD) -const UPGRADABLE_GUARD: usize = (GUARD_COUNT_MASK >> 1) + (SHARED_GUARD >> 1); - -// Token indicating what type of lock queued threads are trying to acquire -const TOKEN_SHARED: ParkToken = ParkToken(SHARED_GUARD); -const TOKEN_EXCLUSIVE: ParkToken = ParkToken(EXCLUSIVE_GUARD); -const TOKEN_UPGRADABLE: ParkToken = ParkToken(UPGRADABLE_GUARD); -const TOKEN_UPGRADING: ParkToken = ParkToken((EXCLUSIVE_GUARD - UPGRADABLE_GUARD) | UPGRADING_BIT); + +// This reader-writer lock implementation is based on Boost's upgrade_mutex: +// https://github.com/boostorg/thread/blob/fc08c1fe2840baeeee143440fba31ef9e9a813c8/include/boost/thread/v2/shared_mutex.hpp#L432 +// +// This implementation uses 2 wait queues, one at key [addr] and one at key +// [addr + 1]. The primary queue is used for all new waiting threads, and the +// secondary queue is used by the thread which has acquired WRITER_BIT but is +// waiting for the remaining readers to exit the lock. +// +// This implementation is fair between readers and writers since it uses the +// order in which threads first started queuing to alternate between read phases +// and write phases. In particular is it not vulnerable to write starvation +// since readers will block if there is a pending writer. + +// There is at least one thread in the main queue. +const PARKED_BIT: usize = 0b0001; +// There is a parked thread holding WRITER_BIT. WRITER_BIT must be set. +const WRITER_PARKED_BIT: usize = 0b0010; +// A reader is holding an upgradable lock. The reader count must be non-zero and +// WRITER_BIT must not be set. +const UPGRADABLE_BIT: usize = 0b0100; +// If the reader count is zero: a writer is currently holding an exclusive lock. +// Otherwise: a writer is waiting for the remaining readers to exit the lock. +const WRITER_BIT: usize = 0b1000; +// Mask of bits used to count readers. +const READERS_MASK: usize = !0b1111; +// Base unit for counting readers. +const ONE_READER: usize = 0b10000; + +// Token indicating what type of lock a queued thread is trying to acquire +const TOKEN_SHARED: ParkToken = ParkToken(ONE_READER); +const TOKEN_EXCLUSIVE: ParkToken = ParkToken(WRITER_BIT); +const TOKEN_UPGRADABLE: ParkToken = ParkToken(ONE_READER | UPGRADABLE_BIT); /// Raw reader-writer lock type backed by the parking lot. pub struct RawRwLock { @@ -44,9 +61,7 @@ pub struct RawRwLock { } unsafe impl RawRwLockTrait for RawRwLock { - const INIT: RawRwLock = RawRwLock { - state: ATOMIC_USIZE_INIT, - }; + const INIT: RawRwLock = RawRwLock { state: AtomicUsize::new(0) }; type GuardMarker = GuardNoSend; @@ -54,23 +69,20 @@ unsafe impl RawRwLockTrait for RawRwLock { fn lock_exclusive(&self) { if self .state - .compare_exchange_weak(0, EXCLUSIVE_GUARD, Ordering::Acquire, Ordering::Relaxed) + .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed) .is_err() { let result = self.lock_exclusive_slow(None); debug_assert!(result); } - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } #[inline] fn try_lock_exclusive(&self) -> bool { - if self - .state - .compare_exchange(0, EXCLUSIVE_GUARD, Ordering::Acquire, Ordering::Relaxed) - .is_ok() + if self.state.compare_exchange(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed).is_ok() { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); true } else { false @@ -79,11 +91,8 @@ unsafe impl RawRwLockTrait for RawRwLock { #[inline] fn unlock_exclusive(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(EXCLUSIVE_GUARD, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() + self.deadlock_release(); + if self.state.compare_exchange(WRITER_BIT, 0, Ordering::Release, Ordering::Relaxed).is_ok() { return; } @@ -96,97 +105,44 @@ unsafe impl RawRwLockTrait for RawRwLock { let result = self.lock_shared_slow(false, None); debug_assert!(result); } - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } #[inline] fn try_lock_shared(&self) -> bool { - let result = if self.try_lock_shared_fast(false) { - true - } else { - self.try_lock_shared_slow(false) - }; + let result = + if self.try_lock_shared_fast(false) { true } else { self.try_lock_shared_slow(false) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } #[inline] fn unlock_shared(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - let state = self.state.load(Ordering::Relaxed); - if state & PARKED_BIT == 0 - || (state & UPGRADING_BIT == 0 && state & GUARD_COUNT_MASK != SHARED_GUARD) - { - if have_elision() { - if self - .state - .elision_release(state, state - SHARED_GUARD) - .is_ok() - { - return; - } - } else { - if self - .state - .compare_exchange_weak( - state, - state - SHARED_GUARD, - Ordering::Release, - Ordering::Relaxed, - ) - .is_ok() - { - return; - } - } + self.deadlock_release(); + let state = if have_elision() { + self.state.elision_fetch_sub_release(ONE_READER) + } else { + self.state.fetch_sub(ONE_READER, Ordering::Release) + }; + if state & (READERS_MASK | WRITER_PARKED_BIT) == (ONE_READER | WRITER_PARKED_BIT) { + self.unlock_shared_slow(); } - self.unlock_shared_slow(false); } } unsafe impl RawRwLockFair for RawRwLock { #[inline] fn unlock_shared_fair(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - let state = self.state.load(Ordering::Relaxed); - if state & PARKED_BIT == 0 - || (state & UPGRADING_BIT == 0 && state & GUARD_COUNT_MASK != SHARED_GUARD) - { - if have_elision() { - if self - .state - .elision_release(state, state - SHARED_GUARD) - .is_ok() - { - return; - } - } else { - if self - .state - .compare_exchange_weak( - state, - state - SHARED_GUARD, - Ordering::Release, - Ordering::Relaxed, - ) - .is_ok() - { - return; - } - } - } - self.unlock_shared_slow(true); + // Shared unlocking is always fair in this implementation. + self.unlock_shared(); } #[inline] fn unlock_exclusive_fair(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(EXCLUSIVE_GUARD, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() + self.deadlock_release(); + if self.state.compare_exchange(WRITER_BIT, 0, Ordering::Release, Ordering::Relaxed).is_ok() { return; } @@ -195,7 +151,9 @@ unsafe impl RawRwLockFair for RawRwLock { #[inline] fn bump_shared(&self) { - if self.state.load(Ordering::Relaxed) & PARKED_BIT != 0 { + if self.state.load(Ordering::Relaxed) & (READERS_MASK | WRITER_BIT) + == ONE_READER | WRITER_BIT + { self.bump_shared_slow(); } } @@ -211,9 +169,7 @@ unsafe impl RawRwLockFair for RawRwLock { unsafe impl RawRwLockDowngrade for RawRwLock { #[inline] fn downgrade(&self) { - let state = self - .state - .fetch_sub(EXCLUSIVE_GUARD - SHARED_GUARD, Ordering::Release); + let state = self.state.fetch_add(ONE_READER - WRITER_BIT, Ordering::Release); // Wake up parked shared and upgradable threads if there are any if state & PARKED_BIT != 0 { @@ -234,7 +190,7 @@ unsafe impl RawRwLockTimed for RawRwLock { self.lock_shared_slow(false, util::to_deadline(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -247,7 +203,7 @@ unsafe impl RawRwLockTimed for RawRwLock { self.lock_shared_slow(false, Some(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -256,7 +212,7 @@ unsafe impl RawRwLockTimed for RawRwLock { fn try_lock_exclusive_for(&self, timeout: Duration) -> bool { let result = if self .state - .compare_exchange_weak(0, EXCLUSIVE_GUARD, Ordering::Acquire, Ordering::Relaxed) + .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed) .is_ok() { true @@ -264,7 +220,7 @@ unsafe impl RawRwLockTimed for RawRwLock { self.lock_exclusive_slow(util::to_deadline(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -273,7 +229,7 @@ unsafe impl RawRwLockTimed for RawRwLock { fn try_lock_exclusive_until(&self, timeout: Instant) -> bool { let result = if self .state - .compare_exchange_weak(0, EXCLUSIVE_GUARD, Ordering::Acquire, Ordering::Relaxed) + .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed) .is_ok() { true @@ -281,7 +237,7 @@ unsafe impl RawRwLockTimed for RawRwLock { self.lock_exclusive_slow(Some(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -294,18 +250,15 @@ unsafe impl RawRwLockRecursive for RawRwLock { let result = self.lock_shared_slow(true, None); debug_assert!(result); } - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } #[inline] fn try_lock_shared_recursive(&self) -> bool { - let result = if self.try_lock_shared_fast(true) { - true - } else { - self.try_lock_shared_slow(true) - }; + let result = + if self.try_lock_shared_fast(true) { true } else { self.try_lock_shared_slow(true) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -320,7 +273,7 @@ unsafe impl RawRwLockRecursiveTimed for RawRwLock { self.lock_shared_slow(true, util::to_deadline(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -333,7 +286,7 @@ unsafe impl RawRwLockRecursiveTimed for RawRwLock { self.lock_shared_slow(true, Some(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -346,58 +299,57 @@ unsafe impl RawRwLockUpgrade for RawRwLock { let result = self.lock_upgradable_slow(None); debug_assert!(result); } - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } #[inline] fn try_lock_upgradable(&self) -> bool { - let result = if self.try_lock_upgradable_fast() { - true - } else { - self.try_lock_upgradable_slow() - }; + let result = + if self.try_lock_upgradable_fast() { true } else { self.try_lock_upgradable_slow() }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } #[inline] fn unlock_upgradable(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(UPGRADABLE_GUARD, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - return; + self.deadlock_release(); + let state = self.state.load(Ordering::Relaxed); + if state & PARKED_BIT == 0 { + if self + .state + .compare_exchange_weak( + state, + state - (ONE_READER | UPGRADABLE_BIT), + Ordering::Release, + Ordering::Relaxed, + ) + .is_ok() + { + return; + } } self.unlock_upgradable_slow(false); } #[inline] fn upgrade(&self) { - if self - .state - .compare_exchange_weak( - UPGRADABLE_GUARD, - EXCLUSIVE_GUARD, - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_err() - { + let state = + self.state.fetch_sub((ONE_READER | UPGRADABLE_BIT) - WRITER_BIT, Ordering::Relaxed); + if state & READERS_MASK != ONE_READER { let result = self.upgrade_slow(None); debug_assert!(result); } } + #[inline] fn try_upgrade(&self) -> bool { if self .state .compare_exchange_weak( - UPGRADABLE_GUARD, - EXCLUSIVE_GUARD, + ONE_READER | UPGRADABLE_BIT, + WRITER_BIT, Ordering::Relaxed, Ordering::Relaxed, ) @@ -413,20 +365,28 @@ unsafe impl RawRwLockUpgrade for RawRwLock { unsafe impl RawRwLockUpgradeFair for RawRwLock { #[inline] fn unlock_upgradable_fair(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - if self - .state - .compare_exchange_weak(UPGRADABLE_GUARD, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - return; + self.deadlock_release(); + let state = self.state.load(Ordering::Relaxed); + if state & PARKED_BIT == 0 { + if self + .state + .compare_exchange_weak( + state, + state - (ONE_READER | UPGRADABLE_BIT), + Ordering::Release, + Ordering::Relaxed, + ) + .is_ok() + { + return; + } } - self.unlock_upgradable_slow(true); + self.unlock_upgradable_slow(false); } #[inline] fn bump_upgradable(&self) { - if self.state.load(Ordering::Relaxed) & PARKED_BIT != 0 { + if self.state.load(Ordering::Relaxed) == ONE_READER | UPGRADABLE_BIT | PARKED_BIT { self.bump_upgradable_slow(); } } @@ -435,21 +395,18 @@ unsafe impl RawRwLockUpgradeFair for RawRwLock { unsafe impl RawRwLockUpgradeDowngrade for RawRwLock { #[inline] fn downgrade_upgradable(&self) { - let state = self - .state - .fetch_sub(UPGRADABLE_GUARD - SHARED_GUARD, Ordering::Relaxed); + let state = self.state.fetch_sub(UPGRADABLE_BIT, Ordering::Relaxed); - // Wake up parked shared and upgradable threads if there are any + // Wake up parked upgradable threads if there are any if state & PARKED_BIT != 0 { - self.downgrade_upgradable_slow(state); + self.downgrade_slow(); } } #[inline] fn downgrade_to_upgradable(&self) { - let state = self - .state - .fetch_sub(EXCLUSIVE_GUARD - UPGRADABLE_GUARD, Ordering::Release); + let state = + self.state.fetch_add((ONE_READER | UPGRADABLE_BIT) - WRITER_BIT, Ordering::Release); // Wake up parked shared threads if there are any if state & PARKED_BIT != 0 { @@ -467,7 +424,7 @@ unsafe impl RawRwLockUpgradeTimed for RawRwLock { self.lock_upgradable_slow(Some(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } @@ -480,41 +437,23 @@ unsafe impl RawRwLockUpgradeTimed for RawRwLock { self.lock_upgradable_slow(util::to_deadline(timeout)) }; if result { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + self.deadlock_acquire(); } result } #[inline] fn try_upgrade_until(&self, timeout: Instant) -> bool { - if self - .state - .compare_exchange_weak( - UPGRADABLE_GUARD, - EXCLUSIVE_GUARD, - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_ok() - { - true - } else { - self.upgrade_slow(Some(timeout)) - } + let state = + self.state.fetch_sub((ONE_READER | UPGRADABLE_BIT) - WRITER_BIT, Ordering::Relaxed); + if state & READERS_MASK == ONE_READER { true } else { self.upgrade_slow(Some(timeout)) } } #[inline] fn try_upgrade_for(&self, timeout: Duration) -> bool { - if self - .state - .compare_exchange_weak( - UPGRADABLE_GUARD, - EXCLUSIVE_GUARD, - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_ok() - { + let state = + self.state.fetch_sub((ONE_READER | UPGRADABLE_BIT) - WRITER_BIT, Ordering::Relaxed); + if state & READERS_MASK == ONE_READER { true } else { self.upgrade_slow(util::to_deadline(timeout)) @@ -527,18 +466,23 @@ impl RawRwLock { fn try_lock_shared_fast(&self, recursive: bool) -> bool { let state = self.state.load(Ordering::Relaxed); - // We can't allow grabbing a shared lock while there are parked threads - // since that could lead to writer starvation. - if !recursive && state & PARKED_BIT != 0 { - return false; + // We can't allow grabbing a shared lock if there is a writer, even if + // the writer is still waiting for the remaining readers to exit. + if state & WRITER_BIT != 0 { + // To allow recursive locks, we make an exception and allow readers + // to skip ahead of a pending writer to avoid deadlocking, at the + // cost of breaking the fairness guarantees. + if !recursive || state & READERS_MASK == 0 { + return false; + } } // Use hardware lock elision to avoid cache conflicts when multiple // readers try to acquire the lock. We only do this if the lock is // completely empty since elision handles conflicts poorly. if have_elision() && state == 0 { - self.state.elision_acquire(0, SHARED_GUARD).is_ok() - } else if let Some(new_state) = state.checked_add(SHARED_GUARD) { + self.state.elision_compare_exchange_acquire(0, ONE_READER).is_ok() + } else if let Some(new_state) = state.checked_add(ONE_READER) { self.state .compare_exchange_weak(state, new_state, Ordering::Acquire, Ordering::Relaxed) .is_ok() @@ -547,17 +491,46 @@ impl RawRwLock { } } + #[cold] + fn try_lock_shared_slow(&self, recursive: bool) -> bool { + let mut state = self.state.load(Ordering::Relaxed); + loop { + // This mirrors the condition in try_lock_shared_fast + if state & WRITER_BIT != 0 { + if !recursive || state & READERS_MASK == 0 { + return false; + } + } + if have_elision() && state == 0 { + match self.state.elision_compare_exchange_acquire(0, ONE_READER) { + Ok(_) => return true, + Err(x) => state = x, + } + } else { + match self.state.compare_exchange_weak( + state, + state.checked_add(ONE_READER).expect("RwLock reader count overflow"), + Ordering::Acquire, + Ordering::Relaxed, + ) { + Ok(_) => return true, + Err(x) => state = x, + } + } + } + } + #[inline(always)] fn try_lock_upgradable_fast(&self) -> bool { let state = self.state.load(Ordering::Relaxed); - // We can't allow grabbing an upgradable lock while there are parked threads - // since that could lead to writer starvation. - if state & PARKED_BIT != 0 { + // We can't grab an upgradable lock if there is already a writer or + // upgradable reader. + if state & (WRITER_BIT | UPGRADABLE_BIT) != 0 { return false; } - if let Some(new_state) = state.checked_add(UPGRADABLE_GUARD) { + if let Some(new_state) = state.checked_add(ONE_READER | UPGRADABLE_BIT) { self.state .compare_exchange_weak(state, new_state, Ordering::Acquire, Ordering::Relaxed) .is_ok() @@ -567,232 +540,117 @@ impl RawRwLock { } #[cold] - #[inline(never)] - fn lock_exclusive_slow(&self, timeout: Option) -> bool { - let mut spinwait = SpinWait::new(); + fn try_lock_upgradable_slow(&self) -> bool { let mut state = self.state.load(Ordering::Relaxed); loop { - // Grab the lock if it isn't locked, even if there are other - // threads parked. - if let Some(new_state) = state.checked_add(EXCLUSIVE_GUARD) { - match self.state.compare_exchange_weak( - state, - new_state, - Ordering::Acquire, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - continue; - } - - // If there are no parked threads and only one reader or writer, try - // spinning a few times. - if (state == EXCLUSIVE_GUARD || state == SHARED_GUARD || state == UPGRADABLE_GUARD) - && spinwait.spin() - { - state = self.state.load(Ordering::Relaxed); - continue; + // This mirrors the condition in try_lock_upgradable_fast + if state & (WRITER_BIT | UPGRADABLE_BIT) != 0 { + return false; } - // Park our thread until we are woken up by an unlock - unsafe { - let addr = self as *const _ as usize; - let validate = || { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // If the rwlock is free, abort the park and try to grab - // it immediately. - if state & GUARD_COUNT_MASK == 0 { - return false; - } - - // Nothing to do if the parked bit is already set - if state & PARKED_BIT != 0 { - return true; - } - - // Set the parked bit - match self.state.compare_exchange_weak( - state, - state | PARKED_BIT, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - } - }; - let before_sleep = || {}; - let timed_out = |_, was_last_thread| { - // Clear the parked bit if we were the last parked thread - if was_last_thread { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); - } - }; - match parking_lot_core::park( - addr, - validate, - before_sleep, - timed_out, - TOKEN_EXCLUSIVE, - timeout, - ) { - // The thread that unparked us passed the lock on to us - // directly without unlocking it. - ParkResult::Unparked(TOKEN_HANDOFF) => return true, - - // We were unparked normally, try acquiring the lock again - ParkResult::Unparked(_) => (), - - // The validation function failed, try locking again - ParkResult::Invalid => (), - - // Timeout expired - ParkResult::TimedOut => return false, - } + match self.state.compare_exchange_weak( + state, + state + .checked_add(ONE_READER | UPGRADABLE_BIT) + .expect("RwLock reader count overflow"), + Ordering::Acquire, + Ordering::Relaxed, + ) { + Ok(_) => return true, + Err(x) => state = x, } - - // Loop back and try locking again - spinwait.reset(); - state = self.state.load(Ordering::Relaxed); } } #[cold] - #[inline(never)] - fn unlock_exclusive_slow(&self, force_fair: bool) { - // Unlock directly if there are no parked threads - if self - .state - .compare_exchange(EXCLUSIVE_GUARD, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - return; - }; - - // There are threads to unpark. We unpark threads up to the guard capacity. - let guard_count = Cell::new(0usize); - unsafe { - let addr = self as *const _ as usize; - let filter = |ParkToken(token)| -> FilterOp { - match guard_count.get().checked_add(token) { - Some(new_guard_count) => { - guard_count.set(new_guard_count); - FilterOp::Unpark - } - None => FilterOp::Stop, - } - }; - let callback = |result: UnparkResult| { - // If we are using a fair unlock then we should keep the - // rwlock locked and hand it off to the unparked threads. - if result.unparked_threads != 0 && (force_fair || result.be_fair) { - // We need to set the guard count accordingly. - let mut new_state = guard_count.get(); - - if result.have_more_threads { - new_state |= PARKED_BIT; + fn lock_exclusive_slow(&self, timeout: Option) -> bool { + // Step 1: grab exclusive ownership of WRITER_BIT + let timed_out = !self.lock_common( + timeout, + TOKEN_EXCLUSIVE, + |state| { + loop { + if *state & (WRITER_BIT | UPGRADABLE_BIT) != 0 { + return false; } - self.state.store(new_state, Ordering::Release); - TOKEN_HANDOFF - } else { - // Clear the parked bit if there are no more parked threads. - if result.have_more_threads { - self.state.store(PARKED_BIT, Ordering::Release); - } else { - self.state.store(0, Ordering::Release); + // Grab WRITER_BIT if it isn't set, even if there are parked threads. + match self.state.compare_exchange_weak( + *state, + *state | WRITER_BIT, + Ordering::Acquire, + Ordering::Relaxed, + ) { + Ok(_) => return true, + Err(x) => *state = x, } - TOKEN_NORMAL } - }; - parking_lot_core::unpark_filter(addr, filter, callback); + }, + |state| state & (WRITER_BIT | UPGRADABLE_BIT) != 0, + ); + if timed_out { + return false; } + + // Step 2: wait for all remaining readers to exit the lock. + self.wait_for_readers(timeout, 0) } #[cold] - #[inline(never)] - fn downgrade_slow(&self) { - unsafe { - let addr = self as *const _ as usize; - let mut guard_count = SHARED_GUARD; - let filter = |ParkToken(token)| -> FilterOp { - match guard_count.checked_add(token) { - Some(new_guard_count) => { - guard_count = new_guard_count; - FilterOp::Unpark - } - None => FilterOp::Stop, + fn unlock_exclusive_slow(&self, force_fair: bool) { + // There are threads to unpark. Try to unpark as many as we can. + let callback = |mut new_state, result: UnparkResult| { + // If we are using a fair unlock then we should keep the + // rwlock locked and hand it off to the unparked threads. + if result.unparked_threads != 0 && (force_fair || result.be_fair) { + if result.have_more_threads { + new_state |= PARKED_BIT; } - }; - let callback = |result: UnparkResult| { - // Clear the parked bit if there no more parked threads - if !result.have_more_threads { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + self.state.store(new_state, Ordering::Release); + TOKEN_HANDOFF + } else { + // Clear the parked bit if there are no more parked threads. + if result.have_more_threads { + self.state.store(PARKED_BIT, Ordering::Release); + } else { + self.state.store(0, Ordering::Release); } TOKEN_NORMAL - }; - parking_lot_core::unpark_filter(addr, filter, callback); - } + } + }; + self.wake_parked_threads(0, callback); } #[cold] - #[inline(never)] - fn downgrade_to_upgradable_slow(&self) { - unsafe { - let addr = self as *const _ as usize; - let mut guard_count = UPGRADABLE_GUARD; - let filter = |ParkToken(token)| -> FilterOp { - match guard_count.checked_add(token) { - Some(new_guard_count) => { - guard_count = new_guard_count; - FilterOp::Unpark + fn lock_shared_slow(&self, recursive: bool, timeout: Option) -> bool { + self.lock_common( + timeout, + TOKEN_SHARED, + |state| { + let mut spinwait_shared = SpinWait::new(); + loop { + // Use hardware lock elision to avoid cache conflicts when multiple + // readers try to acquire the lock. We only do this if the lock is + // completely empty since elision handles conflicts poorly. + if have_elision() && *state == 0 { + match self.state.elision_compare_exchange_acquire(0, ONE_READER) { + Ok(_) => return true, + Err(x) => *state = x, + } } - None => FilterOp::Stop, - } - }; - let callback = |result: UnparkResult| { - // Clear the parked bit if there no more parked threads - if !result.have_more_threads { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); - } - TOKEN_NORMAL - }; - parking_lot_core::unpark_filter(addr, filter, callback); - } - } - #[cold] - #[inline(never)] - fn lock_shared_slow(&self, recursive: bool, timeout: Option) -> bool { - let mut spinwait = SpinWait::new(); - let mut spinwait_shared = SpinWait::new(); - let mut state = self.state.load(Ordering::Relaxed); - let mut unparked = false; - loop { - // Use hardware lock elision to avoid cache conflicts when multiple - // readers try to acquire the lock. We only do this if the lock is - // completely empty since elision handles conflicts poorly. - if have_elision() && state == 0 { - match self.state.elision_acquire(0, SHARED_GUARD) { - Ok(_) => return true, - Err(x) => state = x, - } - } + // This is the same condition as try_lock_shared_fast + if *state & WRITER_BIT != 0 { + if !recursive || *state & READERS_MASK == 0 { + return false; + } + } - // Grab the lock if there are no exclusive threads locked or - // waiting. However if we were unparked then we are allowed to grab - // the lock even if there are pending exclusive threads. - if unparked || recursive || state & PARKED_BIT == 0 { - if let Some(new_state) = state.checked_add(SHARED_GUARD) { if self .state .compare_exchange_weak( - state, - new_state, + *state, + state.checked_add(ONE_READER).expect("RwLock reader count overflow"), Ordering::Acquire, Ordering::Relaxed, ) @@ -805,243 +663,50 @@ impl RawRwLock { // to leave some time between attempts to acquire the lock to // let other threads make progress. spinwait_shared.spin_no_yield(); - state = self.state.load(Ordering::Relaxed); - continue; - } else { - // We were unparked spuriously, reset unparked flag. - unparked = false; - } - } - - // If there are no parked threads, try spinning a few times - if state & PARKED_BIT == 0 && spinwait.spin() { - state = self.state.load(Ordering::Relaxed); - continue; - } - - // Park our thread until we are woken up by an unlock - unsafe { - let addr = self as *const _ as usize; - let validate = || { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // Nothing to do if the parked bit is already set - if state & PARKED_BIT != 0 { - return true; - } - - // If the parked bit is not set then it means we are at - // the front of the queue. If there is space for another - // lock then we should abort the park and try acquiring - // the lock again. - if state & GUARD_COUNT_MASK != GUARD_COUNT_MASK { - return false; - } - - // Set the parked bit - match self.state.compare_exchange_weak( - state, - state | PARKED_BIT, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - } - }; - let before_sleep = || {}; - let timed_out = |_, was_last_thread| { - // Clear the parked bit if we were the last parked thread - if was_last_thread { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); - } - }; - match parking_lot_core::park( - addr, - validate, - before_sleep, - timed_out, - TOKEN_SHARED, - timeout, - ) { - // The thread that unparked us passed the lock on to us - // directly without unlocking it. - ParkResult::Unparked(TOKEN_HANDOFF) => return true, - - // We were unparked normally, try acquiring the lock again - ParkResult::Unparked(_) => (), - - // The validation function failed, try locking again - ParkResult::Invalid => (), - - // Timeout expired - ParkResult::TimedOut => return false, + *state = self.state.load(Ordering::Relaxed); } - } - - // Loop back and try locking again - spinwait.reset(); - spinwait_shared.reset(); - state = self.state.load(Ordering::Relaxed); - unparked = true; - } + }, + |state| state & WRITER_BIT != 0, + ) } #[cold] - #[inline(never)] - fn try_lock_shared_slow(&self, recursive: bool) -> bool { - let mut state = self.state.load(Ordering::Relaxed); - loop { - if !recursive && state & PARKED_BIT != 0 { - return false; - } - if have_elision() && state == 0 { - match self.state.elision_acquire(0, SHARED_GUARD) { - Ok(_) => return true, - Err(x) => state = x, - } - } else { - match state.checked_add(SHARED_GUARD) { - Some(new_state) => match self.state.compare_exchange_weak( - state, - new_state, - Ordering::Acquire, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - }, - None => return false, - } - } - } - } - - #[cold] - #[inline(never)] - fn unlock_shared_slow(&self, force_fair: bool) { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // Just release the lock if there are no parked thread or if we are - // not the last shared thread. - if state & PARKED_BIT == 0 - || (state & UPGRADING_BIT == 0 && state & GUARD_COUNT_MASK != SHARED_GUARD) - || (state & UPGRADING_BIT != 0 - && state & GUARD_COUNT_MASK != UPGRADABLE_GUARD + SHARED_GUARD) - { - match self.state.compare_exchange_weak( - state, - state - SHARED_GUARD, - Ordering::Release, - Ordering::Relaxed, - ) { - Ok(_) => return, - Err(x) => state = x, - } - continue; - } - - break; - } - - // There are threads to unpark. If there is a thread waiting to be - // upgraded, we find that thread and let it upgrade, otherwise we - // unpark threads up to the guard capacity. Note that there is a - // potential race condition here: another thread might grab a shared - // lock between now and when we actually release our lock. - let additional_guards = Cell::new(0usize); - let has_upgraded = Cell::new(false); + fn unlock_shared_slow(&self) { + // At this point WRITER_PARKED_BIT is set and READER_MASK is empty. We + // just need to wake up a potentially sleeping pending writer. unsafe { - let addr = self as *const _ as usize; - let filter = |ParkToken(token)| -> FilterOp { - // We need to check UPGRADING_BIT while holding the bucket lock, - // otherwise we might miss a thread trying to upgrade. - if self.state.load(Ordering::Relaxed) & UPGRADING_BIT == 0 { - match additional_guards.get().checked_add(token) { - Some(x) => { - additional_guards.set(x); - FilterOp::Unpark - } - None => FilterOp::Stop, - } - } else if has_upgraded.get() { - FilterOp::Stop - } else { - if token & UPGRADING_BIT != 0 { - additional_guards.set(token & !UPGRADING_BIT); - has_upgraded.set(true); - FilterOp::Unpark - } else { - FilterOp::Skip - } - } - }; + // Using the 2nd key at addr + 1 + let addr = self as *const _ as usize + 1; let callback = |result: UnparkResult| { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // Release our shared lock - let mut new_state = state - SHARED_GUARD; - - // Clear the parked bit if there are no more threads in - // the queue. - if !result.have_more_threads { - new_state &= !PARKED_BIT; - } - - // Clear the upgrading bit if we are upgrading a thread. - if has_upgraded.get() { - new_state &= !UPGRADING_BIT; - } - - // Consider using fair unlocking. If we are, then we should set - // the state to the new value and tell the threads that we are - // handing the lock directly. - let token = if result.unparked_threads != 0 && (force_fair || result.be_fair) { - match new_state.checked_add(additional_guards.get()) { - Some(x) => { - new_state = x; - TOKEN_HANDOFF - } - None => TOKEN_NORMAL, - } - } else { - TOKEN_NORMAL - }; - - match self.state.compare_exchange_weak( - state, - new_state, - Ordering::Release, - Ordering::Relaxed, - ) { - Ok(_) => return token, - Err(x) => state = x, - } - } + // Clear the WRITER_PARKED_BIT here since there can only be one + // parked writer thread. + debug_assert!(!result.have_more_threads); + self.state.fetch_and(!WRITER_PARKED_BIT, Ordering::Relaxed); + TOKEN_NORMAL }; - parking_lot_core::unpark_filter(addr, filter, callback); + parking_lot_core::unpark_one(addr, callback); } } #[cold] - #[inline(never)] fn lock_upgradable_slow(&self, timeout: Option) -> bool { - let mut spinwait = SpinWait::new(); - let mut spinwait_shared = SpinWait::new(); - let mut state = self.state.load(Ordering::Relaxed); - let mut unparked = false; - loop { - // Grab the lock if there are no exclusive or upgradable threads - // locked or waiting. However if we were unparked then we are - // allowed to grab the lock even if there are pending exclusive threads. - if unparked || state & PARKED_BIT == 0 { - if let Some(new_state) = state.checked_add(UPGRADABLE_GUARD) { + self.lock_common( + timeout, + TOKEN_UPGRADABLE, + |state| { + let mut spinwait_shared = SpinWait::new(); + loop { + if *state & (WRITER_BIT | UPGRADABLE_BIT) != 0 { + return false; + } + if self .state .compare_exchange_weak( - state, - new_state, + *state, + state + .checked_add(ONE_READER | UPGRADABLE_BIT) + .expect("RwLock reader count overflow"), Ordering::Acquire, Ordering::Relaxed, ) @@ -1054,306 +719,327 @@ impl RawRwLock { // to leave some time between attempts to acquire the lock to // let other threads make progress. spinwait_shared.spin_no_yield(); - state = self.state.load(Ordering::Relaxed); - continue; - } else { - // We were unparked spuriously, reset unparked flag. - unparked = false; + *state = self.state.load(Ordering::Relaxed); } - } + }, + |state| state & (WRITER_BIT | UPGRADABLE_BIT) != 0, + ) + } - // If there are no parked threads, try spinning a few times - if state & PARKED_BIT == 0 && spinwait.spin() { - state = self.state.load(Ordering::Relaxed); - continue; + #[cold] + fn unlock_upgradable_slow(&self, force_fair: bool) { + // Just release the lock if there are no parked threads. + let mut state = self.state.load(Ordering::Relaxed); + while state & PARKED_BIT == 0 { + match self.state.compare_exchange_weak( + state, + state - (ONE_READER | UPGRADABLE_BIT), + Ordering::Release, + Ordering::Relaxed, + ) { + Ok(_) => return, + Err(x) => state = x, } + } - // Park our thread until we are woken up by an unlock - unsafe { - let addr = self as *const _ as usize; - let validate = || { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // Nothing to do if the parked bit is already set - if state & PARKED_BIT != 0 { - return true; - } - - // If the parked bit is not set then it means we are at - // the front of the queue. If there is space for an - // upgradable lock then we should abort the park and try - // acquiring the lock again. - if state & UPGRADABLE_GUARD != UPGRADABLE_GUARD { - return false; - } - - // Set the parked bit - match self.state.compare_exchange_weak( - state, - state | PARKED_BIT, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } + // There are threads to unpark. Try to unpark as many as we can. + let callback = |new_state, result: UnparkResult| { + // If we are using a fair unlock then we should keep the + // rwlock locked and hand it off to the unparked threads. + let mut state = self.state.load(Ordering::Relaxed); + if force_fair || result.be_fair { + // Fall back to normal unpark on overflow. Panicking is + // not allowed in parking_lot callbacks. + while let Some(mut new_state) = + (state - (ONE_READER | UPGRADABLE_BIT)).checked_add(new_state) + { + if result.have_more_threads { + new_state |= PARKED_BIT; + } else { + new_state &= !PARKED_BIT; } - }; - let before_sleep = || {}; - let timed_out = |_, was_last_thread| { - // Clear the parked bit if we were the last parked thread - if was_last_thread { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + match self.state.compare_exchange_weak( + state, + new_state, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => return TOKEN_HANDOFF, + Err(x) => state = x, } - }; - match parking_lot_core::park( - addr, - validate, - before_sleep, - timed_out, - TOKEN_UPGRADABLE, - timeout, - ) { - // The thread that unparked us passed the lock on to us - // directly without unlocking it. - ParkResult::Unparked(TOKEN_HANDOFF) => return true, - - // We were unparked normally, try acquiring the lock again - ParkResult::Unparked(_) => (), - - // The validation function failed, try locking again - ParkResult::Invalid => (), - - // Timeout expired - ParkResult::TimedOut => return false, } } - // Loop back and try locking again - spinwait.reset(); - spinwait_shared.reset(); - state = self.state.load(Ordering::Relaxed); - unparked = true; - } - } - - #[cold] - #[inline(never)] - fn try_lock_upgradable_slow(&self) -> bool { - let mut state = self.state.load(Ordering::Relaxed); - loop { - if state & PARKED_BIT != 0 { - return false; - } - - match state.checked_add(UPGRADABLE_GUARD) { - Some(new_state) => match self.state.compare_exchange_weak( + // Otherwise just release the upgradable lock and update PARKED_BIT. + loop { + let mut new_state = state - (ONE_READER | UPGRADABLE_BIT); + if result.have_more_threads { + new_state |= PARKED_BIT; + } else { + new_state &= !PARKED_BIT; + } + match self.state.compare_exchange_weak( state, new_state, - Ordering::Acquire, + Ordering::Relaxed, Ordering::Relaxed, ) { - Ok(_) => return true, + Ok(_) => return TOKEN_NORMAL, Err(x) => state = x, - }, - None => return false, + } } - } + }; + self.wake_parked_threads(0, callback); } #[cold] - #[inline(never)] - fn unlock_upgradable_slow(&self, force_fair: bool) { + fn try_upgrade_slow(&self) -> bool { let mut state = self.state.load(Ordering::Relaxed); loop { - // Just release the lock if there are no parked threads. - if state & PARKED_BIT == 0 { - match self.state.compare_exchange_weak( - state, - state - UPGRADABLE_GUARD, - Ordering::Release, - Ordering::Relaxed, - ) { - Ok(_) => return, - Err(x) => state = x, - } - continue; + if state & READERS_MASK != ONE_READER { + return false; + } + match self.state.compare_exchange_weak( + state, + state - (ONE_READER | UPGRADABLE_BIT) + WRITER_BIT, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => return true, + Err(x) => state = x, } - - break; } + } - // There are threads to unpark. We unpark threads up to the guard capacity. - let additional_guards = Cell::new(0usize); - unsafe { - let addr = self as *const _ as usize; - let filter = |ParkToken(token)| -> FilterOp { - match additional_guards.get().checked_add(token) { - Some(x) => { - additional_guards.set(x); - FilterOp::Unpark - } - None => FilterOp::Stop, - } - }; - let callback = |result: UnparkResult| { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // Release our upgradable lock - let mut new_state = state - UPGRADABLE_GUARD; + #[cold] + fn upgrade_slow(&self, timeout: Option) -> bool { + self.wait_for_readers(timeout, ONE_READER | UPGRADABLE_BIT) + } - // Clear the parked bit if there are no more threads in - // the queue - if !result.have_more_threads { - new_state &= !PARKED_BIT; - } + #[cold] + fn downgrade_slow(&self) { + // We only reach this point if PARKED_BIT is set. + let callback = |_, result: UnparkResult| { + // Clear the parked bit if there no more parked threads + if !result.have_more_threads { + self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + } + TOKEN_NORMAL + }; + self.wake_parked_threads(ONE_READER, callback); + } - // Consider using fair unlocking. If we are, then we should set - // the state to the new value and tell the threads that we are - // handing the lock directly. - let token = if result.unparked_threads != 0 && (force_fair || result.be_fair) { - match new_state.checked_add(additional_guards.get()) { - Some(x) => { - new_state = x; - TOKEN_HANDOFF - } - None => TOKEN_NORMAL, - } - } else { - TOKEN_NORMAL - }; + #[cold] + fn downgrade_to_upgradable_slow(&self) { + // We only reach this point if PARKED_BIT is set. + let callback = |_, result: UnparkResult| { + // Clear the parked bit if there no more parked threads + if !result.have_more_threads { + self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + } + TOKEN_NORMAL + }; + self.wake_parked_threads(ONE_READER | UPGRADABLE_BIT, callback); + } - match self.state.compare_exchange_weak( - state, - new_state, - Ordering::Release, - Ordering::Relaxed, - ) { - Ok(_) => return token, - Err(x) => state = x, - } - } - }; - parking_lot_core::unpark_filter(addr, filter, callback); - } + #[cold] + fn bump_shared_slow(&self) { + self.unlock_shared(); + self.lock_shared(); + } + + #[cold] + fn bump_exclusive_slow(&self) { + self.deadlock_release(); + self.unlock_exclusive_slow(true); + self.lock_exclusive(); } #[cold] - #[inline(never)] - fn downgrade_upgradable_slow(&self, state: usize) { + fn bump_upgradable_slow(&self) { + self.deadlock_release(); + self.unlock_upgradable_slow(true); + self.lock_upgradable(); + } + + // Common code for waking up parked threads after releasing WRITER_BIT or + // UPGRADABLE_BIT. + #[inline] + fn wake_parked_threads(&self, new_state: usize, callback: C) + where + C: FnOnce(usize, UnparkResult) -> UnparkToken, + { + // We must wake up at least one upgrader or writer if there is one, + // otherwise they may end up parked indefinitely since unlock_shared + // does not call wake_parked_threads. + let new_state = Cell::new(new_state); unsafe { let addr = self as *const _ as usize; - let mut guard_count = (state & GUARD_COUNT_MASK) - UPGRADABLE_GUARD; - let filter = |ParkToken(token)| -> FilterOp { - match guard_count.checked_add(token) { - Some(x) => { - guard_count = x; - FilterOp::Unpark - } - None => FilterOp::Stop, + let filter = |ParkToken(token)| { + let s = new_state.get(); + + // If we are waking up a writer, don't wake anything else. + if s & WRITER_BIT != 0 { + return FilterOp::Stop; } - }; - let callback = |result: UnparkResult| { - // Clear the parked bit if there no more parked threads - if !result.have_more_threads { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + + // Otherwise wake *all* readers and one upgrader/writer. + if token & (UPGRADABLE_BIT | WRITER_BIT) != 0 && s & UPGRADABLE_BIT != 0 { + // Skip writers and upgradable readers if we already have + // a writer/upgradable reader. + FilterOp::Skip + } else { + new_state.set(s + token); + FilterOp::Unpark } - TOKEN_NORMAL }; - parking_lot_core::unpark_filter(addr, filter, callback); + parking_lot_core::unpark_filter(addr, filter, |result| { + callback(new_state.get(), result) + }); } } - #[cold] - #[inline(never)] - fn try_upgrade_slow(&self) -> bool { + // Common code for waiting for readers to exit the lock after acquiring + // WRITER_BIT. + #[inline] + fn wait_for_readers(&self, timeout: Option, prev_value: usize) -> bool { + // At this point WRITER_BIT is already set, we just need to wait for the + // remaining readers to exit the lock. + let mut spinwait = SpinWait::new(); let mut state = self.state.load(Ordering::Relaxed); - loop { - match state.checked_add(EXCLUSIVE_GUARD - SHARED_GUARD) { - Some(new_state) => match self.state.compare_exchange_weak( + while state & READERS_MASK != 0 { + // Spin a few times to wait for readers to exit + if spinwait.spin() { + state = self.state.load(Ordering::Relaxed); + continue; + } + + // Set the parked bit + if state & WRITER_PARKED_BIT == 0 { + if let Err(x) = self.state.compare_exchange_weak( state, - new_state, + state | WRITER_PARKED_BIT, Ordering::Relaxed, Ordering::Relaxed, ) { - Ok(_) => return true, - Err(x) => state = x, - }, - None => return false, + state = x; + continue; + } + } + + // Park our thread until we are woken up by an unlock + unsafe { + // Using the 2nd key at addr + 1 + let addr = self as *const _ as usize + 1; + let validate = || { + let state = self.state.load(Ordering::Relaxed); + state & READERS_MASK != 0 && state & WRITER_PARKED_BIT != 0 + }; + let before_sleep = || {}; + let timed_out = |_, _| {}; + match parking_lot_core::park( + addr, + validate, + before_sleep, + timed_out, + TOKEN_EXCLUSIVE, + timeout, + ) { + // We still need to re-check the state if we are unparked + // since a previous writer timing-out could have allowed + // another reader to sneak in before we parked. + ParkResult::Unparked(_) | ParkResult::Invalid => { + state = self.state.load(Ordering::Relaxed); + continue; + } + + // Timeout expired + ParkResult::TimedOut => { + // We need to release WRITER_BIT and revert back to + // our previous value. We also wake up any threads that + // might be waiting on WRITER_BIT. + let state = self.state.fetch_add( + prev_value.wrapping_sub(WRITER_BIT | WRITER_PARKED_BIT), + Ordering::Relaxed, + ); + if state & PARKED_BIT != 0 { + let callback = |_, result: UnparkResult| { + // Clear the parked bit if there no more parked threads + if !result.have_more_threads { + self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); + } + TOKEN_NORMAL + }; + self.wake_parked_threads(ONE_READER | UPGRADABLE_BIT, callback); + } + return false; + } + } } } + true } - #[cold] - #[inline(never)] - fn upgrade_slow(&self, timeout: Option) -> bool { + // Common code for acquiring a lock + #[inline] + fn lock_common( + &self, + timeout: Option, + token: ParkToken, + mut try_lock: F, + validate: V, + ) -> bool + where + F: FnMut(&mut usize) -> bool, + V: Fn(usize) -> bool, + { let mut spinwait = SpinWait::new(); let mut state = self.state.load(Ordering::Relaxed); loop { - // Grab the lock if it isn't locked, even if there are other - // threads parked. - if let Some(new_state) = state.checked_add(EXCLUSIVE_GUARD - UPGRADABLE_GUARD) { - match self.state.compare_exchange_weak( - state, - new_state, - Ordering::Acquire, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - continue; + // Attempt to grab the lock + if try_lock(&mut state) { + return true; } - // If there are no parked threads and only one other reader, try - // spinning a few times. - if state == UPGRADABLE_GUARD | SHARED_GUARD && spinwait.spin() { + // If there are no parked threads, try spinning a few times. + if state & (PARKED_BIT | WRITER_PARKED_BIT) == 0 && spinwait.spin() { state = self.state.load(Ordering::Relaxed); continue; } + // Set the parked bit + if state & PARKED_BIT == 0 { + if let Err(x) = self.state.compare_exchange_weak( + state, + state | PARKED_BIT, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + state = x; + continue; + } + } + // Park our thread until we are woken up by an unlock unsafe { let addr = self as *const _ as usize; let validate = || { - let mut state = self.state.load(Ordering::Relaxed); - loop { - // If the rwlock is free, abort the park and try to grab - // it immediately. - if state & GUARD_COUNT_MASK == UPGRADABLE_GUARD { - return false; - } - - // Set the upgrading and parked bits - match self.state.compare_exchange_weak( - state, - state | (UPGRADING_BIT | PARKED_BIT), - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - } + let state = self.state.load(Ordering::Relaxed); + state & PARKED_BIT != 0 && validate(state) }; let before_sleep = || {}; let timed_out = |_, was_last_thread| { - // Clear the upgrading bit - let mut flags = UPGRADING_BIT; - // Clear the parked bit if we were the last parked thread if was_last_thread { - flags |= PARKED_BIT; + self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); } - - self.state.fetch_and(!flags, Ordering::Relaxed); }; match parking_lot_core::park( addr, validate, before_sleep, timed_out, - TOKEN_UPGRADING, + token, timeout, ) { // The thread that unparked us passed the lock on to us @@ -1377,27 +1063,15 @@ impl RawRwLock { } } - #[cold] - #[inline(never)] - fn bump_shared_slow(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - self.unlock_shared_slow(true); - self.lock_shared(); - } - - #[cold] - #[inline(never)] - fn bump_exclusive_slow(&self) { - unsafe { deadlock::release_resource(self as *const _ as usize) }; - self.unlock_exclusive_slow(true); - self.lock_exclusive(); + #[inline] + fn deadlock_acquire(&self) { + unsafe { deadlock::acquire_resource(self as *const _ as usize) }; + unsafe { deadlock::acquire_resource(self as *const _ as usize + 1) }; } - #[cold] - #[inline(never)] - fn bump_upgradable_slow(&self) { + #[inline] + fn deadlock_release(&self) { unsafe { deadlock::release_resource(self as *const _ as usize) }; - self.unlock_upgradable_slow(true); - self.lock_upgradable(); + unsafe { deadlock::release_resource(self as *const _ as usize + 1) }; } } diff --git a/vendor/parking_lot/src/remutex.rs b/vendor/parking_lot/src/remutex.rs index aa40e1440d..b244f42866 100644 --- a/vendor/parking_lot/src/remutex.rs +++ b/vendor/parking_lot/src/remutex.rs @@ -5,8 +5,9 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use crate::raw_mutex::RawMutex; +use core::num::NonZeroUsize; use lock_api::{self, GetThreadId}; -use raw_mutex::RawMutex; /// Implementation of the `GetThreadId` trait for `lock_api::ReentrantMutex`. pub struct RawThreadId; @@ -14,11 +15,14 @@ pub struct RawThreadId; unsafe impl GetThreadId for RawThreadId { const INIT: RawThreadId = RawThreadId; - fn nonzero_thread_id(&self) -> usize { + fn nonzero_thread_id(&self) -> NonZeroUsize { // The address of a thread-local variable is guaranteed to be unique to the // current thread, and is also guaranteed to be non-zero. thread_local!(static KEY: u8 = unsafe { ::std::mem::uninitialized() }); - KEY.with(|x| x as *const _ as usize) + KEY.with(|x| { + NonZeroUsize::new(x as *const _ as usize) + .expect("thread-local variable address is null") + }) } } @@ -54,10 +58,13 @@ pub type MappedReentrantMutexGuard<'a, T> = #[cfg(test)] mod tests { + use crate::ReentrantMutex; use std::cell::RefCell; use std::sync::Arc; use std::thread; - use ReentrantMutex; + + #[cfg(feature = "serde")] + use bincode::{deserialize, serialize}; #[test] fn smoke() { @@ -113,14 +120,18 @@ mod tests { let mutex = ReentrantMutex::new(vec![0u8, 10]); assert_eq!(format!("{:?}", mutex), "ReentrantMutex { data: [0, 10] }"); - assert_eq!( - format!("{:#?}", mutex), - "ReentrantMutex { - data: [ - 0, - 10 - ] -}" - ); + } + + #[cfg(feature = "serde")] + #[test] + fn test_serde() { + let contents: Vec = vec![0, 1, 2]; + let mutex = ReentrantMutex::new(contents.clone()); + + let serialized = serialize(&mutex).unwrap(); + let deserialized: ReentrantMutex> = deserialize(&serialized).unwrap(); + + assert_eq!(*(mutex.lock()), *(deserialized.lock())); + assert_eq!(contents, *(deserialized.lock())); } } diff --git a/vendor/parking_lot/src/rwlock.rs b/vendor/parking_lot/src/rwlock.rs index f97092454d..a6e160aad2 100644 --- a/vendor/parking_lot/src/rwlock.rs +++ b/vendor/parking_lot/src/rwlock.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use crate::raw_rwlock::RawRwLock; use lock_api; -use raw_rwlock::RawRwLock; /// A reader-writer lock /// @@ -120,14 +120,16 @@ pub type RwLockUpgradableReadGuard<'a, T> = lock_api::RwLockUpgradableReadGuard< #[cfg(test)] mod tests { - extern crate rand; - use self::rand::Rng; + use crate::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; + use rand::Rng; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; use std::sync::Arc; use std::thread; use std::time::Duration; - use {RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; + + #[cfg(feature = "serde")] + use bincode::{deserialize, serialize}; #[derive(Eq, PartialEq, Debug)] struct NonCopy(i32); @@ -357,10 +359,7 @@ mod tests { let read_guard = lock.read(); let read_result = lock.try_read(); - assert!( - read_result.is_some(), - "try_read should succeed while read_guard is in scope" - ); + assert!(read_result.is_some(), "try_read should succeed while read_guard is in scope"); drop(read_guard); } @@ -379,10 +378,7 @@ mod tests { let write_guard = lock.write(); let read_result = lock.try_read(); - assert!( - read_result.is_none(), - "try_read should fail while write_guard is in scope" - ); + assert!(read_result.is_none(), "try_read should fail while write_guard is in scope"); drop(write_guard); } @@ -395,10 +391,7 @@ mod tests { let read_guard = lock.read(); let write_result = lock.try_write(); - assert!( - write_result.is_none(), - "try_write should fail while read_guard is in scope" - ); + assert!(write_result.is_none(), "try_write should fail while read_guard is in scope"); drop(read_guard); } @@ -417,10 +410,7 @@ mod tests { let write_guard = lock.write(); let write_result = lock.try_write(); - assert!( - write_result.is_none(), - "try_write should fail while write_guard is in scope" - ); + assert!(write_result.is_none(), "try_write should fail while write_guard is in scope"); drop(write_guard); } @@ -534,7 +524,15 @@ mod tests { thread::spawn(move || { let _lock = arc2.write(); }); - thread::sleep(Duration::from_millis(100)); + + if cfg!(not(all(target_env = "sgx", target_vendor = "fortanix"))) { + thread::sleep(Duration::from_millis(100)); + } else { + // FIXME: https://github.com/fortanix/rust-sgx/issues/31 + for _ in 0..100 { + thread::yield_now(); + } + } // A normal read would block here since there is a pending writer let _lock2 = arc.read_recursive(); @@ -545,17 +543,8 @@ mod tests { let x = RwLock::new(vec![0u8, 10]); assert_eq!(format!("{:?}", x), "RwLock { data: [0, 10] }"); - assert_eq!( - format!("{:#?}", x), - "RwLock { - data: [ - 0, - 10 - ] -}" - ); let _lock = x.write(); - assert_eq!(format!("{:?}", x), "RwLock { }"); + assert_eq!(format!("{:?}", x), "RwLock { data: }"); } #[test] @@ -565,4 +554,17 @@ mod tests { let b = a.clone(); assert_eq!(Arc::strong_count(&b), 2); } + + #[cfg(feature = "serde")] + #[test] + fn test_serde() { + let contents: Vec = vec![0, 1, 2]; + let mutex = RwLock::new(contents.clone()); + + let serialized = serialize(&mutex).unwrap(); + let deserialized: RwLock> = deserialize(&serialized).unwrap(); + + assert_eq!(*(mutex.read()), *(deserialized.read())); + assert_eq!(contents, *(deserialized.read())); + } } diff --git a/vendor/parking_lot/src/util.rs b/vendor/parking_lot/src/util.rs index c05a539b67..90e008b9cf 100644 --- a/vendor/parking_lot/src/util.rs +++ b/vendor/parking_lot/src/util.rs @@ -22,22 +22,21 @@ impl UncheckedOptionExt for Option { } } -// Equivalent to intrinsics::unreachable() in release mode +// hint::unreachable_unchecked() in release mode #[inline] unsafe fn unreachable() -> ! { if cfg!(debug_assertions) { unreachable!(); } else { - enum Void {} - match *(1 as *const Void) {} + core::hint::unreachable_unchecked() } } #[inline] pub fn to_deadline(timeout: Duration) -> Option { - #[cfg(feature = "nightly")] + #[cfg(has_checked_instant)] let deadline = Instant::now().checked_add(timeout); - #[cfg(not(feature = "nightly"))] + #[cfg(not(has_checked_instant))] let deadline = Some(Instant::now() + timeout); deadline diff --git a/vendor/parking_lot_core/.cargo-checksum.json b/vendor/parking_lot_core/.cargo-checksum.json index 8cbf15cffa..d052f943c2 100644 --- a/vendor/parking_lot_core/.cargo-checksum.json +++ b/vendor/parking_lot_core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"b8af1f3d0946ea4db58f7fa34c19e38165eac9b070bb055e5888d55fa52e3007","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"b4ca69501aa539f2d9a50a3188e93d69eb5ad0c38d5cd194df361a3f2f9a8b92","src/lib.rs":"9d5d80460481b44b8d9048b7319be33ac989250960c61b7c4528c0431f9ad36c","src/parking_lot.rs":"70d621eed1e4a85d4e4f619d50fd11b12e3a4b7141d4400252d3ab071d665f8e","src/spinwait.rs":"45a0f2a57177bc9759c0c2167f758ee220fba7cd8bdf1fbcd9c2b962fef9a1e5","src/thread_parker/generic.rs":"985966b1bdc763ada6d1fee800d19dd92611da4f84cfeef2d82763ffd2a499c3","src/thread_parker/linux.rs":"c41d08ab333972b67f20443f474ed25a1f171db0f87e227df4bdc504f6f9d897","src/thread_parker/unix.rs":"6364bcfeacfb3189bcebeddfccef1b9843d3c59d6d0f046827e62b33bcee30dd","src/thread_parker/windows/keyed_event.rs":"83d4bace5d2f17993071de28043e94f3b9673c887e01c72653b6fd24db260634","src/thread_parker/windows/mod.rs":"f31eed53f3e402477d80a70a7c6d474c01ba4c9ad952bbe562509448cd3cc1ad","src/thread_parker/windows/waitaddress.rs":"1a6eee8ab9131c746089e78b0aab900f23a5ed8ee6f2e789b8ec4d2232153ab8","src/util.rs":"2d07c0c010a857790ae2ed6a1215eeed8af76859e076797ea1ba8dec82169e84","src/word_lock.rs":"c4d50c0d37e6dd92fb078c80f84dc5b5c83bdf46baad34ed35af8730a345a2b5"},"package":"94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"} \ No newline at end of file +{"files":{"Cargo.toml":"b63bbe68314522e15a5bbe3ae70bd92278f96301e3b7bca99bf11375c7914be6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"d6aa24b67fdcacf238778c5efaf1f622ec7f7a7ec27fa051f415a1e2d31f3532","src/lib.rs":"5f93085983b6fe90306e2a8b19102a5e5dc495c6628e5bea0806ad6143fdf6a2","src/parking_lot.rs":"fcd9a449ecd98544b3e728c5c0e19eec8963a5131a529f4a89aed96bf2844e5e","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/cloudabi.rs":"fe21f7b70a80b5fa0fa3209e56a090bf8b0b7dba26f2199d37477208f3f7e47d","src/thread_parker/generic.rs":"2f501c6e46fcff434ba9e13ae8859e66de3327f601ed92989b310124e4129ff4","src/thread_parker/linux.rs":"853fd22f51215d1f553ad6461ad3c92c4ec9c294e607e69ed5f53b2e8c7a11d7","src/thread_parker/mod.rs":"e23da913e184c12e2f566beabdcbb141df0610dabf3ea83e6b5cefede51c4bcf","src/thread_parker/redox.rs":"081c76af1e24be12da45d8093e261c48d558342ac2ac64dc3f7dd95eaaa1bf11","src/thread_parker/sgx.rs":"3fd71a7066db58189f302d2344e4e425320f82c298ca482ca4318bae44ae37fd","src/thread_parker/unix.rs":"da20f3151add154947054c8c7cab22c93231ade2e5dfe43c78eba7dbfc1aea5d","src/thread_parker/wasm.rs":"b4c9f9e9c1fd636b235a0e8e0227c954b1e7432d8394b58af77b348cdfa2141e","src/thread_parker/wasm_atomic.rs":"a1ab05981a833e72d8d353350ab2b95e6f833cd7224591e595ccdb3692968c23","src/thread_parker/windows/keyed_event.rs":"e0c2ed647e0550bffa003160405b5f4ddd40500134c2eb15c3eb598792c30e84","src/thread_parker/windows/mod.rs":"7702ff9b72ac647ec998a9b205ace961a28839fcd94631fb750ca459e4804260","src/thread_parker/windows/waitaddress.rs":"06d994633006e237dc940f377432ea00cf1609e56096d69d46f7bb3b80eeb857","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"e5af5bdae754f4799d1e0e0bbdcf48b82213ca5bfc785104aa27f3d6ea728dd4"},"package":"b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"} \ No newline at end of file diff --git a/vendor/parking_lot_core/Cargo.toml b/vendor/parking_lot_core/Cargo.toml index 8a379252e2..ea8d5ee101 100644 --- a/vendor/parking_lot_core/Cargo.toml +++ b/vendor/parking_lot_core/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,8 +11,9 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "parking_lot_core" -version = "0.4.0" +version = "0.6.2" authors = ["Amanieu d'Antras "] description = "An advanced API for creating custom synchronization primitives." keywords = ["mutex", "condvar", "rwlock", "once", "thread"] @@ -23,13 +24,13 @@ repository = "https://github.com/Amanieu/parking_lot" version = "0.3.2" optional = true +[dependencies.cfg-if] +version = "0.1.5" + [dependencies.petgraph] version = "0.4.5" optional = true -[dependencies.rand] -version = "0.6" - [dependencies.smallvec] version = "0.6" @@ -42,8 +43,12 @@ version = "0.2" [features] deadlock_detection = ["petgraph", "thread-id", "backtrace"] nightly = [] +[target."cfg(target_os = \"cloudabi\")".dependencies.cloudabi] +version = "0.0.3" +[target."cfg(target_os = \"redox\")".dependencies.redox_syscall] +version = "0.1" [target."cfg(unix)".dependencies.libc] -version = "0.2.27" +version = "0.2.55" [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"] diff --git a/vendor/parking_lot_core/build.rs b/vendor/parking_lot_core/build.rs index 8d745eefc7..417a770ae8 100644 --- a/vendor/parking_lot_core/build.rs +++ b/vendor/parking_lot_core/build.rs @@ -1,8 +1,7 @@ -extern crate rustc_version; use rustc_version::{version, Version}; fn main() { - if version().unwrap() >= Version::parse("1.26.0").unwrap() { - println!("cargo:rustc-cfg=has_localkey_try_with"); + if version().unwrap() >= Version::parse("1.34.0").unwrap() { + println!("cargo:rustc-cfg=has_sized_atomics"); } } diff --git a/vendor/parking_lot_core/src/lib.rs b/vendor/parking_lot_core/src/lib.rs index 338b63e98a..6fad7801f1 100644 --- a/vendor/parking_lot_core/src/lib.rs +++ b/vendor/parking_lot_core/src/lib.rs @@ -38,47 +38,34 @@ //! reference count and the two mutex bits in the same atomic word. #![warn(missing_docs)] +#![warn(rust_2018_idioms)] #![cfg_attr( - all(feature = "nightly", target_os = "linux"), - feature(integer_atomics) + all(target_env = "sgx", target_vendor = "fortanix"), + feature(sgx_platform) +)] +#![cfg_attr( + all( + feature = "nightly", + target_arch = "wasm32", + target_feature = "atomics" + ), + feature(checked_duration_since, stdsimd) +)] +#![cfg_attr( + all(feature = "nightly", target_os = "cloudabi",), + feature(thread_local, checked_duration_since) )] - -extern crate rand; -extern crate smallvec; - -#[cfg(feature = "deadlock_detection")] -extern crate backtrace; -#[cfg(feature = "deadlock_detection")] -extern crate petgraph; -#[cfg(feature = "deadlock_detection")] -extern crate thread_id; - -#[cfg(unix)] -extern crate libc; - -#[cfg(windows)] -extern crate winapi; - -#[cfg(all(feature = "nightly", target_os = "linux"))] -#[path = "thread_parker/linux.rs"] -mod thread_parker; -#[cfg(all(unix, not(all(feature = "nightly", target_os = "linux"))))] -#[path = "thread_parker/unix.rs"] -mod thread_parker; -#[cfg(windows)] -#[path = "thread_parker/windows/mod.rs"] -mod thread_parker; -#[cfg(not(any(windows, unix)))] -#[path = "thread_parker/generic.rs"] -mod thread_parker; mod parking_lot; mod spinwait; +mod thread_parker; mod util; mod word_lock; -pub use parking_lot::deadlock; -pub use parking_lot::{park, unpark_all, unpark_filter, unpark_one, unpark_requeue}; -pub use parking_lot::{FilterOp, ParkResult, ParkToken, RequeueOp, UnparkResult, UnparkToken}; -pub use parking_lot::{DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; -pub use spinwait::SpinWait; +pub use self::parking_lot::deadlock; +pub use self::parking_lot::{park, unpark_all, unpark_filter, unpark_one, unpark_requeue}; +pub use self::parking_lot::{ + FilterOp, ParkResult, ParkToken, RequeueOp, UnparkResult, UnparkToken, +}; +pub use self::parking_lot::{DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; +pub use self::spinwait::SpinWait; diff --git a/vendor/parking_lot_core/src/parking_lot.rs b/vendor/parking_lot_core/src/parking_lot.rs index 64acaf93f7..24962511f0 100644 --- a/vendor/parking_lot_core/src/parking_lot.rs +++ b/vendor/parking_lot_core/src/parking_lot.rs @@ -5,23 +5,19 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use rand::rngs::SmallRng; -use rand::{FromEntropy, Rng}; +use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT}; +use crate::util::UncheckedOptionExt; +use crate::word_lock::WordLock; +use core::{ + cell::{Cell, UnsafeCell}, + ptr, + sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, +}; use smallvec::SmallVec; -use std::cell::{Cell, UnsafeCell}; -use std::mem; -#[cfg(not(has_localkey_try_with))] -use std::panic; -use std::ptr; -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; -use std::thread::LocalKey; use std::time::{Duration, Instant}; -use thread_parker::ThreadParker; -use util::UncheckedOptionExt; -use word_lock::WordLock; -static NUM_THREADS: AtomicUsize = ATOMIC_USIZE_INIT; -static HASHTABLE: AtomicUsize = ATOMIC_USIZE_INIT; +static NUM_THREADS: AtomicUsize = AtomicUsize::new(0); +static HASHTABLE: AtomicPtr = AtomicPtr::new(ptr::null_mut()); // Even with 3x more buckets than threads, the memory overhead per thread is // still only a few hundred bytes per thread. @@ -39,24 +35,27 @@ struct HashTable { } impl HashTable { + #[inline] fn new(num_threads: usize, prev: *const HashTable) -> Box { let new_size = (num_threads * LOAD_FACTOR).next_power_of_two(); let hash_bits = 0usize.leading_zeros() - new_size.leading_zeros() - 1; - let bucket = Bucket { - mutex: WordLock::new(), - queue_head: Cell::new(ptr::null()), - queue_tail: Cell::new(ptr::null()), - fair_timeout: UnsafeCell::new(FairTimeout::new()), - _padding: unsafe { mem::uninitialized() }, - }; + + let now = Instant::now(); + let mut entries = Vec::with_capacity(new_size); + for i in 0..new_size { + // We must ensure the seed is not zero + entries.push(Bucket::new(now, i as u32 + 1)); + } + Box::new(HashTable { - entries: vec![bucket; new_size].into_boxed_slice(), - hash_bits: hash_bits, + entries: entries.into_boxed_slice(), + hash_bits, _prev: prev, }) } } +#[repr(align(64))] struct Bucket { // Lock protecting the queue mutex: WordLock, @@ -67,22 +66,16 @@ struct Bucket { // Next time at which point be_fair should be set fair_timeout: UnsafeCell, - - // Padding to avoid false sharing between buckets. Ideally we would just - // align the bucket structure to 64 bytes, but Rust doesn't support that - // yet. - _padding: [u8; 64], } -// Implementation of Clone for Bucket, needed to make vec![] work -impl Clone for Bucket { - fn clone(&self) -> Bucket { - Bucket { - mutex: WordLock::new(), +impl Bucket { + #[inline] + pub fn new(timeout: Instant, seed: u32) -> Self { + Self { + mutex: WordLock::INIT, queue_head: Cell::new(ptr::null()), queue_tail: Cell::new(ptr::null()), - fair_timeout: UnsafeCell::new(FairTimeout::new()), - _padding: unsafe { mem::uninitialized() }, + fair_timeout: UnsafeCell::new(FairTimeout::new(timeout, seed)), } } } @@ -91,28 +84,37 @@ struct FairTimeout { // Next time at which point be_fair should be set timeout: Instant, - // Random number generator for calculating the next timeout - rng: SmallRng, + // the PRNG state for calculating the next timeout + seed: u32, } impl FairTimeout { - fn new() -> FairTimeout { - FairTimeout { - timeout: Instant::now(), - rng: SmallRng::from_entropy(), - } + #[inline] + fn new(timeout: Instant, seed: u32) -> FairTimeout { + FairTimeout { timeout, seed } } // Determine whether we should force a fair unlock, and update the timeout + #[inline] fn should_timeout(&mut self) -> bool { let now = Instant::now(); if now > self.timeout { - self.timeout = now + Duration::new(0, self.rng.gen_range(0, 1000000)); + // Time between 0 and 1ms. + let nanos = self.gen_u32() % 1_000_000; + self.timeout = now + Duration::new(0, nanos); true } else { false } } + + // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia. + fn gen_u32(&mut self) -> u32 { + self.seed ^= self.seed << 13; + self.seed ^= self.seed >> 17; + self.seed ^= self.seed << 5; + self.seed + } } struct ThreadData { @@ -135,8 +137,7 @@ struct ThreadData { parked_with_timeout: Cell, // Extra data for deadlock detection - // TODO: once supported in stable replace with #[cfg...] & remove dummy struct/impl - #[allow(dead_code)] + #[cfg(feature = "deadlock_detection")] deadlock_data: deadlock::DeadlockData, } @@ -156,34 +157,25 @@ impl ThreadData { unpark_token: Cell::new(DEFAULT_UNPARK_TOKEN), park_token: Cell::new(DEFAULT_PARK_TOKEN), parked_with_timeout: Cell::new(false), + #[cfg(feature = "deadlock_detection")] deadlock_data: deadlock::DeadlockData::new(), } } } -// Returns a ThreadData structure for the current thread -unsafe fn get_thread_data(local: &mut Option) -> &ThreadData { - // Try to read from thread-local storage, but return None if the TLS has - // already been destroyed. - #[cfg(has_localkey_try_with)] - fn try_get_tls(key: &'static LocalKey) -> Option<*const ThreadData> { - key.try_with(|x| x as *const ThreadData).ok() - } - #[cfg(not(has_localkey_try_with))] - fn try_get_tls(key: &'static LocalKey) -> Option<*const ThreadData> { - panic::catch_unwind(|| key.with(|x| x as *const ThreadData)).ok() - } - +// Invokes the given closure with a reference to the current thread `ThreadData`. +#[inline(always)] +fn with_thread_data(f: impl FnOnce(&ThreadData) -> T) -> T { // Unlike word_lock::ThreadData, parking_lot::ThreadData is always expensive - // to construct. Try to use a thread-local version if possible. + // to construct. Try to use a thread-local version if possible. Otherwise just + // create a ThreadData on the stack + let mut thread_data_storage = None; thread_local!(static THREAD_DATA: ThreadData = ThreadData::new()); - if let Some(tls) = try_get_tls(&THREAD_DATA) { - return &*tls; - } + let thread_data_ptr = THREAD_DATA + .try_with(|x| x as *const ThreadData) + .unwrap_or_else(|_| thread_data_storage.get_or_insert_with(ThreadData::new)); - // Otherwise just create a ThreadData on the stack - *local = Some(ThreadData::new()); - local.as_ref().unwrap() + f(unsafe { &*thread_data_ptr }) } impl Drop for ThreadData { @@ -193,30 +185,40 @@ impl Drop for ThreadData { } // Get a pointer to the latest hash table, creating one if it doesn't exist yet. -unsafe fn get_hashtable() -> *const HashTable { - let mut table = HASHTABLE.load(Ordering::Acquire); +#[inline] +fn get_hashtable() -> *mut HashTable { + let table = HASHTABLE.load(Ordering::Acquire); // If there is no table, create one - if table == 0 { - let new_table = Box::into_raw(HashTable::new(LOAD_FACTOR, ptr::null())); + if table.is_null() { + create_hashtable() + } else { + table + } +} - // If this fails then it means some other thread created the hash - // table first. - match HASHTABLE.compare_exchange( - 0, - new_table as usize, - Ordering::Release, - Ordering::Relaxed, - ) { - Ok(_) => return new_table, - Err(x) => table = x, +// Get a pointer to the latest hash table, creating one if it doesn't exist yet. +#[cold] +fn create_hashtable() -> *mut HashTable { + let new_table = Box::into_raw(HashTable::new(LOAD_FACTOR, ptr::null())); + + // If this fails then it means some other thread created the hash + // table first. + match HASHTABLE.compare_exchange( + ptr::null_mut(), + new_table, + Ordering::Release, + Ordering::Relaxed, + ) { + Ok(_) => new_table, + Err(old_table) => { + // Free the table we created + unsafe { + Box::from_raw(new_table); + } + old_table } - - // Free the table we created - Box::from_raw(new_table); } - - table as *const HashTable } // Grow the hash table so that it is big enough for the given number of threads. @@ -224,13 +226,18 @@ unsafe fn get_hashtable() -> *const HashTable { // created, which only happens once per thread. unsafe fn grow_hashtable(num_threads: usize) { // If there is no table, create one - if HASHTABLE.load(Ordering::Relaxed) == 0 { + if HASHTABLE.load(Ordering::Relaxed).is_null() { let new_table = Box::into_raw(HashTable::new(num_threads, ptr::null())); // If this fails then it means some other thread created the hash // table first. if HASHTABLE - .compare_exchange(0, new_table as usize, Ordering::Release, Ordering::Relaxed) + .compare_exchange( + ptr::null_mut(), + new_table, + Ordering::Release, + Ordering::Relaxed, + ) .is_ok() { return; @@ -242,7 +249,7 @@ unsafe fn grow_hashtable(num_threads: usize) { let mut old_table; loop { - old_table = HASHTABLE.load(Ordering::Acquire) as *mut HashTable; + old_table = HASHTABLE.load(Ordering::Acquire); // Check if we need to resize the existing table if (*old_table).entries.len() >= LOAD_FACTOR * num_threads { @@ -257,7 +264,7 @@ unsafe fn grow_hashtable(num_threads: usize) { // Now check if our table is still the latest one. Another thread could // have grown the hash table between us reading HASHTABLE and locking // the buckets. - if HASHTABLE.load(Ordering::Relaxed) == old_table as usize { + if HASHTABLE.load(Ordering::Relaxed) == old_table { break; } @@ -292,7 +299,7 @@ unsafe fn grow_hashtable(num_threads: usize) { // Publish the new table. No races are possible at this point because // any other thread trying to grow the hash table is blocked on the bucket // locks in the old table. - HASHTABLE.store(Box::into_raw(new_table) as usize, Ordering::Release); + HASHTABLE.store(Box::into_raw(new_table), Ordering::Release); // Unlock all buckets in the old table for b in &(*old_table).entries[..] { @@ -302,15 +309,18 @@ unsafe fn grow_hashtable(num_threads: usize) { // Hash function for addresses #[cfg(target_pointer_width = "32")] +#[inline] fn hash(key: usize, bits: u32) -> usize { key.wrapping_mul(0x9E3779B9) >> (32 - bits) } #[cfg(target_pointer_width = "64")] +#[inline] fn hash(key: usize, bits: u32) -> usize { key.wrapping_mul(0x9E3779B97F4A7C15) >> (64 - bits) } // Lock the bucket for the given key +#[inline] unsafe fn lock_bucket<'a>(key: usize) -> &'a Bucket { let mut bucket; loop { @@ -324,7 +334,7 @@ unsafe fn lock_bucket<'a>(key: usize) -> &'a Bucket { // If no other thread has rehashed the table before we grabbed the lock // then we are good to go! The lock we grabbed prevents any rehashes. - if HASHTABLE.load(Ordering::Relaxed) == hashtable as usize { + if HASHTABLE.load(Ordering::Relaxed) == hashtable { return bucket; } @@ -335,6 +345,7 @@ unsafe fn lock_bucket<'a>(key: usize) -> &'a Bucket { // Lock the bucket for the given key, but check that the key hasn't been changed // in the meantime due to a requeue. +#[inline] unsafe fn lock_bucket_checked<'a>(key: &AtomicUsize) -> (usize, &'a Bucket) { let mut bucket; loop { @@ -350,7 +361,7 @@ unsafe fn lock_bucket_checked<'a>(key: &AtomicUsize) -> (usize, &'a Bucket) { // Check that both the hash table and key are correct while the bucket // is locked. Note that the key can't change once we locked the proper // bucket for it, so we just keep trying until we have the correct key. - if HASHTABLE.load(Ordering::Relaxed) == hashtable as usize + if HASHTABLE.load(Ordering::Relaxed) == hashtable && key.load(Ordering::Relaxed) == current_key { return (current_key, bucket); @@ -362,6 +373,7 @@ unsafe fn lock_bucket_checked<'a>(key: &AtomicUsize) -> (usize, &'a Bucket) { } // Lock the two buckets for the given pair of keys +#[inline] unsafe fn lock_bucket_pair<'a>(key1: usize, key2: usize) -> (&'a Bucket, &'a Bucket) { let mut bucket1; loop { @@ -381,7 +393,7 @@ unsafe fn lock_bucket_pair<'a>(key1: usize, key2: usize) -> (&'a Bucket, &'a Buc // If no other thread has rehashed the table before we grabbed the lock // then we are good to go! The lock we grabbed prevents any rehashes. - if HASHTABLE.load(Ordering::Relaxed) == hashtable as usize { + if HASHTABLE.load(Ordering::Relaxed) == hashtable { // Now lock the second bucket and return the two buckets if hash1 == hash2 { return (bucket1, bucket1); @@ -402,14 +414,10 @@ unsafe fn lock_bucket_pair<'a>(key1: usize, key2: usize) -> (&'a Bucket, &'a Buc } // Unlock a pair of buckets +#[inline] unsafe fn unlock_bucket_pair(bucket1: &Bucket, bucket2: &Bucket) { - if bucket1 as *const _ == bucket2 as *const _ { - bucket1.mutex.unlock(); - } else if bucket1 as *const _ < bucket2 as *const _ { - bucket2.mutex.unlock(); - bucket1.mutex.unlock(); - } else { - bucket1.mutex.unlock(); + bucket1.mutex.unlock(); + if !ptr::eq(bucket1, bucket2) { bucket2.mutex.unlock(); } } @@ -429,6 +437,7 @@ pub enum ParkResult { impl ParkResult { /// Returns true if we were unparked by another thread. + #[inline] pub fn is_unparked(self) -> bool { if let ParkResult::Unparked(_) = self { true @@ -535,142 +544,117 @@ pub const DEFAULT_PARK_TOKEN: ParkToken = ParkToken(0); /// to call `unpark_one`, `unpark_all`, `unpark_requeue` or `unpark_filter`, but /// it is not allowed to call `park` or panic. #[inline] -pub unsafe fn park( +pub unsafe fn park( key: usize, - validate: V, - before_sleep: B, - timed_out: T, - park_token: ParkToken, - timeout: Option, -) -> ParkResult -where - V: FnOnce() -> bool, - B: FnOnce(), - T: FnOnce(usize, bool), -{ - let mut v = Some(validate); - let mut b = Some(before_sleep); - let mut t = Some(timed_out); - park_internal( - key, - &mut || v.take().unchecked_unwrap()(), - &mut || b.take().unchecked_unwrap()(), - &mut |key, was_last_thread| t.take().unchecked_unwrap()(key, was_last_thread), - park_token, - timeout, - ) -} - -// Non-generic version to reduce monomorphization cost -unsafe fn park_internal( - key: usize, - validate: &mut FnMut() -> bool, - before_sleep: &mut FnMut(), - timed_out: &mut FnMut(usize, bool), + validate: impl FnOnce() -> bool, + before_sleep: impl FnOnce(), + timed_out: impl FnOnce(usize, bool), park_token: ParkToken, timeout: Option, ) -> ParkResult { // Grab our thread data, this also ensures that the hash table exists - let mut thread_data = None; - let thread_data = get_thread_data(&mut thread_data); + with_thread_data(|thread_data| { + // Lock the bucket for the given key + let bucket = lock_bucket(key); - // Lock the bucket for the given key - let bucket = lock_bucket(key); + // If the validation function fails, just return + if !validate() { + bucket.mutex.unlock(); + return ParkResult::Invalid; + } - // If the validation function fails, just return - if !validate() { + // Append our thread data to the queue and unlock the bucket + thread_data.parked_with_timeout.set(timeout.is_some()); + thread_data.next_in_queue.set(ptr::null()); + thread_data.key.store(key, Ordering::Relaxed); + thread_data.park_token.set(park_token); + thread_data.parker.prepare_park(); + if !bucket.queue_head.get().is_null() { + (*bucket.queue_tail.get()).next_in_queue.set(thread_data); + } else { + bucket.queue_head.set(thread_data); + } + bucket.queue_tail.set(thread_data); bucket.mutex.unlock(); - return ParkResult::Invalid; - } - // Append our thread data to the queue and unlock the bucket - thread_data.parked_with_timeout.set(timeout.is_some()); - thread_data.next_in_queue.set(ptr::null()); - thread_data.key.store(key, Ordering::Relaxed); - thread_data.park_token.set(park_token); - thread_data.parker.prepare_park(); - if !bucket.queue_head.get().is_null() { - (*bucket.queue_tail.get()).next_in_queue.set(thread_data); - } else { - bucket.queue_head.set(thread_data); - } - bucket.queue_tail.set(thread_data); - bucket.mutex.unlock(); + // Invoke the pre-sleep callback + before_sleep(); + + // Park our thread and determine whether we were woken up by an unpark + // or by our timeout. Note that this isn't precise: we can still be + // unparked since we are still in the queue. + let unparked = match timeout { + Some(timeout) => thread_data.parker.park_until(timeout), + None => { + thread_data.parker.park(); + // call deadlock detection on_unpark hook + deadlock::on_unpark(thread_data); + true + } + }; - // Invoke the pre-sleep callback - before_sleep(); - - // Park our thread and determine whether we were woken up by an unpark or by - // our timeout. Note that this isn't precise: we can still be unparked since - // we are still in the queue. - let unparked = match timeout { - Some(timeout) => thread_data.parker.park_until(timeout), - None => { - thread_data.parker.park(); - // call deadlock detection on_unpark hook - deadlock::on_unpark(thread_data); - true + // If we were unparked, return now + if unparked { + return ParkResult::Unparked(thread_data.unpark_token.get()); } - }; - // If we were unparked, return now - if unparked { - return ParkResult::Unparked(thread_data.unpark_token.get()); - } + // Lock our bucket again. Note that the hashtable may have been rehashed in + // the meantime. Our key may also have changed if we were requeued. + let (key, bucket) = lock_bucket_checked(&thread_data.key); - // Lock our bucket again. Note that the hashtable may have been rehashed in - // the meantime. Our key may also have changed if we were requeued. - let (key, bucket) = lock_bucket_checked(&thread_data.key); + // Now we need to check again if we were unparked or timed out. Unlike the + // last check this is precise because we hold the bucket lock. + if !thread_data.parker.timed_out() { + bucket.mutex.unlock(); + return ParkResult::Unparked(thread_data.unpark_token.get()); + } - // Now we need to check again if we were unparked or timed out. Unlike the - // last check this is precise because we hold the bucket lock. - if !thread_data.parker.timed_out() { - bucket.mutex.unlock(); - return ParkResult::Unparked(thread_data.unpark_token.get()); - } + // We timed out, so we now need to remove our thread from the queue + let mut link = &bucket.queue_head; + let mut current = bucket.queue_head.get(); + let mut previous = ptr::null(); + let mut was_last_thread = true; + while !current.is_null() { + if current == thread_data { + let next = (*current).next_in_queue.get(); + link.set(next); + if bucket.queue_tail.get() == current { + bucket.queue_tail.set(previous); + } else { + // Scan the rest of the queue to see if there are any other + // entries with the given key. + let mut scan = next; + while !scan.is_null() { + if (*scan).key.load(Ordering::Relaxed) == key { + was_last_thread = false; + break; + } + scan = (*scan).next_in_queue.get(); + } + } - // We timed out, so we now need to remove our thread from the queue - let mut link = &bucket.queue_head; - let mut current = bucket.queue_head.get(); - let mut previous = ptr::null(); - while !current.is_null() { - if current == thread_data { - let next = (*current).next_in_queue.get(); - link.set(next); - let mut was_last_thread = true; - if bucket.queue_tail.get() == current { - bucket.queue_tail.set(previous); + // Callback to indicate that we timed out, and whether we were the + // last thread on the queue. + timed_out(key, was_last_thread); + break; } else { - // Scan the rest of the queue to see if there are any other - // entries with the given key. - let mut scan = next; - while !scan.is_null() { - if (*scan).key.load(Ordering::Relaxed) == key { - was_last_thread = false; - break; - } - scan = (*scan).next_in_queue.get(); + if (*current).key.load(Ordering::Relaxed) == key { + was_last_thread = false; } + link = &(*current).next_in_queue; + previous = current; + current = link.get(); } - - // Callback to indicate that we timed out, and whether we were the - // last thread on the queue. - timed_out(key, was_last_thread); - break; - } else { - link = &(*current).next_in_queue; - previous = current; - current = link.get(); } - } - // There should be no way for our thread to have been removed from the queue - // if we timed out. - debug_assert!(!current.is_null()); + // There should be no way for our thread to have been removed from the queue + // if we timed out. + debug_assert!(!current.is_null()); - // Unlock the bucket, we are done - bucket.mutex.unlock(); - ParkResult::TimedOut + // Unlock the bucket, we are done + bucket.mutex.unlock(); + ParkResult::TimedOut + }) } /// Unparks one thread from the queue associated with the given key. @@ -693,18 +677,9 @@ unsafe fn park_internal( /// The `callback` function is called while the queue is locked and must not /// panic or call into any function in `parking_lot`. #[inline] -pub unsafe fn unpark_one(key: usize, callback: C) -> UnparkResult -where - C: FnOnce(UnparkResult) -> UnparkToken, -{ - let mut c = Some(callback); - unpark_one_internal(key, &mut |result| c.take().unchecked_unwrap()(result)) -} - -// Non-generic version to reduce monomorphization cost -unsafe fn unpark_one_internal( +pub unsafe fn unpark_one( key: usize, - callback: &mut FnMut(UnparkResult) -> UnparkToken, + callback: impl FnOnce(UnparkResult) -> UnparkToken, ) -> UnparkResult { // Lock the bucket for the given key let bucket = lock_bucket(key); @@ -776,6 +751,7 @@ unsafe fn unpark_one_internal( /// You should only call this function with an address that you control, since /// you could otherwise interfere with the operation of other synchronization /// primitives. +#[inline] pub unsafe fn unpark_all(key: usize, unpark_token: UnparkToken) -> usize { // Lock the bucket for the given key let bucket = lock_bucket(key); @@ -850,32 +826,11 @@ pub unsafe fn unpark_all(key: usize, unpark_token: UnparkToken) -> usize { /// The `validate` and `callback` functions are called while the queue is locked /// and must not panic or call into any function in `parking_lot`. #[inline] -pub unsafe fn unpark_requeue( +pub unsafe fn unpark_requeue( key_from: usize, key_to: usize, - validate: V, - callback: C, -) -> UnparkResult -where - V: FnOnce() -> RequeueOp, - C: FnOnce(RequeueOp, UnparkResult) -> UnparkToken, -{ - let mut v = Some(validate); - let mut c = Some(callback); - unpark_requeue_internal( - key_from, - key_to, - &mut || v.take().unchecked_unwrap()(), - &mut |op, r| c.take().unchecked_unwrap()(op, r), - ) -} - -// Non-generic version to reduce monomorphization cost -unsafe fn unpark_requeue_internal( - key_from: usize, - key_to: usize, - validate: &mut FnMut() -> RequeueOp, - callback: &mut FnMut(RequeueOp, UnparkResult) -> UnparkToken, + validate: impl FnOnce() -> RequeueOp, + callback: impl FnOnce(RequeueOp, UnparkResult) -> UnparkToken, ) -> UnparkResult { // Lock the two buckets for the given key let (bucket_from, bucket_to) = lock_bucket_pair(key_from, key_to); @@ -1000,20 +955,10 @@ unsafe fn unpark_requeue_internal( /// The `filter` and `callback` functions are called while the queue is locked /// and must not panic or call into any function in `parking_lot`. #[inline] -pub unsafe fn unpark_filter(key: usize, mut filter: F, callback: C) -> UnparkResult -where - F: FnMut(ParkToken) -> FilterOp, - C: FnOnce(UnparkResult) -> UnparkToken, -{ - let mut c = Some(callback); - unpark_filter_internal(key, &mut filter, &mut |r| c.take().unchecked_unwrap()(r)) -} - -// Non-generic version to reduce monomorphization cost -unsafe fn unpark_filter_internal( +pub unsafe fn unpark_filter( key: usize, - filter: &mut FnMut(ParkToken) -> FilterOp, - callback: &mut FnMut(UnparkResult) -> UnparkToken, + mut filter: impl FnMut(ParkToken) -> FilterOp, + callback: impl FnOnce(UnparkResult) -> UnparkToken, ) -> UnparkResult { // Lock the bucket for the given key let bucket = lock_bucket(key); @@ -1094,16 +1039,6 @@ pub mod deadlock { #[cfg(feature = "deadlock_detection")] pub(super) use super::deadlock_impl::DeadlockData; - #[cfg(not(feature = "deadlock_detection"))] - pub(super) struct DeadlockData {} - - #[cfg(not(feature = "deadlock_detection"))] - impl DeadlockData { - pub(super) fn new() -> Self { - DeadlockData {} - } - } - /// Acquire a resource identified by key in the deadlock detector /// Noop if deadlock_detection feature isn't enabled. /// Note: Call after the resource is acquired @@ -1141,7 +1076,9 @@ pub mod deadlock { #[cfg(feature = "deadlock_detection")] mod deadlock_impl { - use super::{get_hashtable, get_thread_data, lock_bucket, ThreadData, NUM_THREADS}; + use super::{get_hashtable, lock_bucket, with_thread_data, ThreadData, NUM_THREADS}; + use crate::thread_parker::{ThreadParkerT, UnparkHandleT}; + use crate::word_lock::WordLock; use backtrace::Backtrace; use petgraph; use petgraph::graphmap::DiGraphMap; @@ -1214,19 +1151,19 @@ mod deadlock_impl { } pub unsafe fn acquire_resource(key: usize) { - let mut thread_data = None; - let thread_data = get_thread_data(&mut thread_data); - (*thread_data.deadlock_data.resources.get()).push(key); + with_thread_data(|thread_data| { + (*thread_data.deadlock_data.resources.get()).push(key); + }); } pub unsafe fn release_resource(key: usize) { - let mut thread_data = None; - let thread_data = get_thread_data(&mut thread_data); - let resources = &mut (*thread_data.deadlock_data.resources.get()); - match resources.iter().rposition(|x| *x == key) { - Some(p) => resources.swap_remove(p), - None => panic!("key {} not found in thread resources", key), - }; + with_thread_data(|thread_data| { + let resources = &mut (*thread_data.deadlock_data.resources.get()); + match resources.iter().rposition(|x| *x == key) { + Some(p) => resources.swap_remove(p), + None => panic!("key {} not found in thread resources", key), + }; + }); } pub fn check_deadlock() -> Vec> { @@ -1283,6 +1220,9 @@ mod deadlock_impl { // Returns all detected thread wait cycles. // Note that once a cycle is reported it's never reported again. unsafe fn check_wait_graph_slow() -> Vec> { + static DEADLOCK_DETECTION_LOCK: WordLock = WordLock::INIT; + DEADLOCK_DETECTION_LOCK.lock(); + let mut table = get_hashtable(); loop { // Lock all buckets in the old table @@ -1356,6 +1296,8 @@ mod deadlock_impl { results.push(receiver.iter().collect()); } + DEADLOCK_DETECTION_LOCK.unlock(); + results } diff --git a/vendor/parking_lot_core/src/spinwait.rs b/vendor/parking_lot_core/src/spinwait.rs index 4185026888..ad0327a3ae 100644 --- a/vendor/parking_lot_core/src/spinwait.rs +++ b/vendor/parking_lot_core/src/spinwait.rs @@ -5,53 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -#[cfg(unix)] -use libc; +use crate::thread_parker; use std::sync::atomic::spin_loop_hint; -#[cfg(not(any(windows, unix)))] -use std::thread; -#[cfg(windows)] -use winapi; - -// Yields the rest of the current timeslice to the OS -#[cfg(windows)] -#[inline] -fn thread_yield() { - // Note that this is manually defined here rather than using the definition - // through `winapi`. The `winapi` definition comes from the `synchapi` - // header which enables the "synchronization.lib" library. It turns out, - // however that `Sleep` comes from `kernel32.dll` so this activation isn't - // necessary. - // - // This was originally identified in rust-lang/rust where on MinGW the - // libsynchronization.a library pulls in a dependency on a newer DLL not - // present in older versions of Windows. (see rust-lang/rust#49438) - // - // This is a bit of a hack for now and ideally we'd fix MinGW's own import - // libraries, but that'll probably take a lot longer than patching this here - // and avoiding the `synchapi` feature entirely. - extern "system" { - fn Sleep(a: winapi::shared::minwindef::DWORD); - } - unsafe { - // We don't use SwitchToThread here because it doesn't consider all - // threads in the system and the thread we are waiting for may not get - // selected. - Sleep(0); - } -} -#[cfg(unix)] -#[inline] -fn thread_yield() { - unsafe { - libc::sched_yield(); - } -} -#[cfg(not(any(windows, unix)))] -#[inline] -fn thread_yield() { - thread::yield_now(); -} // Wastes some CPU time for the given number of iterations, // using a hint to indicate to the CPU that we are spinning. @@ -63,6 +18,7 @@ fn cpu_relax(iterations: u32) { } /// A counter used to perform exponential backoff in spin loops. +#[derive(Default)] pub struct SpinWait { counter: u32, } @@ -70,8 +26,8 @@ pub struct SpinWait { impl SpinWait { /// Creates a new `SpinWait`. #[inline] - pub fn new() -> SpinWait { - SpinWait { counter: 0 } + pub fn new() -> Self { + Self::default() } /// Resets a `SpinWait` to its initial state. @@ -97,7 +53,7 @@ impl SpinWait { if self.counter <= 3 { cpu_relax(1 << self.counter); } else { - thread_yield(); + thread_parker::thread_yield(); } true } @@ -116,10 +72,3 @@ impl SpinWait { cpu_relax(1 << self.counter); } } - -impl Default for SpinWait { - #[inline] - fn default() -> SpinWait { - SpinWait::new() - } -} diff --git a/vendor/parking_lot_core/src/thread_parker/cloudabi.rs b/vendor/parking_lot_core/src/thread_parker/cloudabi.rs new file mode 100644 index 0000000000..d5be2f26cb --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/cloudabi.rs @@ -0,0 +1,298 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use cloudabi as abi; +use core::{ + cell::Cell, + mem, + sync::atomic::{AtomicU32, Ordering}, +}; +use std::{convert::TryFrom, thread, time::Instant}; + +extern "C" { + #[thread_local] + static __pthread_thread_id: abi::tid; +} + +struct Lock { + lock: AtomicU32, +} + +impl Lock { + pub fn new() -> Self { + Lock { + lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), + } + } + + /// # Safety + /// + /// See `Lock::lock`. + unsafe fn try_lock(&self) -> Option { + // Attempt to acquire the lock. + if let Err(old) = self.lock.compare_exchange( + abi::LOCK_UNLOCKED.0, + __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, + Ordering::Acquire, + Ordering::Relaxed, + ) { + // Failure. Crash upon recursive acquisition. + debug_assert_ne!( + old & !abi::LOCK_KERNEL_MANAGED.0, + __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, + "Attempted to recursive write-lock a lock", + ); + None + } else { + Some(LockGuard { lock: &self.lock }) + } + } + + /// # Safety + /// + /// This method is unsafe because the `LockGuard` has a raw pointer into this `Lock` + /// that it will access on drop to unlock the lock. So make sure the `LockGuard` goes + /// out of scope before the `Lock` it came from moves or goes out of scope. + pub unsafe fn lock(&self) -> LockGuard { + self.try_lock().unwrap_or_else(|| { + // Call into the kernel to acquire a write lock. + let subscription = abi::subscription { + type_: abi::eventtype::LOCK_WRLOCK, + union: abi::subscription_union { + lock: abi::subscription_lock { + lock: self.ptr(), + lock_scope: abi::scope::PRIVATE, + }, + }, + ..mem::zeroed() + }; + let mut event: abi::event = mem::uninitialized(); + let mut nevents: usize = mem::uninitialized(); + let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + debug_assert_eq!(ret, abi::errno::SUCCESS); + debug_assert_eq!(event.error, abi::errno::SUCCESS); + + LockGuard { lock: &self.lock } + }) + } + + fn ptr(&self) -> *mut abi::lock { + &self.lock as *const AtomicU32 as *mut abi::lock + } +} + +struct LockGuard { + lock: *const AtomicU32, +} + +impl LockGuard { + fn ptr(&self) -> *mut abi::lock { + self.lock as *mut abi::lock + } +} + +impl Drop for LockGuard { + fn drop(&mut self) { + let lock = unsafe { &*self.lock }; + debug_assert_eq!( + lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0, + unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0, + "This lock is not write-locked by this thread" + ); + + if !lock + .compare_exchange( + unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0, + abi::LOCK_UNLOCKED.0, + Ordering::Release, + Ordering::Relaxed, + ) + .is_ok() + { + // Lock is managed by kernelspace. Call into the kernel + // to unblock waiting threads. + let ret = unsafe { abi::lock_unlock(self.lock as *mut abi::lock, abi::scope::PRIVATE) }; + debug_assert_eq!(ret, abi::errno::SUCCESS); + } + } +} + +struct Condvar { + condvar: AtomicU32, +} + +impl Condvar { + pub fn new() -> Self { + Condvar { + condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0), + } + } + + pub fn wait(&self, lock: &LockGuard) { + unsafe { + let subscription = abi::subscription { + type_: abi::eventtype::CONDVAR, + union: abi::subscription_union { + condvar: abi::subscription_condvar { + condvar: self.ptr(), + condvar_scope: abi::scope::PRIVATE, + lock: lock.ptr(), + lock_scope: abi::scope::PRIVATE, + }, + }, + ..mem::zeroed() + }; + let mut event: abi::event = mem::uninitialized(); + let mut nevents: usize = mem::uninitialized(); + + let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + debug_assert_eq!(ret, abi::errno::SUCCESS); + debug_assert_eq!(event.error, abi::errno::SUCCESS); + } + } + + /// Waits for a signal on the condvar. + /// Returns false if it times out before anyone notified us. + pub fn wait_timeout(&self, lock: &LockGuard, timeout: abi::timestamp) -> bool { + unsafe { + let subscriptions = [ + abi::subscription { + type_: abi::eventtype::CONDVAR, + union: abi::subscription_union { + condvar: abi::subscription_condvar { + condvar: self.ptr(), + condvar_scope: abi::scope::PRIVATE, + lock: lock.ptr(), + lock_scope: abi::scope::PRIVATE, + }, + }, + ..mem::zeroed() + }, + abi::subscription { + type_: abi::eventtype::CLOCK, + union: abi::subscription_union { + clock: abi::subscription_clock { + clock_id: abi::clockid::MONOTONIC, + timeout, + ..mem::zeroed() + }, + }, + ..mem::zeroed() + }, + ]; + let mut events: [abi::event; 2] = mem::uninitialized(); + let mut nevents: usize = mem::uninitialized(); + + let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents); + debug_assert_eq!(ret, abi::errno::SUCCESS); + for i in 0..nevents { + debug_assert_eq!(events[i].error, abi::errno::SUCCESS); + if events[i].type_ == abi::eventtype::CONDVAR { + return true; + } + } + } + false + } + + pub fn notify(&self) { + let ret = unsafe { abi::condvar_signal(self.ptr(), abi::scope::PRIVATE, 1) }; + debug_assert_eq!(ret, abi::errno::SUCCESS); + } + + fn ptr(&self) -> *mut abi::condvar { + &self.condvar as *const AtomicU32 as *mut abi::condvar + } +} + +// Helper type for putting a thread to sleep until some other thread wakes it up +pub struct ThreadParker { + should_park: Cell, + lock: Lock, + condvar: Condvar, +} + +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + fn new() -> ThreadParker { + ThreadParker { + should_park: Cell::new(false), + lock: Lock::new(), + condvar: Condvar::new(), + } + } + + unsafe fn prepare_park(&self) { + self.should_park.set(true); + } + + unsafe fn timed_out(&self) -> bool { + // We need to grab the lock here because another thread may be + // concurrently executing UnparkHandle::unpark, which is done without + // holding the queue lock. + let _guard = self.lock.lock(); + self.should_park.get() + } + + unsafe fn park(&self) { + let guard = self.lock.lock(); + while self.should_park.get() { + self.condvar.wait(&guard); + } + } + + unsafe fn park_until(&self, timeout: Instant) -> bool { + let guard = self.lock.lock(); + while self.should_park.get() { + if let Some(duration_left) = timeout.checked_duration_since(Instant::now()) { + if let Ok(nanos_left) = abi::timestamp::try_from(duration_left.as_nanos()) { + self.condvar.wait_timeout(&guard, nanos_left); + } else { + // remaining timeout overflows an abi::timestamp. Sleep indefinitely + self.condvar.wait(&guard); + } + } else { + // We timed out + return false; + } + } + true + } + + unsafe fn unpark_lock(&self) -> UnparkHandle { + let _lock_guard = self.lock.lock(); + + UnparkHandle { + thread_parker: self, + _lock_guard, + } + } +} + +pub struct UnparkHandle { + thread_parker: *const ThreadParker, + _lock_guard: LockGuard, +} + +impl super::UnparkHandleT for UnparkHandle { + unsafe fn unpark(self) { + (*self.thread_parker).should_park.set(false); + + // We notify while holding the lock here to avoid races with the target + // thread. In particular, the thread could exit after we unlock the + // mutex, which would make the condvar access invalid memory. + (*self.thread_parker).condvar.notify(); + } +} + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/generic.rs b/vendor/parking_lot_core/src/thread_parker/generic.rs index d06406a23f..3ee837ac6f 100644 --- a/vendor/parking_lot_core/src/thread_parker/generic.rs +++ b/vendor/parking_lot_core/src/thread_parker/generic.rs @@ -5,94 +5,73 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::cell::Cell; -use std::sync::{Condvar, Mutex, MutexGuard}; -use std::time::Instant; +//! A simple spin lock based thread parker. Used on platforms without better +//! parking facilities available. + +use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering}; +use std::{thread, time::Instant}; // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { - should_park: Cell, - mutex: Mutex<()>, - condvar: Condvar, + parked: AtomicBool, } -impl ThreadParker { - pub fn new() -> ThreadParker { +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] + fn new() -> ThreadParker { ThreadParker { - should_park: Cell::new(false), - mutex: Mutex::new(()), - condvar: Condvar::new(), + parked: AtomicBool::new(false), } } - // Prepares the parker. This should be called before adding it to the queue. - pub unsafe fn prepare_park(&self) { - self.should_park.set(true); + #[inline] + unsafe fn prepare_park(&self) { + self.parked.store(true, Ordering::Relaxed); } - // Checks if the park timed out. This should be called while holding the - // queue lock after park_until has returned false. - pub unsafe fn timed_out(&self) -> bool { - // We need to grab the mutex here because another thread may be - // concurrently executing UnparkHandle::unpark, which is done without - // holding the queue lock. - let _lock = self.mutex.lock().unwrap(); - self.should_park.get() + #[inline] + unsafe fn timed_out(&self) -> bool { + self.parked.load(Ordering::Relaxed) != false } - // Parks the thread until it is unparked. This should be called after it has - // been added to the queue, after unlocking the queue. - pub unsafe fn park(&self) { - let mut lock = self.mutex.lock().unwrap(); - while self.should_park.get() { - lock = self.condvar.wait(lock).unwrap(); + #[inline] + unsafe fn park(&self) { + while self.parked.load(Ordering::Acquire) != false { + spin_loop_hint(); } } - // Parks the thread until it is unparked or the timeout is reached. This - // should be called after it has been added to the queue, after unlocking - // the queue. Returns true if we were unparked and false if we timed out. - pub unsafe fn park_until(&self, timeout: Instant) -> bool { - let mut lock = self.mutex.lock().unwrap(); - while self.should_park.get() { - let now = Instant::now(); - if timeout <= now { + #[inline] + unsafe fn park_until(&self, timeout: Instant) -> bool { + while self.parked.load(Ordering::Acquire) != false { + if Instant::now() >= timeout { return false; } - let (new_lock, _) = self.condvar.wait_timeout(lock, timeout - now).unwrap(); - lock = new_lock; + spin_loop_hint(); } true } - // Locks the parker to prevent the target thread from exiting. This is - // necessary to ensure that thread-local ThreadData objects remain valid. - // This should be called while holding the queue lock. - pub unsafe fn unpark_lock(&self) -> UnparkHandle { - UnparkHandle { - thread_parker: self, - _guard: self.mutex.lock().unwrap(), - } + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { + // We don't need to lock anything, just clear the state + self.parked.store(false, Ordering::Release); + UnparkHandle(()) } } -// Handle for a thread that is about to be unparked. We need to mark the thread -// as unparked while holding the queue lock, but we delay the actual unparking -// until after the queue lock is released. -pub struct UnparkHandle<'a> { - thread_parker: *const ThreadParker, - _guard: MutexGuard<'a, ()>, -} +pub struct UnparkHandle(()); -impl<'a> UnparkHandle<'a> { - // Wakes up the parked thread. This should be called after the queue lock is - // released to avoid blocking the queue for too long. - pub unsafe fn unpark(self) { - (*self.thread_parker).should_park.set(false); +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) {} +} - // We notify while holding the lock here to avoid races with the target - // thread. In particular, the thread could exit after we unlock the - // mutex, which would make the condvar access invalid memory. - (*self.thread_parker).condvar.notify_one(); - } +#[inline] +pub fn thread_yield() { + thread::yield_now(); } diff --git a/vendor/parking_lot_core/src/thread_parker/linux.rs b/vendor/parking_lot_core/src/thread_parker/linux.rs index 4a13d7309e..04f66a737f 100644 --- a/vendor/parking_lot_core/src/thread_parker/linux.rs +++ b/vendor/parking_lot_core/src/thread_parker/linux.rs @@ -5,13 +5,12 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use core::{ + ptr, + sync::atomic::{AtomicI32, Ordering}, +}; use libc; -use std::sync::atomic::{AtomicI32, Ordering}; -use std::time::Instant; - -const FUTEX_WAIT: i32 = 0; -const FUTEX_WAKE: i32 = 1; -const FUTEX_PRIVATE: i32 = 128; +use std::{thread, time::Instant}; // x32 Linux uses a non-standard type for tv_nsec in timespec. // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 @@ -22,54 +21,53 @@ type tv_nsec_t = i64; #[allow(non_camel_case_types)] type tv_nsec_t = libc::c_long; +fn errno() -> libc::c_int { + #[cfg(target_os = "linux")] + unsafe { + *libc::__errno_location() + } + #[cfg(target_os = "android")] + unsafe { + *libc::__errno() + } +} + // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { futex: AtomicI32, } -impl ThreadParker { - pub fn new() -> ThreadParker { +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] + fn new() -> ThreadParker { ThreadParker { futex: AtomicI32::new(0), } } - // Prepares the parker. This should be called before adding it to the queue. - pub unsafe fn prepare_park(&self) { + #[inline] + unsafe fn prepare_park(&self) { self.futex.store(1, Ordering::Relaxed); } - // Checks if the park timed out. This should be called while holding the - // queue lock after park_until has returned false. - pub unsafe fn timed_out(&self) -> bool { + #[inline] + unsafe fn timed_out(&self) -> bool { self.futex.load(Ordering::Relaxed) != 0 } - // Parks the thread until it is unparked. This should be called after it has - // been added to the queue, after unlocking the queue. - pub unsafe fn park(&self) { + #[inline] + unsafe fn park(&self) { while self.futex.load(Ordering::Acquire) != 0 { - let r = libc::syscall( - libc::SYS_futex, - &self.futex, - FUTEX_WAIT | FUTEX_PRIVATE, - 1, - 0, - ); - debug_assert!(r == 0 || r == -1); - if r == -1 { - debug_assert!( - *libc::__errno_location() == libc::EINTR - || *libc::__errno_location() == libc::EAGAIN - ); - } + self.futex_wait(None); } } - // Parks the thread until it is unparked or the timeout is reached. This - // should be called after it has been added to the queue, after unlocking - // the queue. Returns true if we were unparked and false if we timed out. - pub unsafe fn park_until(&self, timeout: Instant) -> bool { + #[inline] + unsafe fn park_until(&self, timeout: Instant) -> bool { while self.futex.load(Ordering::Acquire) != 0 { let now = Instant::now(); if timeout <= now { @@ -85,21 +83,7 @@ impl ThreadParker { tv_sec: diff.as_secs() as libc::time_t, tv_nsec: diff.subsec_nanos() as tv_nsec_t, }; - let r = libc::syscall( - libc::SYS_futex, - &self.futex, - FUTEX_WAIT | FUTEX_PRIVATE, - 1, - &ts, - ); - debug_assert!(r == 0 || r == -1); - if r == -1 { - debug_assert!( - *libc::__errno_location() == libc::EINTR - || *libc::__errno_location() == libc::EAGAIN - || *libc::__errno_location() == libc::ETIMEDOUT - ); - } + self.futex_wait(Some(ts)); } true } @@ -107,7 +91,8 @@ impl ThreadParker { // Locks the parker to prevent the target thread from exiting. This is // necessary to ensure that thread-local ThreadData objects remain valid. // This should be called while holding the queue lock. - pub unsafe fn unpark_lock(&self) -> UnparkHandle { + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { // We don't need to lock anything, just clear the state self.futex.store(0, Ordering::Release); @@ -115,23 +100,56 @@ impl ThreadParker { } } -// Handle for a thread that is about to be unparked. We need to mark the thread -// as unparked while holding the queue lock, but we delay the actual unparking -// until after the queue lock is released. +impl ThreadParker { + #[inline] + fn futex_wait(&self, ts: Option) { + let ts_ptr = ts + .as_ref() + .map(|ts_ref| ts_ref as *const _) + .unwrap_or(ptr::null()); + let r = unsafe { + libc::syscall( + libc::SYS_futex, + &self.futex, + libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG, + 1, + ts_ptr, + ) + }; + debug_assert!(r == 0 || r == -1); + if r == -1 { + debug_assert!( + errno() == libc::EINTR + || errno() == libc::EAGAIN + || (ts.is_some() && errno() == libc::ETIMEDOUT) + ); + } + } +} + pub struct UnparkHandle { futex: *const AtomicI32, } -impl UnparkHandle { - // Wakes up the parked thread. This should be called after the queue lock is - // released to avoid blocking the queue for too long. - pub unsafe fn unpark(self) { +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) { // The thread data may have been freed at this point, but it doesn't // matter since the syscall will just return EFAULT in that case. - let r = libc::syscall(libc::SYS_futex, self.futex, FUTEX_WAKE | FUTEX_PRIVATE, 1); + let r = libc::syscall( + libc::SYS_futex, + self.futex, + libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, + 1, + ); debug_assert!(r == 0 || r == 1 || r == -1); if r == -1 { - debug_assert_eq!(*libc::__errno_location(), libc::EFAULT); + debug_assert_eq!(errno(), libc::EFAULT); } } } + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/mod.rs b/vendor/parking_lot_core/src/thread_parker/mod.rs new file mode 100644 index 0000000000..f39d639ef4 --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/mod.rs @@ -0,0 +1,89 @@ +use cfg_if::cfg_if; +use std::time::Instant; + +/// Trait for the platform thread parker implementation. +/// +/// All unsafe methods are unsafe because the Unix thread parker is based on +/// pthread mutexes and condvars. Those primitives must not be moved and used +/// from any other memory address than the one they were located at when they +/// were initialized. As such, it's UB to call any unsafe method on +/// `ThreadParkerT` if the implementing instance has moved since the last +/// call to any of the unsafe methods. +pub trait ThreadParkerT { + type UnparkHandle: UnparkHandleT; + + const IS_CHEAP_TO_CONSTRUCT: bool; + + fn new() -> Self; + + /// Prepares the parker. This should be called before adding it to the queue. + unsafe fn prepare_park(&self); + + /// Checks if the park timed out. This should be called while holding the + /// queue lock after park_until has returned false. + unsafe fn timed_out(&self) -> bool; + + /// Parks the thread until it is unparked. This should be called after it has + /// been added to the queue, after unlocking the queue. + unsafe fn park(&self); + + /// Parks the thread until it is unparked or the timeout is reached. This + /// should be called after it has been added to the queue, after unlocking + /// the queue. Returns true if we were unparked and false if we timed out. + unsafe fn park_until(&self, timeout: Instant) -> bool; + + /// Locks the parker to prevent the target thread from exiting. This is + /// necessary to ensure that thread-local ThreadData objects remain valid. + /// This should be called while holding the queue lock. + unsafe fn unpark_lock(&self) -> Self::UnparkHandle; +} + +/// Handle for a thread that is about to be unparked. We need to mark the thread +/// as unparked while holding the queue lock, but we delay the actual unparking +/// until after the queue lock is released. +pub trait UnparkHandleT { + /// Wakes up the parked thread. This should be called after the queue lock is + /// released to avoid blocking the queue for too long. + /// + /// This method is unsafe for the same reason as the unsafe methods in + /// `ThreadParkerT`. + #[inline] + unsafe fn unpark(self); +} + +cfg_if! { + if #[cfg(all(has_sized_atomics, any(target_os = "linux", target_os = "android")))] { + #[path = "linux.rs"] + mod imp; + } else if #[cfg(unix)] { + #[path = "unix.rs"] + mod imp; + } else if #[cfg(windows)] { + #[path = "windows/mod.rs"] + mod imp; + } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] { + #[path = "redox.rs"] + mod imp; + } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] { + #[path = "sgx.rs"] + mod imp; + } else if #[cfg(all( + feature = "nightly", + target_arch = "wasm32", + target_feature = "atomics" + ))] { + #[path = "wasm_atomic.rs"] + mod imp; + } else if #[cfg(target_arch = "wasm32")] { + #[path = "wasm.rs"] + mod imp; + } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] { + #[path = "cloudabi.rs"] + mod imp; + } else { + #[path = "generic.rs"] + mod imp; + } +} + +pub use self::imp::{thread_yield, ThreadParker, UnparkHandle}; diff --git a/vendor/parking_lot_core/src/thread_parker/redox.rs b/vendor/parking_lot_core/src/thread_parker/redox.rs new file mode 100644 index 0000000000..97ffc8adc0 --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/redox.rs @@ -0,0 +1,138 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::{ + ptr, + sync::atomic::{AtomicI32, Ordering}, +}; +use std::{thread, time::Instant}; +use syscall::{ + call::futex, + data::TimeSpec, + error::{Error, EAGAIN, EFAULT, EINTR, ETIMEDOUT}, + flag::{FUTEX_WAIT, FUTEX_WAKE}, +}; + +const UNPARKED: i32 = 0; +const PARKED: i32 = 1; + +// Helper type for putting a thread to sleep until some other thread wakes it up +pub struct ThreadParker { + futex: AtomicI32, +} + +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] + fn new() -> ThreadParker { + ThreadParker { + futex: AtomicI32::new(UNPARKED), + } + } + + #[inline] + unsafe fn prepare_park(&self) { + self.futex.store(PARKED, Ordering::Relaxed); + } + + #[inline] + unsafe fn timed_out(&self) -> bool { + self.futex.load(Ordering::Relaxed) != UNPARKED + } + + #[inline] + unsafe fn park(&self) { + while self.futex.load(Ordering::Acquire) != UNPARKED { + self.futex_wait(None); + } + } + + #[inline] + unsafe fn park_until(&self, timeout: Instant) -> bool { + while self.futex.load(Ordering::Acquire) != UNPARKED { + let now = Instant::now(); + if timeout <= now { + return false; + } + let diff = timeout - now; + if diff.as_secs() > i64::max_value() as u64 { + // Timeout overflowed, just sleep indefinitely + self.park(); + return true; + } + let ts = TimeSpec { + tv_sec: diff.as_secs() as i64, + tv_nsec: diff.subsec_nanos() as i32, + }; + self.futex_wait(Some(ts)); + } + true + } + + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { + // We don't need to lock anything, just clear the state + self.futex.store(UNPARKED, Ordering::Release); + + UnparkHandle { futex: self.ptr() } + } +} + +impl ThreadParker { + #[inline] + fn futex_wait(&self, ts: Option) { + let ts_ptr = ts + .as_ref() + .map(|ts_ref| ts_ref as *const _) + .unwrap_or(ptr::null()); + let r = unsafe { + futex( + self.ptr(), + FUTEX_WAIT, + PARKED, + ts_ptr as usize, + ptr::null_mut(), + ) + }; + match r { + Ok(r) => debug_assert_eq!(r, 0), + Err(Error { errno }) => { + debug_assert!(errno == EINTR || errno == EAGAIN || errno == ETIMEDOUT); + } + } + } + + #[inline] + fn ptr(&self) -> *mut i32 { + &self.futex as *const AtomicI32 as *mut i32 + } +} + +pub struct UnparkHandle { + futex: *mut i32, +} + +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) { + // The thread data may have been freed at this point, but it doesn't + // matter since the syscall will just return EFAULT in that case. + let r = futex(self.futex, FUTEX_WAKE, PARKED, 0, ptr::null_mut()); + match r { + Ok(num_woken) => debug_assert!(num_woken == 0 || num_woken == 1), + Err(Error { errno }) => debug_assert_eq!(errno, EFAULT), + } + } +} + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/sgx.rs b/vendor/parking_lot_core/src/thread_parker/sgx.rs new file mode 100644 index 0000000000..56fc65a208 --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/sgx.rs @@ -0,0 +1,94 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::sync::atomic::{AtomicBool, Ordering}; +use std::{ + io, + os::fortanix_sgx::{ + thread::current as current_tcs, + usercalls::{ + self, + raw::{Tcs, EV_UNPARK, WAIT_INDEFINITE}, + }, + }, + thread, + time::Instant, +}; + +// Helper type for putting a thread to sleep until some other thread wakes it up +pub struct ThreadParker { + parked: AtomicBool, + tcs: Tcs, +} + +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] + fn new() -> ThreadParker { + ThreadParker { + parked: AtomicBool::new(false), + tcs: current_tcs(), + } + } + + #[inline] + unsafe fn prepare_park(&self) { + self.parked.store(true, Ordering::Relaxed); + } + + #[inline] + unsafe fn timed_out(&self) -> bool { + self.parked.load(Ordering::Relaxed) + } + + #[inline] + unsafe fn park(&self) { + while self.parked.load(Ordering::Acquire) { + let result = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE); + debug_assert_eq!(result.expect("wait returned error") & EV_UNPARK, EV_UNPARK); + } + } + + #[inline] + unsafe fn park_until(&self, _timeout: Instant) -> bool { + // FIXME: https://github.com/fortanix/rust-sgx/issues/31 + panic!("timeout not supported in SGX"); + } + + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { + // We don't need to lock anything, just clear the state + self.parked.store(false, Ordering::Release); + UnparkHandle(self.tcs) + } +} + +pub struct UnparkHandle(Tcs); + +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) { + let result = usercalls::send(EV_UNPARK, Some(self.0)); + if cfg!(debug_assertions) { + if let Err(error) = result { + // `InvalidInput` may be returned if the thread we send to has + // already been unparked and exited. + if error.kind() != io::ErrorKind::InvalidInput { + panic!("send returned an unexpected error: {:?}", error); + } + } + } + } +} + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/unix.rs b/vendor/parking_lot_core/src/thread_parker/unix.rs index 169586b56e..42c0f3124d 100644 --- a/vendor/parking_lot_core/src/thread_parker/unix.rs +++ b/vendor/parking_lot_core/src/thread_parker/unix.rs @@ -5,12 +5,17 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use libc; -use std::cell::{Cell, UnsafeCell}; -use std::mem; #[cfg(any(target_os = "macos", target_os = "ios"))] -use std::ptr; -use std::time::{Duration, Instant}; +use core::ptr; +use core::{ + cell::{Cell, UnsafeCell}, + mem, +}; +use libc; +use std::{ + thread, + time::{Duration, Instant}, +}; // x32 Linux uses a non-standard type for tv_nsec in timespec. // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 @@ -29,8 +34,13 @@ pub struct ThreadParker { initialized: Cell, } -impl ThreadParker { - pub fn new() -> ThreadParker { +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = false; + + #[inline] + fn new() -> ThreadParker { ThreadParker { should_park: Cell::new(false), mutex: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER), @@ -39,32 +49,8 @@ impl ThreadParker { } } - // Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME. - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "android" - ))] - unsafe fn init(&self) {} - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "android" - )))] - unsafe fn init(&self) { - let mut attr: libc::pthread_condattr_t = mem::uninitialized(); - let r = libc::pthread_condattr_init(&mut attr); - debug_assert_eq!(r, 0); - let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC); - debug_assert_eq!(r, 0); - let r = libc::pthread_cond_init(self.condvar.get(), &attr); - debug_assert_eq!(r, 0); - let r = libc::pthread_condattr_destroy(&mut attr); - debug_assert_eq!(r, 0); - } - - // Prepares the parker. This should be called before adding it to the queue. - pub unsafe fn prepare_park(&self) { + #[inline] + unsafe fn prepare_park(&self) { self.should_park.set(true); if !self.initialized.get() { self.init(); @@ -72,9 +58,8 @@ impl ThreadParker { } } - // Checks if the park timed out. This should be called while holding the - // queue lock after park_until has returned false. - pub unsafe fn timed_out(&self) -> bool { + #[inline] + unsafe fn timed_out(&self) -> bool { // We need to grab the mutex here because another thread may be // concurrently executing UnparkHandle::unpark, which is done without // holding the queue lock. @@ -86,9 +71,8 @@ impl ThreadParker { should_park } - // Parks the thread until it is unparked. This should be called after it has - // been added to the queue, after unlocking the queue. - pub unsafe fn park(&self) { + #[inline] + unsafe fn park(&self) { let r = libc::pthread_mutex_lock(self.mutex.get()); debug_assert_eq!(r, 0); while self.should_park.get() { @@ -99,10 +83,8 @@ impl ThreadParker { debug_assert_eq!(r, 0); } - // Parks the thread until it is unparked or the timeout is reached. This - // should be called after it has been added to the queue, after unlocking - // the queue. Returns true if we were unparked and false if we timed out. - pub unsafe fn park_until(&self, timeout: Instant) -> bool { + #[inline] + unsafe fn park_until(&self, timeout: Instant) -> bool { let r = libc::pthread_mutex_lock(self.mutex.get()); debug_assert_eq!(r, 0); while self.should_park.get() { @@ -134,10 +116,8 @@ impl ThreadParker { true } - // Locks the parker to prevent the target thread from exiting. This is - // necessary to ensure that thread-local ThreadData objects remain valid. - // This should be called while holding the queue lock. - pub unsafe fn unpark_lock(&self) -> UnparkHandle { + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { let r = libc::pthread_mutex_lock(self.mutex.get()); debug_assert_eq!(r, 0); @@ -147,7 +127,30 @@ impl ThreadParker { } } +impl ThreadParker { + /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME. + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))] + #[inline] + unsafe fn init(&self) {} + + /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME. + #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))] + #[inline] + unsafe fn init(&self) { + let mut attr: libc::pthread_condattr_t = mem::uninitialized(); + let r = libc::pthread_condattr_init(&mut attr); + debug_assert_eq!(r, 0); + let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC); + debug_assert_eq!(r, 0); + let r = libc::pthread_cond_init(self.condvar.get(), &attr); + debug_assert_eq!(r, 0); + let r = libc::pthread_condattr_destroy(&mut attr); + debug_assert_eq!(r, 0); + } +} + impl Drop for ThreadParker { + #[inline] fn drop(&mut self) { // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. @@ -170,17 +173,13 @@ impl Drop for ThreadParker { } } -// Handle for a thread that is about to be unparked. We need to mark the thread -// as unparked while holding the queue lock, but we delay the actual unparking -// until after the queue lock is released. pub struct UnparkHandle { thread_parker: *const ThreadParker, } -impl UnparkHandle { - // Wakes up the parked thread. This should be called after the queue lock is - // released to avoid blocking the queue for too long. - pub unsafe fn unpark(self) { +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) { (*self.thread_parker).should_park.set(false); // We notify while holding the lock here to avoid races with the target @@ -195,9 +194,10 @@ impl UnparkHandle { // Returns the current time on the clock used by pthread_cond_t as a timespec. #[cfg(any(target_os = "macos", target_os = "ios"))] -unsafe fn timespec_now() -> libc::timespec { - let mut now: libc::timeval = mem::uninitialized(); - let r = libc::gettimeofday(&mut now, ptr::null_mut()); +#[inline] +fn timespec_now() -> libc::timespec { + let mut now: libc::timeval = unsafe { mem::uninitialized() }; + let r = unsafe { libc::gettimeofday(&mut now, ptr::null_mut()) }; debug_assert_eq!(r, 0); libc::timespec { tv_sec: now.tv_sec, @@ -205,8 +205,9 @@ unsafe fn timespec_now() -> libc::timespec { } } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -unsafe fn timespec_now() -> libc::timespec { - let mut now: libc::timespec = mem::uninitialized(); +#[inline] +fn timespec_now() -> libc::timespec { + let mut now: libc::timespec = unsafe { mem::uninitialized() }; let clock = if cfg!(target_os = "android") { // Android doesn't support pthread_condattr_setclock, so we need to // specify the timeout in CLOCK_REALTIME. @@ -214,14 +215,15 @@ unsafe fn timespec_now() -> libc::timespec { } else { libc::CLOCK_MONOTONIC }; - let r = libc::clock_gettime(clock, &mut now); + let r = unsafe { libc::clock_gettime(clock, &mut now) }; debug_assert_eq!(r, 0); now } // Converts a relative timeout into an absolute timeout in the clock used by // pthread_cond_t. -unsafe fn timeout_to_timespec(timeout: Duration) -> Option { +#[inline] +fn timeout_to_timespec(timeout: Duration) -> Option { // Handle overflows early on if timeout.as_secs() > libc::time_t::max_value() as u64 { return None; @@ -240,3 +242,8 @@ unsafe fn timeout_to_timespec(timeout: Duration) -> Option { tv_sec: sec, }) } + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/wasm.rs b/vendor/parking_lot_core/src/thread_parker/wasm.rs new file mode 100644 index 0000000000..f91a218cfe --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/wasm.rs @@ -0,0 +1,53 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +//! The wasm platform can't park when atomic support is not available. +//! So this ThreadParker just panics on any attempt to park. + +use std::{thread, time::Instant}; + +pub struct ThreadParker(()); + +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + fn new() -> ThreadParker { + ThreadParker(()) + } + + unsafe fn prepare_park(&self) { + panic!("Parking not supported on this platform"); + } + + unsafe fn timed_out(&self) -> bool { + panic!("Parking not supported on this platform"); + } + + unsafe fn park(&self) { + panic!("Parking not supported on this platform"); + } + + unsafe fn park_until(&self, _timeout: Instant) -> bool { + panic!("Parking not supported on this platform"); + } + + unsafe fn unpark_lock(&self) -> UnparkHandle { + panic!("Parking not supported on this platform"); + } +} + +pub struct UnparkHandle(()); + +impl super::UnparkHandleT for UnparkHandle { + unsafe fn unpark(self) {} +} + +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/wasm_atomic.rs b/vendor/parking_lot_core/src/thread_parker/wasm_atomic.rs new file mode 100644 index 0000000000..37f302708f --- /dev/null +++ b/vendor/parking_lot_core/src/thread_parker/wasm_atomic.rs @@ -0,0 +1,96 @@ +// Copyright 2016 Amanieu d'Antras +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use core::{ + arch::wasm32, + sync::atomic::{AtomicI32, Ordering}, +}; +use std::{convert::TryFrom, thread, time::Instant}; + +// Helper type for putting a thread to sleep until some other thread wakes it up +pub struct ThreadParker { + parked: AtomicI32, +} + +const UNPARKED: i32 = 0; +const PARKED: i32 = 1; + +impl super::ThreadParkerT for ThreadParker { + type UnparkHandle = UnparkHandle; + + const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] + fn new() -> ThreadParker { + ThreadParker { + parked: AtomicI32::new(UNPARKED), + } + } + + #[inline] + unsafe fn prepare_park(&self) { + self.parked.store(PARKED, Ordering::Relaxed); + } + + #[inline] + unsafe fn timed_out(&self) -> bool { + self.parked.load(Ordering::Relaxed) == PARKED + } + + #[inline] + unsafe fn park(&self) { + while self.parked.load(Ordering::Acquire) == PARKED { + let r = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, -1) }; + // we should have either woken up (0) or got a not-equal due to a + // race (1). We should never time out (2) + debug_assert!(r == 0 || r == 1); + } + } + + #[inline] + unsafe fn park_until(&self, timeout: Instant) -> bool { + while self.parked.load(Ordering::Acquire) == PARKED { + if let Some(left) = timeout.checked_duration_since(Instant::now()) { + let nanos_left = i64::try_from(left.as_nanos()).unwrap_or(i64::max_value()); + let r = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, nanos_left) }; + debug_assert!(r == 0 || r == 1 || r == 2); + } else { + return false; + } + } + true + } + + #[inline] + unsafe fn unpark_lock(&self) -> UnparkHandle { + // We don't need to lock anything, just clear the state + self.parked.store(UNPARKED, Ordering::Release); + UnparkHandle(self.ptr()) + } +} + +impl ThreadParker { + #[inline] + fn ptr(&self) -> *mut i32 { + &self.parked as *const AtomicI32 as *mut i32 + } +} + +pub struct UnparkHandle(*mut i32); + +impl super::UnparkHandleT for UnparkHandle { + #[inline] + unsafe fn unpark(self) { + let num_notified = unsafe { wasm32::atomic_notify(self.0 as *mut i32, 1) }; + debug_assert!(num_notified == 0 || num_notified == 1); + } +} + +#[inline] +pub fn thread_yield() { + thread::yield_now(); +} diff --git a/vendor/parking_lot_core/src/thread_parker/windows/keyed_event.rs b/vendor/parking_lot_core/src/thread_parker/windows/keyed_event.rs index 0e32fced1e..71b55f0f3e 100644 --- a/vendor/parking_lot_core/src/thread_parker/windows/keyed_event.rs +++ b/vendor/parking_lot_core/src/thread_parker/windows/keyed_event.rs @@ -5,18 +5,26 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::mem; -use std::ptr; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Instant; - -use winapi::shared::minwindef::{TRUE, ULONG}; -use winapi::shared::ntdef::NTSTATUS; -use winapi::shared::ntstatus::{STATUS_SUCCESS, STATUS_TIMEOUT}; -use winapi::um::handleapi::CloseHandle; -use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress}; -use winapi::um::winnt::{ACCESS_MASK, GENERIC_READ, GENERIC_WRITE, LPCSTR}; -use winapi::um::winnt::{BOOLEAN, HANDLE, LARGE_INTEGER, PHANDLE, PLARGE_INTEGER, PVOID}; +use core::{mem, ptr}; +use std::{ + sync::atomic::{AtomicUsize, Ordering}, + time::Instant, +}; +use winapi::{ + shared::{ + minwindef::{TRUE, ULONG}, + ntdef::NTSTATUS, + ntstatus::{STATUS_SUCCESS, STATUS_TIMEOUT}, + }, + um::{ + handleapi::CloseHandle, + libloaderapi::{GetModuleHandleA, GetProcAddress}, + winnt::{ + ACCESS_MASK, BOOLEAN, GENERIC_READ, GENERIC_WRITE, HANDLE, LARGE_INTEGER, LPCSTR, + PHANDLE, PLARGE_INTEGER, PVOID, + }, + }, +}; const STATE_UNPARKED: usize = 0; const STATE_PARKED: usize = 1; @@ -40,73 +48,82 @@ pub struct KeyedEvent { } impl KeyedEvent { + #[inline] unsafe fn wait_for(&self, key: PVOID, timeout: PLARGE_INTEGER) -> NTSTATUS { (self.NtWaitForKeyedEvent)(self.handle, key, 0, timeout) } + #[inline] unsafe fn release(&self, key: PVOID) -> NTSTATUS { (self.NtReleaseKeyedEvent)(self.handle, key, 0, ptr::null_mut()) } #[allow(non_snake_case)] - pub unsafe fn create() -> Option { - let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR); - if ntdll.is_null() { - return None; - } + pub fn create() -> Option { + unsafe { + let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR); + if ntdll.is_null() { + return None; + } - let NtCreateKeyedEvent = GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR); - if NtCreateKeyedEvent.is_null() { - return None; - } - let NtReleaseKeyedEvent = - GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR); - if NtReleaseKeyedEvent.is_null() { - return None; - } - let NtWaitForKeyedEvent = - GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR); - if NtWaitForKeyedEvent.is_null() { - return None; - } + let NtCreateKeyedEvent = + GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR); + if NtCreateKeyedEvent.is_null() { + return None; + } + let NtReleaseKeyedEvent = + GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR); + if NtReleaseKeyedEvent.is_null() { + return None; + } + let NtWaitForKeyedEvent = + GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR); + if NtWaitForKeyedEvent.is_null() { + return None; + } - let NtCreateKeyedEvent: extern "system" fn( - KeyedEventHandle: PHANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: PVOID, - Flags: ULONG, - ) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent); - let mut handle = mem::uninitialized(); - let status = NtCreateKeyedEvent( - &mut handle, - GENERIC_READ | GENERIC_WRITE, - ptr::null_mut(), - 0, - ); - if status != STATUS_SUCCESS { - return None; - } + let NtCreateKeyedEvent: extern "system" fn( + KeyedEventHandle: PHANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: PVOID, + Flags: ULONG, + ) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent); + let mut handle = mem::uninitialized(); + let status = NtCreateKeyedEvent( + &mut handle, + GENERIC_READ | GENERIC_WRITE, + ptr::null_mut(), + 0, + ); + if status != STATUS_SUCCESS { + return None; + } - Some(KeyedEvent { - handle, - NtReleaseKeyedEvent: mem::transmute(NtReleaseKeyedEvent), - NtWaitForKeyedEvent: mem::transmute(NtWaitForKeyedEvent), - }) + Some(KeyedEvent { + handle, + NtReleaseKeyedEvent: mem::transmute(NtReleaseKeyedEvent), + NtWaitForKeyedEvent: mem::transmute(NtWaitForKeyedEvent), + }) + } } - pub unsafe fn prepare_park(&'static self, key: &AtomicUsize) { + #[inline] + pub fn prepare_park(&'static self, key: &AtomicUsize) { key.store(STATE_PARKED, Ordering::Relaxed); } - pub unsafe fn timed_out(&'static self, key: &AtomicUsize) -> bool { + #[inline] + pub fn timed_out(&'static self, key: &AtomicUsize) -> bool { key.load(Ordering::Relaxed) == STATE_TIMED_OUT } + #[inline] pub unsafe fn park(&'static self, key: &AtomicUsize) { let status = self.wait_for(key as *const _ as PVOID, ptr::null_mut()); debug_assert_eq!(status, STATUS_SUCCESS); } + #[inline] pub unsafe fn park_until(&'static self, key: &AtomicUsize, timeout: Instant) -> bool { let now = Instant::now(); if timeout <= now { @@ -152,6 +169,7 @@ impl KeyedEvent { false } + #[inline] pub unsafe fn unpark_lock(&'static self, key: &AtomicUsize) -> UnparkHandle { // If the state was STATE_PARKED then we need to wake up the thread if key.swap(STATE_UNPARKED, Ordering::Relaxed) == STATE_PARKED { @@ -169,6 +187,7 @@ impl KeyedEvent { } impl Drop for KeyedEvent { + #[inline] fn drop(&mut self) { unsafe { let ok = CloseHandle(self.handle); @@ -188,6 +207,7 @@ pub struct UnparkHandle { impl UnparkHandle { // Wakes up the parked thread. This should be called after the queue lock is // released to avoid blocking the queue for too long. + #[inline] pub unsafe fn unpark(self) { if !self.key.is_null() { let status = self.keyed_event.release(self.key as PVOID); diff --git a/vendor/parking_lot_core/src/thread_parker/windows/mod.rs b/vendor/parking_lot_core/src/thread_parker/windows/mod.rs index a91ab61b5c..9db1652445 100644 --- a/vendor/parking_lot_core/src/thread_parker/windows/mod.rs +++ b/vendor/parking_lot_core/src/thread_parker/windows/mod.rs @@ -5,7 +5,10 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; +use core::{ + ptr, + sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, +}; use std::time::Instant; mod keyed_event; @@ -16,16 +19,22 @@ enum Backend { WaitAddress(waitaddress::WaitAddress), } -impl Backend { - unsafe fn get() -> &'static Backend { - static BACKEND: AtomicUsize = ATOMIC_USIZE_INIT; +static BACKEND: AtomicPtr = AtomicPtr::new(ptr::null_mut()); +impl Backend { + #[inline] + fn get() -> &'static Backend { // Fast path: use the existing object - let backend = BACKEND.load(Ordering::Acquire); - if backend != 0 { - return &*(backend as *const Backend); + let backend_ptr = BACKEND.load(Ordering::Acquire); + if !backend_ptr.is_null() { + return unsafe { &*backend_ptr }; }; + Backend::create() + } + + #[cold] + fn create() -> &'static Backend { // Try to create a new Backend let backend; if let Some(waitaddress) = waitaddress::WaitAddress::create() { @@ -39,14 +48,21 @@ impl Backend { ); } - // Try to create a new object - let backend = Box::into_raw(Box::new(backend)); - match BACKEND.compare_exchange(0, backend as usize, Ordering::Release, Ordering::Relaxed) { - Ok(_) => &*(backend as *const Backend), - Err(x) => { - // We lost the race, free our object and return the global one - Box::from_raw(backend); - &*(x as *const Backend) + // Try to set our new Backend as the global one + let backend_ptr = Box::into_raw(Box::new(backend)); + match BACKEND.compare_exchange( + ptr::null_mut(), + backend_ptr, + Ordering::Release, + Ordering::Relaxed, + ) { + Ok(_) => unsafe { &*backend_ptr }, + Err(global_backend_ptr) => { + unsafe { + // We lost the race, free our object and return the global one + Box::from_raw(backend_ptr); + &*global_backend_ptr + } } } } @@ -59,18 +75,22 @@ pub struct ThreadParker { } impl ThreadParker { + pub const IS_CHEAP_TO_CONSTRUCT: bool = true; + + #[inline] pub fn new() -> ThreadParker { // Initialize the backend here to ensure we don't get any panics // later on, which could leave synchronization primitives in a broken // state. ThreadParker { key: AtomicUsize::new(0), - backend: unsafe { Backend::get() }, + backend: Backend::get(), } } // Prepares the parker. This should be called before adding it to the queue. - pub unsafe fn prepare_park(&self) { + #[inline] + pub fn prepare_park(&self) { match *self.backend { Backend::KeyedEvent(ref x) => x.prepare_park(&self.key), Backend::WaitAddress(ref x) => x.prepare_park(&self.key), @@ -79,7 +99,8 @@ impl ThreadParker { // Checks if the park timed out. This should be called while holding the // queue lock after park_until has returned false. - pub unsafe fn timed_out(&self) -> bool { + #[inline] + pub fn timed_out(&self) -> bool { match *self.backend { Backend::KeyedEvent(ref x) => x.timed_out(&self.key), Backend::WaitAddress(ref x) => x.timed_out(&self.key), @@ -88,6 +109,7 @@ impl ThreadParker { // Parks the thread until it is unparked. This should be called after it has // been added to the queue, after unlocking the queue. + #[inline] pub unsafe fn park(&self) { match *self.backend { Backend::KeyedEvent(ref x) => x.park(&self.key), @@ -98,6 +120,7 @@ impl ThreadParker { // Parks the thread until it is unparked or the timeout is reached. This // should be called after it has been added to the queue, after unlocking // the queue. Returns true if we were unparked and false if we timed out. + #[inline] pub unsafe fn park_until(&self, timeout: Instant) -> bool { match *self.backend { Backend::KeyedEvent(ref x) => x.park_until(&self.key, timeout), @@ -108,6 +131,7 @@ impl ThreadParker { // Locks the parker to prevent the target thread from exiting. This is // necessary to ensure that thread-local ThreadData objects remain valid. // This should be called while holding the queue lock. + #[inline] pub unsafe fn unpark_lock(&self) -> UnparkHandle { match *self.backend { Backend::KeyedEvent(ref x) => UnparkHandle::KeyedEvent(x.unpark_lock(&self.key)), @@ -127,6 +151,7 @@ pub enum UnparkHandle { impl UnparkHandle { // Wakes up the parked thread. This should be called after the queue lock is // released to avoid blocking the queue for too long. + #[inline] pub unsafe fn unpark(self) { match self { UnparkHandle::KeyedEvent(x) => x.unpark(), @@ -134,3 +159,30 @@ impl UnparkHandle { } } } + +// Yields the rest of the current timeslice to the OS +#[inline] +pub fn thread_yield() { + // Note that this is manually defined here rather than using the definition + // through `winapi`. The `winapi` definition comes from the `synchapi` + // header which enables the "synchronization.lib" library. It turns out, + // however that `Sleep` comes from `kernel32.dll` so this activation isn't + // necessary. + // + // This was originally identified in rust-lang/rust where on MinGW the + // libsynchronization.a library pulls in a dependency on a newer DLL not + // present in older versions of Windows. (see rust-lang/rust#49438) + // + // This is a bit of a hack for now and ideally we'd fix MinGW's own import + // libraries, but that'll probably take a lot longer than patching this here + // and avoiding the `synchapi` feature entirely. + extern "system" { + fn Sleep(a: winapi::shared::minwindef::DWORD); + } + unsafe { + // We don't use SwitchToThread here because it doesn't consider all + // threads in the system and the thread we are waiting for may not get + // selected. + Sleep(0); + } +} diff --git a/vendor/parking_lot_core/src/thread_parker/windows/waitaddress.rs b/vendor/parking_lot_core/src/thread_parker/windows/waitaddress.rs index 1d9fca836c..0ec780404d 100644 --- a/vendor/parking_lot_core/src/thread_parker/windows/waitaddress.rs +++ b/vendor/parking_lot_core/src/thread_parker/windows/waitaddress.rs @@ -5,17 +5,24 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::mem; -use std::sync::atomic::{AtomicUsize, Ordering}; +use core::{ + mem, + sync::atomic::{AtomicUsize, Ordering}, +}; use std::time::Instant; - -use winapi::shared::basetsd::SIZE_T; -use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE}; -use winapi::shared::winerror::ERROR_TIMEOUT; -use winapi::um::errhandlingapi::GetLastError; -use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress}; -use winapi::um::winbase::INFINITE; -use winapi::um::winnt::{LPCSTR, PVOID}; +use winapi::{ + shared::{ + basetsd::SIZE_T, + minwindef::{BOOL, DWORD, FALSE, TRUE}, + winerror::ERROR_TIMEOUT, + }, + um::{ + errhandlingapi::GetLastError, + libloaderapi::{GetModuleHandleA, GetProcAddress}, + winbase::INFINITE, + winnt::{LPCSTR, PVOID}, + }, +}; #[allow(non_snake_case)] pub struct WaitAddress { @@ -30,51 +37,52 @@ pub struct WaitAddress { impl WaitAddress { #[allow(non_snake_case)] - pub unsafe fn create() -> Option { - // MSDN claims that that WaitOnAddress and WakeByAddressSingle are - // located in kernel32.dll, but they are lying... - let synch_dll = GetModuleHandleA(b"api-ms-win-core-synch-l1-2-0.dll\0".as_ptr() as LPCSTR); - if synch_dll.is_null() { - return None; - } + pub fn create() -> Option { + unsafe { + // MSDN claims that that WaitOnAddress and WakeByAddressSingle are + // located in kernel32.dll, but they are lying... + let synch_dll = + GetModuleHandleA(b"api-ms-win-core-synch-l1-2-0.dll\0".as_ptr() as LPCSTR); + if synch_dll.is_null() { + return None; + } - let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr() as LPCSTR); - if WaitOnAddress.is_null() { - return None; - } - let WakeByAddressSingle = - GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr() as LPCSTR); - if WakeByAddressSingle.is_null() { - return None; + let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr() as LPCSTR); + if WaitOnAddress.is_null() { + return None; + } + let WakeByAddressSingle = + GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr() as LPCSTR); + if WakeByAddressSingle.is_null() { + return None; + } + Some(WaitAddress { + WaitOnAddress: mem::transmute(WaitOnAddress), + WakeByAddressSingle: mem::transmute(WakeByAddressSingle), + }) } - Some(WaitAddress { - WaitOnAddress: mem::transmute(WaitOnAddress), - WakeByAddressSingle: mem::transmute(WakeByAddressSingle), - }) } - pub unsafe fn prepare_park(&'static self, key: &AtomicUsize) { + #[inline] + pub fn prepare_park(&'static self, key: &AtomicUsize) { key.store(1, Ordering::Relaxed); } - pub unsafe fn timed_out(&'static self, key: &AtomicUsize) -> bool { + #[inline] + pub fn timed_out(&'static self, key: &AtomicUsize) -> bool { key.load(Ordering::Relaxed) != 0 } - pub unsafe fn park(&'static self, key: &AtomicUsize) { + #[inline] + pub fn park(&'static self, key: &AtomicUsize) { while key.load(Ordering::Acquire) != 0 { - let cmp = 1usize; - let r = (self.WaitOnAddress)( - key as *const _ as PVOID, - &cmp as *const _ as PVOID, - mem::size_of::() as SIZE_T, - INFINITE, - ); + let r = self.wait_on_address(key, INFINITE); debug_assert!(r == TRUE); } } - pub unsafe fn park_until(&'static self, key: &AtomicUsize, timeout: Instant) -> bool { + #[inline] + pub fn park_until(&'static self, key: &AtomicUsize, timeout: Instant) -> bool { while key.load(Ordering::Acquire) != 0 { let now = Instant::now(); if timeout <= now { @@ -91,22 +99,17 @@ impl WaitAddress { } else { ms as DWORD } - }).unwrap_or(INFINITE); - let cmp = 1usize; - let r = (self.WaitOnAddress)( - key as *const _ as PVOID, - &cmp as *const _ as PVOID, - mem::size_of::() as SIZE_T, - timeout, - ); - if r == FALSE { - debug_assert_eq!(GetLastError(), ERROR_TIMEOUT); + }) + .unwrap_or(INFINITE); + if self.wait_on_address(key, timeout) == FALSE { + debug_assert_eq!(unsafe { GetLastError() }, ERROR_TIMEOUT); } } true } - pub unsafe fn unpark_lock(&'static self, key: &AtomicUsize) -> UnparkHandle { + #[inline] + pub fn unpark_lock(&'static self, key: &AtomicUsize) -> UnparkHandle { // We don't need to lock anything, just clear the state key.store(0, Ordering::Release); @@ -115,6 +118,17 @@ impl WaitAddress { waitaddress: self, } } + + #[inline] + fn wait_on_address(&'static self, key: &AtomicUsize, timeout: DWORD) -> BOOL { + let cmp = 1usize; + (self.WaitOnAddress)( + key as *const _ as PVOID, + &cmp as *const _ as PVOID, + mem::size_of::() as SIZE_T, + timeout, + ) + } } // Handle for a thread that is about to be unparked. We need to mark the thread @@ -128,7 +142,8 @@ pub struct UnparkHandle { impl UnparkHandle { // Wakes up the parked thread. This should be called after the queue lock is // released to avoid blocking the queue for too long. - pub unsafe fn unpark(self) { + #[inline] + pub fn unpark(self) { (self.waitaddress.WakeByAddressSingle)(self.key as PVOID); } } diff --git a/vendor/parking_lot_core/src/util.rs b/vendor/parking_lot_core/src/util.rs index c7dfd32250..d7aaa87155 100644 --- a/vendor/parking_lot_core/src/util.rs +++ b/vendor/parking_lot_core/src/util.rs @@ -20,13 +20,12 @@ impl UncheckedOptionExt for Option { } } -// Equivalent to intrinsics::unreachable() in release mode +// hint::unreachable_unchecked() in release mode #[inline] unsafe fn unreachable() -> ! { if cfg!(debug_assertions) { unreachable!(); } else { - enum Void {} - match *(1 as *const Void) {} + core::hint::unreachable_unchecked() } } diff --git a/vendor/parking_lot_core/src/word_lock.rs b/vendor/parking_lot_core/src/word_lock.rs index 79605680d0..9b1411de1e 100644 --- a/vendor/parking_lot_core/src/word_lock.rs +++ b/vendor/parking_lot_core/src/word_lock.rs @@ -5,15 +5,13 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use spinwait::SpinWait; -use std::cell::Cell; -use std::mem; -#[cfg(not(has_localkey_try_with))] -use std::panic; -use std::ptr; -use std::sync::atomic::{fence, AtomicUsize, Ordering}; -use std::thread::LocalKey; -use thread_parker::ThreadParker; +use crate::spinwait::SpinWait; +use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT}; +use core::{ + cell::Cell, + mem, ptr, + sync::atomic::{fence, AtomicUsize, Ordering}, +}; struct ThreadData { parker: ThreadParker, @@ -36,7 +34,9 @@ struct ThreadData { } impl ThreadData { + #[inline] fn new() -> ThreadData { + assert!(mem::align_of::() > !QUEUE_MASK); ThreadData { parker: ThreadParker::new(), queue_tail: Cell::new(ptr::null()), @@ -46,31 +46,25 @@ impl ThreadData { } } -// Returns a ThreadData structure for the current thread -unsafe fn get_thread_data(local: &mut Option) -> &ThreadData { - // Try to read from thread-local storage, but return None if the TLS has - // already been destroyed. - #[cfg(has_localkey_try_with)] - fn try_get_tls(key: &'static LocalKey) -> Option<*const ThreadData> { - key.try_with(|x| x as *const ThreadData).ok() - } - #[cfg(not(has_localkey_try_with))] - fn try_get_tls(key: &'static LocalKey) -> Option<*const ThreadData> { - panic::catch_unwind(|| key.with(|x| x as *const ThreadData)).ok() - } - +// Invokes the given closure with a reference to the current thread `ThreadData`. +#[inline] +fn with_thread_data(f: impl FnOnce(&ThreadData) -> T) -> T { + let mut thread_data_ptr = ptr::null(); // If ThreadData is expensive to construct, then we want to use a cached // version in thread-local storage if possible. - if !cfg!(windows) && !cfg!(all(feature = "nightly", target_os = "linux")) { + if !ThreadParker::IS_CHEAP_TO_CONSTRUCT { thread_local!(static THREAD_DATA: ThreadData = ThreadData::new()); - if let Some(tls) = try_get_tls(&THREAD_DATA) { - return &*tls; + if let Ok(tls_thread_data) = THREAD_DATA.try_with(|x| x as *const ThreadData) { + thread_data_ptr = tls_thread_data; } } - // Otherwise just create a ThreadData on the stack - *local = Some(ThreadData::new()); - local.as_ref().unwrap() + let mut thread_data_storage = None; + if thread_data_ptr.is_null() { + thread_data_ptr = thread_data_storage.get_or_insert_with(ThreadData::new); + } + + f(unsafe { &*thread_data_ptr }) } const LOCKED_BIT: usize = 1; @@ -84,15 +78,12 @@ pub struct WordLock { } impl WordLock { - #[inline] - pub fn new() -> WordLock { - WordLock { - state: AtomicUsize::new(0), - } - } + pub const INIT: WordLock = WordLock { + state: AtomicUsize::new(0), + }; #[inline] - pub unsafe fn lock(&self) { + pub fn lock(&self) { if self .state .compare_exchange_weak(0, LOCKED_BIT, Ordering::Acquire, Ordering::Relaxed) @@ -103,23 +94,23 @@ impl WordLock { self.lock_slow(); } + /// Must not be called on an already unlocked `WordLock`! #[inline] pub unsafe fn unlock(&self) { let state = self.state.fetch_sub(LOCKED_BIT, Ordering::Release); - if state & QUEUE_LOCKED_BIT != 0 || state & QUEUE_MASK == 0 { + if state.is_queue_locked() || state.queue_head().is_null() { return; } self.unlock_slow(); } #[cold] - #[inline(never)] - unsafe fn lock_slow(&self) { + fn lock_slow(&self) { let mut spinwait = SpinWait::new(); let mut state = self.state.load(Ordering::Relaxed); loop { // Grab the lock if it isn't locked, even if there is a queue on it - if state & LOCKED_BIT == 0 { + if !state.is_locked() { match self.state.compare_exchange_weak( state, state | LOCKED_BIT, @@ -133,55 +124,61 @@ impl WordLock { } // If there is no queue, try spinning a few times - if state & QUEUE_MASK == 0 && spinwait.spin() { + if state.queue_head().is_null() && spinwait.spin() { state = self.state.load(Ordering::Relaxed); continue; } // Get our thread data and prepare it for parking - let mut thread_data = None; - let thread_data = get_thread_data(&mut thread_data); - assert!(mem::align_of_val(thread_data) > !QUEUE_MASK); - thread_data.parker.prepare_park(); + state = with_thread_data(|thread_data| { + // The pthread implementation is still unsafe, so we need to surround `prepare_park` + // with `unsafe {}`. + #[allow(unused_unsafe)] + unsafe { + thread_data.parker.prepare_park(); + } - // Add our thread to the front of the queue - let queue_head = (state & QUEUE_MASK) as *const ThreadData; - if queue_head.is_null() { - thread_data.queue_tail.set(thread_data); - thread_data.prev.set(ptr::null()); - } else { - thread_data.queue_tail.set(ptr::null()); - thread_data.prev.set(ptr::null()); - thread_data.next.set(queue_head); - } - if let Err(x) = self.state.compare_exchange_weak( - state, - (state & !QUEUE_MASK) | thread_data as *const _ as usize, - Ordering::Release, - Ordering::Relaxed, - ) { - state = x; - continue; - } + // Add our thread to the front of the queue + let queue_head = state.queue_head(); + if queue_head.is_null() { + thread_data.queue_tail.set(thread_data); + thread_data.prev.set(ptr::null()); + } else { + thread_data.queue_tail.set(ptr::null()); + thread_data.prev.set(ptr::null()); + thread_data.next.set(queue_head); + } + if let Err(x) = self.state.compare_exchange_weak( + state, + state.with_queue_head(thread_data), + Ordering::Release, + Ordering::Relaxed, + ) { + return x; + } - // Sleep until we are woken up by an unlock - thread_data.parker.park(); + // Sleep until we are woken up by an unlock + // Ignoring unused unsafe, since it's only a few platforms where this is unsafe. + #[allow(unused_unsafe)] + unsafe { + thread_data.parker.park(); + } - // Loop back and try locking again - spinwait.reset(); - self.state.load(Ordering::Relaxed); + // Loop back and try locking again + spinwait.reset(); + self.state.load(Ordering::Relaxed) + }); } } #[cold] - #[inline(never)] - unsafe fn unlock_slow(&self) { + fn unlock_slow(&self) { let mut state = self.state.load(Ordering::Relaxed); loop { // We just unlocked the WordLock. Just check if there is a thread // to wake up. If the queue is locked then another thread is already // taking care of waking up a thread. - if state & QUEUE_LOCKED_BIT != 0 || state & QUEUE_MASK == 0 { + if state.is_queue_locked() || state.queue_head().is_null() { return; } @@ -202,27 +199,31 @@ impl WordLock { // First, we need to fill in the prev pointers for any newly added // threads. We do this until we reach a node that we previously // processed, which has a non-null queue_tail pointer. - let queue_head = (state & QUEUE_MASK) as *const ThreadData; + let queue_head = state.queue_head(); let mut queue_tail; let mut current = queue_head; loop { - queue_tail = (*current).queue_tail.get(); + queue_tail = unsafe { (*current).queue_tail.get() }; if !queue_tail.is_null() { break; } - let next = (*current).next.get(); - (*next).prev.set(current); - current = next; + unsafe { + let next = (*current).next.get(); + (*next).prev.set(current); + current = next; + } } // Set queue_tail on the queue head to indicate that the whole list // has prev pointers set correctly. - (*queue_head).queue_tail.set(queue_tail); + unsafe { + (*queue_head).queue_tail.set(queue_tail); + } // If the WordLock is locked, then there is no point waking up a // thread now. Instead we let the next unlocker take care of waking // up a thread. - if state & LOCKED_BIT != 0 { + if state.is_locked() { match self.state.compare_exchange_weak( state, state & !QUEUE_LOCKED_BIT, @@ -239,7 +240,7 @@ impl WordLock { } // Remove the last thread from the queue and unlock the queue - let new_tail = (*queue_tail).prev.get(); + let new_tail = unsafe { (*queue_tail).prev.get() }; if new_tail.is_null() { loop { match self.state.compare_exchange_weak( @@ -255,7 +256,7 @@ impl WordLock { // If the compare_exchange failed because a new thread was // added to the queue then we need to re-scan the queue to // find the previous element. - if state & QUEUE_MASK == 0 { + if state.queue_head().is_null() { continue; } else { // Need an acquire fence before reading the new queue @@ -264,7 +265,9 @@ impl WordLock { } } } else { - (*queue_head).queue_tail.set(new_tail); + unsafe { + (*queue_head).queue_tail.set(new_tail); + } self.state.fetch_and(!QUEUE_LOCKED_BIT, Ordering::Release); } @@ -272,8 +275,39 @@ impl WordLock { // we don't need to worry about any races here since the thread is // guaranteed to be sleeping right now and we are the only one who // can wake it up. - (*queue_tail).parker.unpark_lock().unpark(); + unsafe { + (*queue_tail).parker.unpark_lock().unpark(); + } break; } } } + +trait LockState { + fn is_locked(self) -> bool; + fn is_queue_locked(self) -> bool; + fn queue_head(self) -> *const ThreadData; + fn with_queue_head(self, thread_data: *const ThreadData) -> Self; +} + +impl LockState for usize { + #[inline] + fn is_locked(self) -> bool { + self & LOCKED_BIT != 0 + } + + #[inline] + fn is_queue_locked(self) -> bool { + self & QUEUE_LOCKED_BIT != 0 + } + + #[inline] + fn queue_head(self) -> *const ThreadData { + (self & QUEUE_MASK) as *const ThreadData + } + + #[inline] + fn with_queue_head(self, thread_data: *const ThreadData) -> Self { + (self & !QUEUE_MASK) | thread_data as *const _ as usize + } +} diff --git a/vendor/polonius-engine/.cargo-checksum.json b/vendor/polonius-engine/.cargo-checksum.json index 575e5b2f5f..f8e34cfead 100644 --- a/vendor/polonius-engine/.cargo-checksum.json +++ b/vendor/polonius-engine/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"18cfb91c631bae15e693216e368566497a109ca4efa6daccad34f2dcc65e49c4","README.md":"fc6752d50a57acbf3d65581c0d2f3d0da8c5fef5735a12857660c9e9687751d0","src/facts.rs":"e38b32939e7d91d4d89368562b8a322094e6419bf79d4800dc2f62b6a03a912a","src/lib.rs":"6672e3a20ecf0e080a137532a8bb0da9c0ba75a49f71ffcc7efd7cbfbe39ca73","src/output/datafrog_opt.rs":"f2f4d60b66554b01edf28730ca73c23db20041e7f49d7e445e29d4c63e8e4917","src/output/hybrid.rs":"5f995b2103c4fea875cbab8f078740c6f012e1e1cc93098a31ff84947f4e77fb","src/output/liveness.rs":"66115b31f56b6bb4099f91a94c7dedc8b92bb69f91149e18b4b3b325cd7b1f8f","src/output/location_insensitive.rs":"a02c764a644447a092622142174b21bd0c05d82e3745982ce5ddeaf10909c38e","src/output/mod.rs":"bf0c3216c992bc311411f42cf3f9622c80a2ecd57f889a1137f56ca704fad646","src/output/naive.rs":"47291ec22146e36473cf9b3d231f16d3be3cd72e057f04f1f151f379302e2bca"},"package":"f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b"} \ No newline at end of file +{"files":{"Cargo.toml":"40f4725af6c105b698db233f69c32f0f617f4de9aeff09fe9ec813b57d2aa0d7","README.md":"fc6752d50a57acbf3d65581c0d2f3d0da8c5fef5735a12857660c9e9687751d0","src/facts.rs":"f0e8388f2afb5e4e7903ff0158eeaa855d81e04bf95d2d4a66746355c48dc3e2","src/lib.rs":"6672e3a20ecf0e080a137532a8bb0da9c0ba75a49f71ffcc7efd7cbfbe39ca73","src/output/datafrog_opt.rs":"a0d97fdaa4a54de3c84af353629ebfe50d290e9da0a49277f7e230867da5a3ab","src/output/hybrid.rs":"5dba09e99a9f5d54c2a6008578f9d0b01e1b85be213b413f306a9f7eb5e8f436","src/output/initialization.rs":"9ca9d46d2bdb68781f105b5182d10678fff85b9983c4fc20c32fce92dabe0847","src/output/liveness.rs":"db9d49121232cc6f7244bd8aa77346819ac0a3b33497224e73a26897d8f3489d","src/output/location_insensitive.rs":"a842497f1ffc4bec6a011770ee3e3e860c1040dfbcc41f39cabb06da67d834d6","src/output/mod.rs":"014083f9171f4fcdef7a6b45a775c7bd10997edc8ae3b0d17872d3e703d2ec58","src/output/naive.rs":"326cb9d1220ee8c4b23a256bb4ab664449d709e8b9ff5d441836d230aaaa9e65"},"package":"50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe"} \ No newline at end of file diff --git a/vendor/polonius-engine/Cargo.toml b/vendor/polonius-engine/Cargo.toml index 9a674f1ac5..614a523a8f 100644 --- a/vendor/polonius-engine/Cargo.toml +++ b/vendor/polonius-engine/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "polonius-engine" -version = "0.9.0" +version = "0.10.0" authors = ["The Rust Project Developers", "Polonius Developers"] description = "Core definition for the Rust borrow checker" readme = "README.md" diff --git a/vendor/polonius-engine/src/facts.rs b/vendor/polonius-engine/src/facts.rs index 1985081cea..4e449f9034 100644 --- a/vendor/polonius-engine/src/facts.rs +++ b/vendor/polonius-engine/src/facts.rs @@ -3,7 +3,7 @@ use std::hash::Hash; /// The "facts" which are the basis of the NLL borrow analysis. #[derive(Clone, Debug)] -pub struct AllFacts { +pub struct AllFacts { /// `borrow_region(R, B, P)` -- the region R may refer to data /// from borrow B starting at the point P (this is usually the /// point *after* a borrow rvalue) @@ -21,9 +21,6 @@ pub struct AllFacts { /// `outlives(R1, R2, P)` when we require `R1@P: R2@P` pub outlives: Vec<(R, R, P)>, - /// `region_live_at(R, P)` when the region R appears in a live variable at P - pub region_live_at: Vec<(R, P)>, - /// `invalidates(P, L)` when the loan L is invalidated at point P pub invalidates: Vec<(P, L)>, @@ -43,12 +40,31 @@ pub struct AllFacts { /// it when dropping` pub var_drops_region: Vec<(V, R)>, - /// `var_initialized_on_exit(V, P) when the variable `V` is initialized on - /// exit from point `P` in the program flow. - pub var_initialized_on_exit: Vec<(V, P)>, + /// `child(M1, M2) when the move path `M1` is the direct or transitive child + /// of `M2`, e.g. `child(x.y, x)`, `child(x.y.z, x.y)`, `child(x.y.z, x)` + /// would all be true if there was a path like `x.y.z`. + pub child: Vec<(M, M)>, + + /// `path_belongs_to_var(M, V) the root path `M` starting in variable `V`. + pub path_belongs_to_var: Vec<(M, V)>, + + /// `initialized_at(M, P) when the move path `M` was initialized at point + /// `P`. This fact is only emitted for a prefix `M`, and not for the + /// implicit initialization of all of `M`'s children. E.g. a statement like + /// `x.y = 3` at point `P` would give the fact `initialized_at(x.y, P)` (but + /// neither `initialized_at(x.y.z, P)` nor `initialized_at(x, P)`). + pub initialized_at: Vec<(M, P)>, + + /// `moved_out_at(M, P) when the move path `M` was moved at point `P`. The + /// same logic is applied as for `initialized_at` above. + pub moved_out_at: Vec<(M, P)>, + + /// `path_accessed_at(M, P) when the move path `M` was accessed at point + /// `P`. The same logic as for `initialized_at` and `moved_out_at` applies. + pub path_accessed_at: Vec<(M, P)>, } -impl Default for AllFacts { +impl Default for AllFacts { fn default() -> Self { AllFacts { borrow_region: Vec::default(), @@ -56,14 +72,17 @@ impl Default for AllFacts { cfg_edge: Vec::default(), killed: Vec::default(), outlives: Vec::default(), - region_live_at: Vec::default(), invalidates: Vec::default(), var_used: Vec::default(), var_defined: Vec::default(), var_drop_used: Vec::default(), var_uses_region: Vec::default(), var_drops_region: Vec::default(), - var_initialized_on_exit: Vec::default(), + child: Vec::default(), + path_belongs_to_var: Vec::default(), + initialized_at: Vec::default(), + moved_out_at: Vec::default(), + path_accessed_at: Vec::default(), } } } diff --git a/vendor/polonius-engine/src/output/datafrog_opt.rs b/vendor/polonius-engine/src/output/datafrog_opt.rs index a921269b3c..c07c96be95 100644 --- a/vendor/polonius-engine/src/output/datafrog_opt.rs +++ b/vendor/polonius-engine/src/output/datafrog_opt.rs @@ -11,26 +11,37 @@ use std::collections::{BTreeMap, BTreeSet}; use std::time::Instant; +use crate::output::initialization; use crate::output::liveness; use crate::output::Output; use datafrog::{Iteration, Relation, RelationLeaper}; use facts::{AllFacts, Atom}; -pub(super) fn compute( +pub(super) fn compute( dump_enabled: bool, - all_facts: AllFacts, -) -> Output { + all_facts: AllFacts, +) -> Output { let mut result = Output::new(dump_enabled); + + let var_maybe_initialized_on_exit = initialization::init_var_maybe_initialized_on_exit( + all_facts.child, + all_facts.path_belongs_to_var, + all_facts.initialized_at, + all_facts.moved_out_at, + all_facts.path_accessed_at, + &all_facts.cfg_edge, + &mut result, + ); + let region_live_at = liveness::init_region_live_at( all_facts.var_used, all_facts.var_drop_used, all_facts.var_defined, all_facts.var_uses_region, all_facts.var_drops_region, - all_facts.var_initialized_on_exit, + var_maybe_initialized_on_exit, &all_facts.cfg_edge, - all_facts.region_live_at, all_facts.universal_region, &mut result, ); diff --git a/vendor/polonius-engine/src/output/hybrid.rs b/vendor/polonius-engine/src/output/hybrid.rs index fdcd581e66..f6c817ba7f 100644 --- a/vendor/polonius-engine/src/output/hybrid.rs +++ b/vendor/polonius-engine/src/output/hybrid.rs @@ -16,10 +16,10 @@ use crate::output::location_insensitive; use crate::output::Output; use facts::{AllFacts, Atom}; -pub(super) fn compute( +pub(super) fn compute( dump_enabled: bool, - all_facts: AllFacts, -) -> Output { + all_facts: AllFacts, +) -> Output { let lins_output = location_insensitive::compute(dump_enabled, &all_facts); if lins_output.errors.is_empty() { lins_output diff --git a/vendor/polonius-engine/src/output/initialization.rs b/vendor/polonius-engine/src/output/initialization.rs new file mode 100644 index 0000000000..d8a6cb1183 --- /dev/null +++ b/vendor/polonius-engine/src/output/initialization.rs @@ -0,0 +1,145 @@ +use std::time::Instant; + +use crate::output::Output; +use facts::Atom; + +use datafrog::{Iteration, Relation, RelationLeaper}; + +pub(super) fn init_var_maybe_initialized_on_exit( + child: Vec<(MovePath, MovePath)>, + path_belongs_to_var: Vec<(MovePath, Variable)>, + initialized_at: Vec<(MovePath, Point)>, + moved_out_at: Vec<(MovePath, Point)>, + path_accessed_at: Vec<(MovePath, Point)>, + cfg_edge: &[(Point, Point)], + output: &mut Output, +) -> Vec<(Variable, Point)> +where + Region: Atom, + Loan: Atom, + Point: Atom, + Variable: Atom, + MovePath: Atom, +{ + debug!("compute_initialization()"); + let computation_start = Instant::now(); + let mut iteration = Iteration::new(); + + // Relations + //let parent: Relation<(MovePath, MovePath)> = child.iter().map(|&(c, p)| (p, c)).collect(); + let child: Relation<(MovePath, MovePath)> = child.into(); + let path_belongs_to_var: Relation<(MovePath, Variable)> = path_belongs_to_var.into(); + let initialized_at: Relation<(MovePath, Point)> = initialized_at.into(); + let moved_out_at: Relation<(MovePath, Point)> = moved_out_at.into(); + let cfg_edge: Relation<(Point, Point)> = cfg_edge.iter().cloned().collect(); + let _path_accessed_at: Relation<(MovePath, Point)> = path_accessed_at.into(); + + // Variables + + // var_maybe_initialized_on_exit(V, P): Upon leaving `P`, at least one part of the + // variable `V` might be initialized for some path through the CFG. + let var_maybe_initialized_on_exit = + iteration.variable::<(Variable, Point)>("var_maybe_initialized_on_exit"); + + // path_maybe_initialized_on_exit(M, P): Upon leaving `P`, the move path `M` + // might be *partially* initialized for some path through the CFG. + let path_maybe_initialized_on_exit = + iteration.variable::<(MovePath, Point)>("path_maybe_initialized_on_exit"); + + // Initial propagation of static relations + + // path_maybe_initialized_on_exit(Path, Point) :- initialized_at(Path, + // Point). + path_maybe_initialized_on_exit.insert(initialized_at); + + while iteration.changed() { + // path_maybe_initialized_on_exit(M, Q) :- + // path_maybe_initialized_on_exit(M, P), + // cfg_edge(P, Q), + // !moved_out_at(M, Q). + path_maybe_initialized_on_exit.from_leapjoin( + &path_maybe_initialized_on_exit, + ( + cfg_edge.extend_with(|&(_m, p)| p), + moved_out_at.extend_anti(|&(m, _p)| m), + ), + |&(m, _p), &q| (m, q), + ); + + // path_maybe_initialized_on_exit(Mother, P) :- + // path_maybe_initialized_on_exit(Daughter, P), + // child(Daughter, Mother). + path_maybe_initialized_on_exit.from_leapjoin( + &path_maybe_initialized_on_exit, + child.extend_with(|&(daughter, _p)| daughter), + |&(_daughter, p), &mother| (mother, p), + ); + + // TODO: the following lines contain things left to implement for move + // tracking: + + // path_accessed :- path_accessed(M, P). + // + // -- transitive access of all children + // path_accessed(Child, P) :- + // path_accessed(Mother, P), + // parent(Mother, Child). + + // Propagate across CFG edges: + // path_maybe_uninit(M, Q) :- + // path_maybe_uninit(M, P), + // cfg_edge_(P, Q) + // !initialized_at(P, Q). + + // Initial value (static). + // path_maybe_uninit(M, P) :- moved_out_at(M, P). + + // NOTE: Double join! + // errors(M, P) :- + // path_maybe_uninit(M, P), + // path_accessed(M, P). + + // END TODO + + // var_maybe_initialized_on_exit(V, P) :- + // path_belongs_to_var(M, V), + // path_maybe_initialized_at(M, P). + var_maybe_initialized_on_exit.from_leapjoin( + &path_maybe_initialized_on_exit, + path_belongs_to_var.extend_with(|&(m, _p)| m), + |&(_m, p), &v| (v, p), + ); + } + + let var_maybe_initialized_on_exit = var_maybe_initialized_on_exit.complete(); + + info!( + "compute_initialization() completed: {} tuples, {:?}", + var_maybe_initialized_on_exit.len(), + computation_start.elapsed() + ); + + if output.dump_enabled { + let path_maybe_initialized_on_exit = path_maybe_initialized_on_exit.complete(); + for &(path, location) in &path_maybe_initialized_on_exit.elements { + output + .path_maybe_initialized_at + .entry(location) + .or_insert_with(Vec::new) + .push(path); + } + + for &(var, location) in &var_maybe_initialized_on_exit.elements { + output + .var_maybe_initialized_on_exit + .entry(location) + .or_insert_with(Vec::new) + .push(var); + } + } + + var_maybe_initialized_on_exit + .iter() + .map(|&(v, p)| (v, p)) + .collect() +} diff --git a/vendor/polonius-engine/src/output/liveness.rs b/vendor/polonius-engine/src/output/liveness.rs index d823f18d9f..da152e6202 100644 --- a/vendor/polonius-engine/src/output/liveness.rs +++ b/vendor/polonius-engine/src/output/liveness.rs @@ -18,27 +18,40 @@ use facts::Atom; use datafrog::{Iteration, Relation, RelationLeaper}; -pub(super) fn compute_live_regions( +pub(super) fn compute_live_regions( var_used: Vec<(Variable, Point)>, var_drop_used: Vec<(Variable, Point)>, var_defined: Vec<(Variable, Point)>, var_uses_region: Vec<(Variable, Region)>, var_drops_region: Vec<(Variable, Region)>, cfg_edge: &[(Point, Point)], - var_initialized_on_exit: Vec<(Variable, Point)>, - output: &mut Output, -) -> Vec<(Region, Point)> { + var_maybe_initialized_on_exit: Vec<(Variable, Point)>, + output: &mut Output, +) -> Vec<(Region, Point)> +where + Region: Atom, + Loan: Atom, + Point: Atom, + Variable: Atom, + MovePath: Atom, +{ debug!("compute_liveness()"); let computation_start = Instant::now(); let mut iteration = Iteration::new(); // Relations let var_defined_rel: Relation<(Variable, Point)> = var_defined.into(); + let cfg_edge_rel: Relation<(Point, Point)> = cfg_edge.iter().map(|(p, q)| (*p, *q)).collect(); let cfg_edge_reverse_rel: Relation<(Point, Point)> = cfg_edge.iter().map(|(p, q)| (*q, *p)).collect(); let var_uses_region_rel: Relation<(Variable, Region)> = var_uses_region.into(); let var_drops_region_rel: Relation<(Variable, Region)> = var_drops_region.into(); - let var_initialized_on_exit_rel: Relation<(Variable, Point)> = var_initialized_on_exit.into(); + let var_maybe_initialized_on_exit_rel: Relation<(Variable, Point)> = + var_maybe_initialized_on_exit.into(); + let var_drop_used_rel: Relation<((Variable, Point), ())> = var_drop_used + .into_iter() + .map(|(v, p)| ((v, p), ())) + .collect(); // Variables @@ -53,8 +66,23 @@ pub(super) fn compute_live_regions( } } -pub(super) fn init_region_live_at( +pub(super) fn init_region_live_at< + Region: Atom, + Loan: Atom, + Point: Atom, + Variable: Atom, + MovePath: Atom, +>( var_used: Vec<(Variable, Point)>, var_drop_used: Vec<(Variable, Point)>, var_defined: Vec<(Variable, Point)>, var_uses_region: Vec<(Variable, Region)>, var_drops_region: Vec<(Variable, Region)>, - var_initialized_on_exit: Vec<(Variable, Point)>, + var_maybe_initialized_on_exit: Vec<(Variable, Point)>, cfg_edge: &[(Point, Point)], - region_live_at: Vec<(Region, Point)>, universal_region: Vec, - output: &mut Output, + output: &mut Output, ) -> Vec<(Region, Point)> { debug!("init_region_live_at()"); - let mut region_live_at = if region_live_at.is_empty() { - debug!("no region_live_at facts provided"); - compute_live_regions( - var_used, - var_drop_used, - var_defined, - var_uses_region, - var_drops_region, - cfg_edge, - var_initialized_on_exit, - output, - ) - } else { - debug!("using provided region_live_at facts"); - region_live_at - }; + let mut region_live_at = compute_live_regions( + var_used, + var_drop_used, + var_defined, + var_uses_region, + var_drops_region, + cfg_edge, + var_maybe_initialized_on_exit, + output, + ); make_universal_region_live(&mut region_live_at, cfg_edge, universal_region); diff --git a/vendor/polonius-engine/src/output/location_insensitive.rs b/vendor/polonius-engine/src/output/location_insensitive.rs index 9d78d7d148..519806224d 100644 --- a/vendor/polonius-engine/src/output/location_insensitive.rs +++ b/vendor/polonius-engine/src/output/location_insensitive.rs @@ -11,26 +11,35 @@ use std::collections::BTreeSet; use std::time::Instant; +use crate::output::initialization; use crate::output::liveness; use crate::output::Output; use datafrog::{Iteration, Relation, RelationLeaper}; use facts::{AllFacts, Atom}; -pub(super) fn compute( +pub(super) fn compute( dump_enabled: bool, - all_facts: &AllFacts, -) -> Output { + all_facts: &AllFacts, +) -> Output { let mut result = Output::new(dump_enabled); + let var_maybe_initialized_on_exit = initialization::init_var_maybe_initialized_on_exit( + all_facts.child.clone(), + all_facts.path_belongs_to_var.clone(), + all_facts.initialized_at.clone(), + all_facts.moved_out_at.clone(), + all_facts.path_accessed_at.clone(), + &all_facts.cfg_edge, + &mut result, + ); let region_live_at = liveness::init_region_live_at( all_facts.var_used.clone(), all_facts.var_drop_used.clone(), all_facts.var_defined.clone(), all_facts.var_uses_region.clone(), all_facts.var_drops_region.clone(), - all_facts.var_initialized_on_exit.clone(), + var_maybe_initialized_on_exit.clone(), &all_facts.cfg_edge, - all_facts.region_live_at.clone(), all_facts.universal_region.clone(), &mut result, ); diff --git a/vendor/polonius-engine/src/output/mod.rs b/vendor/polonius-engine/src/output/mod.rs index 900f110172..2b919b3c08 100644 --- a/vendor/polonius-engine/src/output/mod.rs +++ b/vendor/polonius-engine/src/output/mod.rs @@ -14,6 +14,7 @@ use std::collections::{BTreeMap, BTreeSet}; mod datafrog_opt; mod hybrid; +mod initialization; mod liveness; mod location_insensitive; mod naive; @@ -61,7 +62,15 @@ impl ::std::str::FromStr for Algorithm { } #[derive(Clone, Debug)] -pub struct Output { +pub struct Output +where + Region: Atom, + Region: Atom, + Loan: Atom, + Point: Atom, + Variable: Atom, + MovePath: Atom, +{ pub errors: FxHashMap>, pub dump_enabled: bool, @@ -76,6 +85,8 @@ pub struct Output { pub subset_anywhere: FxHashMap>, pub var_live_at: FxHashMap>, pub var_drop_live_at: FxHashMap>, + pub path_maybe_initialized_at: FxHashMap>, + pub var_maybe_initialized_on_exit: FxHashMap>, } /// Compares errors reported by Naive implementation with the errors @@ -114,15 +125,16 @@ fn compare_errors( differ } -impl Output +impl Output where Region: Atom, Loan: Atom, Point: Atom, Variable: Atom, + MovePath: Atom, { pub fn compute( - all_facts: &AllFacts, + all_facts: &AllFacts, algorithm: Algorithm, dump_enabled: bool, ) -> Self { @@ -162,6 +174,8 @@ where subset_anywhere: FxHashMap::default(), var_live_at: FxHashMap::default(), var_drop_live_at: FxHashMap::default(), + path_maybe_initialized_at: FxHashMap::default(), + var_maybe_initialized_on_exit: FxHashMap::default(), dump_enabled, } } diff --git a/vendor/polonius-engine/src/output/naive.rs b/vendor/polonius-engine/src/output/naive.rs index c6098ac562..028fdfd4d3 100644 --- a/vendor/polonius-engine/src/output/naive.rs +++ b/vendor/polonius-engine/src/output/naive.rs @@ -13,27 +13,37 @@ use std::collections::{BTreeMap, BTreeSet}; use std::time::Instant; +use crate::output::initialization; use crate::output::liveness; use crate::output::Output; use facts::{AllFacts, Atom}; use datafrog::{Iteration, Relation, RelationLeaper}; -pub(super) fn compute( +pub(super) fn compute( dump_enabled: bool, - all_facts: AllFacts, -) -> Output { + all_facts: AllFacts, +) -> Output { let mut result = Output::new(dump_enabled); + let var_maybe_initialized_on_exit = initialization::init_var_maybe_initialized_on_exit( + all_facts.child, + all_facts.path_belongs_to_var, + all_facts.initialized_at, + all_facts.moved_out_at, + all_facts.path_accessed_at, + &all_facts.cfg_edge, + &mut result, + ); + let region_live_at = liveness::init_region_live_at( all_facts.var_used, all_facts.var_drop_used, all_facts.var_defined, all_facts.var_uses_region, all_facts.var_drops_region, - all_facts.var_initialized_on_exit, + var_maybe_initialized_on_exit, &all_facts.cfg_edge, - all_facts.region_live_at, all_facts.universal_region, &mut result, ); diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2-0.4.30/.cargo-checksum.json similarity index 100% rename from vendor/proc-macro2/.cargo-checksum.json rename to vendor/proc-macro2-0.4.30/.cargo-checksum.json diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2-0.4.30/Cargo.toml similarity index 100% rename from vendor/proc-macro2/Cargo.toml rename to vendor/proc-macro2-0.4.30/Cargo.toml diff --git a/vendor/proc-macro2/LICENSE-APACHE b/vendor/proc-macro2-0.4.30/LICENSE-APACHE similarity index 100% rename from vendor/proc-macro2/LICENSE-APACHE rename to vendor/proc-macro2-0.4.30/LICENSE-APACHE diff --git a/vendor/proc-macro2/LICENSE-MIT b/vendor/proc-macro2-0.4.30/LICENSE-MIT similarity index 100% rename from vendor/proc-macro2/LICENSE-MIT rename to vendor/proc-macro2-0.4.30/LICENSE-MIT diff --git a/vendor/proc-macro2/README.md b/vendor/proc-macro2-0.4.30/README.md similarity index 100% rename from vendor/proc-macro2/README.md rename to vendor/proc-macro2-0.4.30/README.md diff --git a/vendor/proc-macro2/build.rs b/vendor/proc-macro2-0.4.30/build.rs similarity index 100% rename from vendor/proc-macro2/build.rs rename to vendor/proc-macro2-0.4.30/build.rs diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2-0.4.30/src/fallback.rs similarity index 100% rename from vendor/proc-macro2/src/fallback.rs rename to vendor/proc-macro2-0.4.30/src/fallback.rs diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2-0.4.30/src/lib.rs similarity index 100% rename from vendor/proc-macro2/src/lib.rs rename to vendor/proc-macro2-0.4.30/src/lib.rs diff --git a/vendor/proc-macro2/src/strnom.rs b/vendor/proc-macro2-0.4.30/src/strnom.rs similarity index 100% rename from vendor/proc-macro2/src/strnom.rs rename to vendor/proc-macro2-0.4.30/src/strnom.rs diff --git a/vendor/proc-macro2/src/wrapper.rs b/vendor/proc-macro2-0.4.30/src/wrapper.rs similarity index 100% rename from vendor/proc-macro2/src/wrapper.rs rename to vendor/proc-macro2-0.4.30/src/wrapper.rs diff --git a/vendor/proc-macro2/tests/marker.rs b/vendor/proc-macro2-0.4.30/tests/marker.rs similarity index 100% rename from vendor/proc-macro2/tests/marker.rs rename to vendor/proc-macro2-0.4.30/tests/marker.rs diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2-0.4.30/tests/test.rs similarity index 100% rename from vendor/proc-macro2/tests/test.rs rename to vendor/proc-macro2-0.4.30/tests/test.rs diff --git a/vendor/pulldown-cmark/.cargo-checksum.json b/vendor/pulldown-cmark-0.5.3/.cargo-checksum.json similarity index 100% rename from vendor/pulldown-cmark/.cargo-checksum.json rename to vendor/pulldown-cmark-0.5.3/.cargo-checksum.json diff --git a/vendor/pulldown-cmark/CONTRIBUTING.md b/vendor/pulldown-cmark-0.5.3/CONTRIBUTING.md similarity index 100% rename from vendor/pulldown-cmark/CONTRIBUTING.md rename to vendor/pulldown-cmark-0.5.3/CONTRIBUTING.md diff --git a/vendor/pulldown-cmark/Cargo.toml b/vendor/pulldown-cmark-0.5.3/Cargo.toml similarity index 100% rename from vendor/pulldown-cmark/Cargo.toml rename to vendor/pulldown-cmark-0.5.3/Cargo.toml diff --git a/vendor/pulldown-cmark/LICENSE b/vendor/pulldown-cmark-0.5.3/LICENSE similarity index 100% rename from vendor/pulldown-cmark/LICENSE rename to vendor/pulldown-cmark-0.5.3/LICENSE diff --git a/vendor/pulldown-cmark/README.md b/vendor/pulldown-cmark-0.5.3/README.md similarity index 100% rename from vendor/pulldown-cmark/README.md rename to vendor/pulldown-cmark-0.5.3/README.md diff --git a/vendor/pulldown-cmark/azure-pipelines.yml b/vendor/pulldown-cmark-0.5.3/azure-pipelines.yml similarity index 100% rename from vendor/pulldown-cmark/azure-pipelines.yml rename to vendor/pulldown-cmark-0.5.3/azure-pipelines.yml diff --git a/vendor/pulldown-cmark/benches/html_rendering.rs b/vendor/pulldown-cmark-0.5.3/benches/html_rendering.rs similarity index 100% rename from vendor/pulldown-cmark/benches/html_rendering.rs rename to vendor/pulldown-cmark-0.5.3/benches/html_rendering.rs diff --git a/vendor/pulldown-cmark/benches/lib.rs b/vendor/pulldown-cmark-0.5.3/benches/lib.rs similarity index 100% rename from vendor/pulldown-cmark/benches/lib.rs rename to vendor/pulldown-cmark-0.5.3/benches/lib.rs diff --git a/vendor/pulldown-cmark/build.rs b/vendor/pulldown-cmark-0.5.3/build.rs similarity index 100% rename from vendor/pulldown-cmark/build.rs rename to vendor/pulldown-cmark-0.5.3/build.rs diff --git a/vendor/pulldown-cmark/examples/event-filter.rs b/vendor/pulldown-cmark-0.5.3/examples/event-filter.rs similarity index 100% rename from vendor/pulldown-cmark/examples/event-filter.rs rename to vendor/pulldown-cmark-0.5.3/examples/event-filter.rs diff --git a/vendor/pulldown-cmark/examples/string-to-string.rs b/vendor/pulldown-cmark-0.5.3/examples/string-to-string.rs similarity index 100% rename from vendor/pulldown-cmark/examples/string-to-string.rs rename to vendor/pulldown-cmark-0.5.3/examples/string-to-string.rs diff --git a/vendor/pulldown-cmark/specs/footnotes.txt b/vendor/pulldown-cmark-0.5.3/specs/footnotes.txt similarity index 100% rename from vendor/pulldown-cmark/specs/footnotes.txt rename to vendor/pulldown-cmark-0.5.3/specs/footnotes.txt diff --git a/vendor/pulldown-cmark/specs/regression.txt b/vendor/pulldown-cmark-0.5.3/specs/regression.txt similarity index 100% rename from vendor/pulldown-cmark/specs/regression.txt rename to vendor/pulldown-cmark-0.5.3/specs/regression.txt diff --git a/vendor/pulldown-cmark/specs/table.txt b/vendor/pulldown-cmark-0.5.3/specs/table.txt similarity index 100% rename from vendor/pulldown-cmark/specs/table.txt rename to vendor/pulldown-cmark-0.5.3/specs/table.txt diff --git a/vendor/pulldown-cmark/src/entities.rs b/vendor/pulldown-cmark-0.5.3/src/entities.rs similarity index 100% rename from vendor/pulldown-cmark/src/entities.rs rename to vendor/pulldown-cmark-0.5.3/src/entities.rs diff --git a/vendor/pulldown-cmark/src/escape.rs b/vendor/pulldown-cmark-0.5.3/src/escape.rs similarity index 100% rename from vendor/pulldown-cmark/src/escape.rs rename to vendor/pulldown-cmark-0.5.3/src/escape.rs diff --git a/vendor/pulldown-cmark/src/html.rs b/vendor/pulldown-cmark-0.5.3/src/html.rs similarity index 100% rename from vendor/pulldown-cmark/src/html.rs rename to vendor/pulldown-cmark-0.5.3/src/html.rs diff --git a/vendor/pulldown-cmark/src/lib.rs b/vendor/pulldown-cmark-0.5.3/src/lib.rs similarity index 100% rename from vendor/pulldown-cmark/src/lib.rs rename to vendor/pulldown-cmark-0.5.3/src/lib.rs diff --git a/vendor/pulldown-cmark/src/linklabel.rs b/vendor/pulldown-cmark-0.5.3/src/linklabel.rs similarity index 100% rename from vendor/pulldown-cmark/src/linklabel.rs rename to vendor/pulldown-cmark-0.5.3/src/linklabel.rs diff --git a/vendor/pulldown-cmark/src/main.rs b/vendor/pulldown-cmark-0.5.3/src/main.rs similarity index 100% rename from vendor/pulldown-cmark/src/main.rs rename to vendor/pulldown-cmark-0.5.3/src/main.rs diff --git a/vendor/pulldown-cmark/src/parse.rs b/vendor/pulldown-cmark-0.5.3/src/parse.rs similarity index 100% rename from vendor/pulldown-cmark/src/parse.rs rename to vendor/pulldown-cmark-0.5.3/src/parse.rs diff --git a/vendor/pulldown-cmark/src/puncttable.rs b/vendor/pulldown-cmark-0.5.3/src/puncttable.rs similarity index 100% rename from vendor/pulldown-cmark/src/puncttable.rs rename to vendor/pulldown-cmark-0.5.3/src/puncttable.rs diff --git a/vendor/pulldown-cmark/src/scanners.rs b/vendor/pulldown-cmark-0.5.3/src/scanners.rs similarity index 100% rename from vendor/pulldown-cmark/src/scanners.rs rename to vendor/pulldown-cmark-0.5.3/src/scanners.rs diff --git a/vendor/pulldown-cmark/src/simd.rs b/vendor/pulldown-cmark-0.5.3/src/simd.rs similarity index 100% rename from vendor/pulldown-cmark/src/simd.rs rename to vendor/pulldown-cmark-0.5.3/src/simd.rs diff --git a/vendor/pulldown-cmark/src/strings.rs b/vendor/pulldown-cmark-0.5.3/src/strings.rs similarity index 100% rename from vendor/pulldown-cmark/src/strings.rs rename to vendor/pulldown-cmark-0.5.3/src/strings.rs diff --git a/vendor/pulldown-cmark/src/tree.rs b/vendor/pulldown-cmark-0.5.3/src/tree.rs similarity index 100% rename from vendor/pulldown-cmark/src/tree.rs rename to vendor/pulldown-cmark-0.5.3/src/tree.rs diff --git a/vendor/pulldown-cmark/tests/errors.rs b/vendor/pulldown-cmark-0.5.3/tests/errors.rs similarity index 100% rename from vendor/pulldown-cmark/tests/errors.rs rename to vendor/pulldown-cmark-0.5.3/tests/errors.rs diff --git a/vendor/pulldown-cmark/tests/html.rs b/vendor/pulldown-cmark-0.5.3/tests/html.rs similarity index 100% rename from vendor/pulldown-cmark/tests/html.rs rename to vendor/pulldown-cmark-0.5.3/tests/html.rs diff --git a/vendor/pulldown-cmark/tests/lib.rs b/vendor/pulldown-cmark-0.5.3/tests/lib.rs similarity index 100% rename from vendor/pulldown-cmark/tests/lib.rs rename to vendor/pulldown-cmark-0.5.3/tests/lib.rs diff --git a/vendor/pulldown-cmark/tests/suite/footnotes.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/footnotes.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/footnotes.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/footnotes.rs diff --git a/vendor/pulldown-cmark/tests/suite/gfm_strikethrough.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/gfm_strikethrough.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/gfm_strikethrough.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/gfm_strikethrough.rs diff --git a/vendor/pulldown-cmark/tests/suite/gfm_table.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/gfm_table.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/gfm_table.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/gfm_table.rs diff --git a/vendor/pulldown-cmark/tests/suite/gfm_tasklist.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/gfm_tasklist.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/gfm_tasklist.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/gfm_tasklist.rs diff --git a/vendor/pulldown-cmark/tests/suite/mod.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/mod.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/mod.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/mod.rs diff --git a/vendor/pulldown-cmark/tests/suite/regression.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/regression.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/regression.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/regression.rs diff --git a/vendor/pulldown-cmark/tests/suite/spec.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/spec.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/spec.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/spec.rs diff --git a/vendor/pulldown-cmark/tests/suite/table.rs b/vendor/pulldown-cmark-0.5.3/tests/suite/table.rs similarity index 100% rename from vendor/pulldown-cmark/tests/suite/table.rs rename to vendor/pulldown-cmark-0.5.3/tests/suite/table.rs diff --git a/vendor/pulldown-cmark/third_party/CommonMark/LICENSE b/vendor/pulldown-cmark-0.5.3/third_party/CommonMark/LICENSE similarity index 100% rename from vendor/pulldown-cmark/third_party/CommonMark/LICENSE rename to vendor/pulldown-cmark-0.5.3/third_party/CommonMark/LICENSE diff --git a/vendor/pulldown-cmark/third_party/CommonMark/README.google b/vendor/pulldown-cmark-0.5.3/third_party/CommonMark/README.google similarity index 100% rename from vendor/pulldown-cmark/third_party/CommonMark/README.google rename to vendor/pulldown-cmark-0.5.3/third_party/CommonMark/README.google diff --git a/vendor/pulldown-cmark/third_party/CommonMark/spec.txt b/vendor/pulldown-cmark-0.5.3/third_party/CommonMark/spec.txt similarity index 100% rename from vendor/pulldown-cmark/third_party/CommonMark/spec.txt rename to vendor/pulldown-cmark-0.5.3/third_party/CommonMark/spec.txt diff --git a/vendor/pulldown-cmark/third_party/GitHub/LICENSE b/vendor/pulldown-cmark-0.5.3/third_party/GitHub/LICENSE similarity index 100% rename from vendor/pulldown-cmark/third_party/GitHub/LICENSE rename to vendor/pulldown-cmark-0.5.3/third_party/GitHub/LICENSE diff --git a/vendor/pulldown-cmark/third_party/GitHub/gfm_strikethrough.txt b/vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_strikethrough.txt similarity index 100% rename from vendor/pulldown-cmark/third_party/GitHub/gfm_strikethrough.txt rename to vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_strikethrough.txt diff --git a/vendor/pulldown-cmark/third_party/GitHub/gfm_table.txt b/vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_table.txt similarity index 100% rename from vendor/pulldown-cmark/third_party/GitHub/gfm_table.txt rename to vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_table.txt diff --git a/vendor/pulldown-cmark/third_party/GitHub/gfm_tasklist.txt b/vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_tasklist.txt similarity index 100% rename from vendor/pulldown-cmark/third_party/GitHub/gfm_tasklist.txt rename to vendor/pulldown-cmark-0.5.3/third_party/GitHub/gfm_tasklist.txt diff --git a/vendor/pulldown-cmark/third_party/GitHub/spec.txt b/vendor/pulldown-cmark-0.5.3/third_party/GitHub/spec.txt similarity index 100% rename from vendor/pulldown-cmark/third_party/GitHub/spec.txt rename to vendor/pulldown-cmark-0.5.3/third_party/GitHub/spec.txt diff --git a/vendor/pulldown-cmark/third_party/xi-editor/LICENSE b/vendor/pulldown-cmark-0.5.3/third_party/xi-editor/LICENSE similarity index 100% rename from vendor/pulldown-cmark/third_party/xi-editor/LICENSE rename to vendor/pulldown-cmark-0.5.3/third_party/xi-editor/LICENSE diff --git a/vendor/pulldown-cmark/third_party/xi-editor/crdt.md b/vendor/pulldown-cmark-0.5.3/third_party/xi-editor/crdt.md similarity index 100% rename from vendor/pulldown-cmark/third_party/xi-editor/crdt.md rename to vendor/pulldown-cmark-0.5.3/third_party/xi-editor/crdt.md diff --git a/vendor/pulldown-cmark/tools/mk_entities.py b/vendor/pulldown-cmark-0.5.3/tools/mk_entities.py similarity index 100% rename from vendor/pulldown-cmark/tools/mk_entities.py rename to vendor/pulldown-cmark-0.5.3/tools/mk_entities.py diff --git a/vendor/pulldown-cmark/tools/mk_puncttable.py b/vendor/pulldown-cmark-0.5.3/tools/mk_puncttable.py similarity index 100% rename from vendor/pulldown-cmark/tools/mk_puncttable.py rename to vendor/pulldown-cmark-0.5.3/tools/mk_puncttable.py diff --git a/vendor/quote/.cargo-checksum.json b/vendor/quote-0.6.12/.cargo-checksum.json similarity index 100% rename from vendor/quote/.cargo-checksum.json rename to vendor/quote-0.6.12/.cargo-checksum.json diff --git a/vendor/quote/Cargo.toml b/vendor/quote-0.6.12/Cargo.toml similarity index 100% rename from vendor/quote/Cargo.toml rename to vendor/quote-0.6.12/Cargo.toml diff --git a/vendor/quote/LICENSE-APACHE b/vendor/quote-0.6.12/LICENSE-APACHE similarity index 100% rename from vendor/quote/LICENSE-APACHE rename to vendor/quote-0.6.12/LICENSE-APACHE diff --git a/vendor/env_logger-0.5.13/LICENSE-MIT b/vendor/quote-0.6.12/LICENSE-MIT similarity index 95% rename from vendor/env_logger-0.5.13/LICENSE-MIT rename to vendor/quote-0.6.12/LICENSE-MIT index 39d4bdb5ac..40b8817a47 100644 --- a/vendor/env_logger-0.5.13/LICENSE-MIT +++ b/vendor/quote-0.6.12/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2014 The Rust Project Developers +Copyright (c) 2016 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/vendor/quote/README.md b/vendor/quote-0.6.12/README.md similarity index 100% rename from vendor/quote/README.md rename to vendor/quote-0.6.12/README.md diff --git a/vendor/quote/src/ext.rs b/vendor/quote-0.6.12/src/ext.rs similarity index 100% rename from vendor/quote/src/ext.rs rename to vendor/quote-0.6.12/src/ext.rs diff --git a/vendor/quote/src/lib.rs b/vendor/quote-0.6.12/src/lib.rs similarity index 100% rename from vendor/quote/src/lib.rs rename to vendor/quote-0.6.12/src/lib.rs diff --git a/vendor/quote/src/runtime.rs b/vendor/quote-0.6.12/src/runtime.rs similarity index 100% rename from vendor/quote/src/runtime.rs rename to vendor/quote-0.6.12/src/runtime.rs diff --git a/vendor/quote/src/to_tokens.rs b/vendor/quote-0.6.12/src/to_tokens.rs similarity index 100% rename from vendor/quote/src/to_tokens.rs rename to vendor/quote-0.6.12/src/to_tokens.rs diff --git a/vendor/quote/tests/conditional/integer128.rs b/vendor/quote-0.6.12/tests/conditional/integer128.rs similarity index 100% rename from vendor/quote/tests/conditional/integer128.rs rename to vendor/quote-0.6.12/tests/conditional/integer128.rs diff --git a/vendor/quote/tests/test.rs b/vendor/quote-0.6.12/tests/test.rs similarity index 100% rename from vendor/quote/tests/test.rs rename to vendor/quote-0.6.12/tests/test.rs diff --git a/vendor/rustc-demangle/.cargo-checksum.json b/vendor/rustc-demangle/.cargo-checksum.json index d87dcb5805..f041b639ff 100644 --- a/vendor/rustc-demangle/.cargo-checksum.json +++ b/vendor/rustc-demangle/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"1053f5e93d51d05f1863bdc806494a3439b4c5e44bb601c8b7b5c7af9ae88f9e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"7bb7dbc6378a31b5b925a0cff628a69006c77a4cdf3533f7507b7c8fbe3492b0","src/legacy.rs":"6ee0396373647f2f555d2226da667a8d222324e517b2c7b0a0367c171754bcdf","src/lib.rs":"53d01da4bdb1965e73e9b5d6613aa51abc8dc6dde86bfdcc59e6ddcf11e210fa","src/v0.rs":"740fa3ed15cee542e38e939226fb25e8c3034561899085e0c97cf8bd1743037e"},"package":"a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"} \ No newline at end of file +{"files":{"Cargo.toml":"ead05c6446fe945323775a2805e07aae6784238364fa07a84a72d38f7363c5d1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"7bb7dbc6378a31b5b925a0cff628a69006c77a4cdf3533f7507b7c8fbe3492b0","src/legacy.rs":"3d469f6ba81129500a23b5975c9f099020c734bd26bb039d1030bf359d3d53fc","src/lib.rs":"4069dce717cdc52933b39991b401834b5aa5cd02fa2cffb78691397a97a467be","src/v0.rs":"9c4df16df15277abe500a539876e77907cda248da4822a921b708d6d4468ff4a"},"package":"4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"} \ No newline at end of file diff --git a/vendor/rustc-demangle/Cargo.toml b/vendor/rustc-demangle/Cargo.toml index 07935ed465..9dac4e4c9a 100644 --- a/vendor/rustc-demangle/Cargo.toml +++ b/vendor/rustc-demangle/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" authors = ["Alex Crichton "] description = "Rust compiler symbol demangling.\n" homepage = "https://github.com/alexcrichton/rustc-demangle" diff --git a/vendor/rustc-demangle/src/legacy.rs b/vendor/rustc-demangle/src/legacy.rs index 1e1824c6ce..5e307972b8 100644 --- a/vendor/rustc-demangle/src/legacy.rs +++ b/vendor/rustc-demangle/src/legacy.rs @@ -1,3 +1,4 @@ +use core::char; use core::fmt; /// Representation of a demangled symbol name. @@ -45,23 +46,22 @@ pub struct Demangle<'a> { // Note that this demangler isn't quite as fancy as it could be. We have lots // of other information in our symbols like hashes, version, type information, // etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(s: &str) -> Result { +pub fn demangle(s: &str) -> Result<(Demangle, &str), ()> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-Rust // symbols because we could have any function in the backtrace. - let inner; - if s.len() > 4 && s.starts_with("_ZN") && s.ends_with('E') { - inner = &s[3..s.len() - 1]; - } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with('E') { + let inner = if s.starts_with("_ZN") { + &s[3..] + } else if s.starts_with("ZN") { // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" // form too. - inner = &s[2..s.len() - 1]; - } else if s.len() > 5 && s.starts_with("__ZN") && s.ends_with('E') { + &s[2..] + } else if s.starts_with("__ZN") { // On OSX, symbols are prefixed with an extra _ - inner = &s[4..s.len() - 1]; + &s[4..] } else { return Err(()); - } + }; // only work with ascii text if inner.bytes().any(|c| c & 0x80 != 0) { @@ -69,40 +69,34 @@ pub fn demangle(s: &str) -> Result { } let mut elements = 0; - let mut chars = inner.chars().peekable(); - loop { - let mut i = 0usize; - while let Some(&c) = chars.peek() { - if !c.is_digit(10) { - break - } - chars.next(); - let next = i.checked_mul(10) - .and_then(|i| i.checked_add(c as usize - '0' as usize)); - i = match next { - Some(i) => i, - None => { - return Err(()); - } - }; + let mut chars = inner.chars(); + let mut c = try!(chars.next().ok_or(())); + while c != 'E' { + // Decode an identifier element's length. + if !c.is_digit(10) { + return Err(()); + } + let mut len = 0usize; + while let Some(d) = c.to_digit(10) { + len = try!(len.checked_mul(10) + .and_then(|len| len.checked_add(d as usize)) + .ok_or(())); + c = try!(chars.next().ok_or(())); } - if i == 0 { - if !chars.next().is_none() { - return Err(()); - } - break; - } else if chars.by_ref().take(i).count() != i { - return Err(()); - } else { - elements += 1; + // `c` already contains the first character of this identifier, skip it and + // all the other characters of this identifier, to reach the next element. + for _ in 0..len { + c = try!(chars.next().ok_or(())); } + + elements += 1; } - Ok(Demangle { + Ok((Demangle { inner: inner, elements: elements, - }) + }, chars.as_str())) } // Rust hashes are hex digits with an `h` prepended. @@ -133,7 +127,7 @@ impl<'a> fmt::Display for Demangle<'a> { if rest.starts_with("_$") { rest = &rest[1..]; } - while !rest.is_empty() { + loop { if rest.starts_with('.') { if let Some('.') = rest[1..].chars().next() { try!(f.write_str("::")); @@ -143,55 +137,54 @@ impl<'a> fmt::Display for Demangle<'a> { rest = &rest[1..]; } } else if rest.starts_with('$') { - macro_rules! demangle { - ($($pat:expr => $demangled:expr,)*) => ({ - $(if rest.starts_with($pat) { - try!(f.write_str($demangled)); - rest = &rest[$pat.len()..]; - } else)* - { - try!(f.write_str(rest)); - break; - } - - }) - } + let (escape, after_escape) = if let Some(end) = rest[1..].find('$') { + (&rest[1..end + 1], &rest[end + 2..]) + } else { + break; + }; - // see src/librustc/back/link.rs for these mappings - demangle! { - "$SP$" => "@", - "$BP$" => "*", - "$RF$" => "&", - "$LT$" => "<", - "$GT$" => ">", - "$LP$" => "(", - "$RP$" => ")", - "$C$" => ",", - - // in theory we can demangle any Unicode code point, but - // for simplicity we just catch the common ones. - "$u7e$" => "~", - "$u20$" => " ", - "$u27$" => "'", - "$u3d$" => "=", - "$u5b$" => "[", - "$u5d$" => "]", - "$u7b$" => "{", - "$u7d$" => "}", - "$u3b$" => ";", - "$u2b$" => "+", - "$u21$" => "!", - "$u22$" => "\"", - } - } else { - let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') { - None => rest.len(), - Some((i, _)) => i, + // see src/librustc_codegen_utils/symbol_names/legacy.rs for these mappings + let unescaped = match escape { + "SP" => "@", + "BP" => "*", + "RF" => "&", + "LT" => "<", + "GT" => ">", + "LP" => "(", + "RP" => ")", + "C" => ",", + + _ => { + if escape.starts_with('u') { + let digits = &escape[1..]; + let all_lower_hex = digits.chars().all(|c| match c { + '0'...'9' | 'a'...'f' => true, + _ => false, + }); + let c = u32::from_str_radix(digits, 16).ok() + .and_then(char::from_u32); + if let (true, Some(c)) = (all_lower_hex, c) { + // FIXME(eddyb) do we need to filter out control codepoints? + if !c.is_control() { + try!(c.fmt(f)); + rest = after_escape; + continue; + } + } + } + break; + } }; - try!(f.write_str(&rest[..idx])); - rest = &rest[idx..]; + try!(f.write_str(unescaped)); + rest = after_escape; + } else if let Some(i) = rest.find(|c| c == '$' || c == '.') { + try!(f.write_str(&rest[..i])); + rest = &rest[i..]; + } else { + break; } } + try!(f.write_str(rest)); } Ok(()) @@ -367,4 +360,20 @@ mod tests { " as std::process::Termination>::report::hfc41d0da4a40b3e8" ); } + + #[test] + fn demangle_utf8_idents() { + t_nohash!( + "_ZN11utf8_idents157_$u10e1$$u10d0$$u10ed$$u10db$$u10d4$$u10da$$u10d0$$u10d3$_$u10d2$$u10d4$$u10db$$u10e0$$u10d8$$u10d4$$u10da$$u10d8$_$u10e1$$u10d0$$u10d3$$u10d8$$u10da$$u10d8$17h21634fd5714000aaE", + "utf8_idents::საჭმელად_გემრიელი_სადილი" + ); + } + + #[test] + fn demangle_issue_60925() { + t_nohash!( + "_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE", + "issue_60925::foo::Foo::foo" + ); + } } diff --git a/vendor/rustc-demangle/src/lib.rs b/vendor/rustc-demangle/src/lib.rs index 41bc796a3a..19778d8370 100644 --- a/vendor/rustc-demangle/src/lib.rs +++ b/vendor/rustc-demangle/src/lib.rs @@ -81,25 +81,33 @@ pub fn demangle(mut s: &str) -> Demangle { } } - // Output like LLVM IR adds extra period-delimited words. See if - // we are in that case and save the trailing words if so. let mut suffix = ""; - if let Some(i) = s.rfind("E.") { - let (head, tail) = s.split_at(i + 1); // After the E, before the period - - if is_symbol_like(tail) { - s = head; - suffix = tail; + let mut style = match legacy::demangle(s) { + Ok((d, s)) => { + suffix = s; + Some(DemangleStyle::Legacy(d)) } - } - - let style = match legacy::demangle(s) { - Ok(d) => Some(DemangleStyle::Legacy(d)), Err(()) => match v0::demangle(s) { - Ok(d) => Some(DemangleStyle::V0(d)), + Ok((d, s)) => { + suffix = s; + Some(DemangleStyle::V0(d)) + } Err(v0::Invalid) => None, }, }; + + // Output like LLVM IR adds extra period-delimited words. See if + // we are in that case and save the trailing words if so. + if !suffix.is_empty() { + if suffix.starts_with(".") && is_symbol_like(suffix) { + // Keep the suffix. + } else { + // Reset the suffix and invalidate the demangling. + suffix = ""; + style = None; + } + } + Demangle { style: style, original: s, diff --git a/vendor/rustc-demangle/src/v0.rs b/vendor/rustc-demangle/src/v0.rs index 8fdbe83d0c..7a6c6a2301 100644 --- a/vendor/rustc-demangle/src/v0.rs +++ b/vendor/rustc-demangle/src/v0.rs @@ -12,7 +12,7 @@ pub struct Demangle<'a> { /// This function will take a **mangled** symbol and return a value. When printed, /// the de-mangled version will be written. If the symbol does not look like /// a mangled symbol, the original value will be written instead. -pub fn demangle(s: &str) -> Result { +pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-Rust // symbols because we could have any function in the backtrace. @@ -47,17 +47,18 @@ pub fn demangle(s: &str) -> Result { next: 0, }; try!(parser.skip_path()); - if parser.next < parser.sym.len() { - // Instantiating crate. - try!(parser.skip_path()); - } - if parser.next != parser.sym.len() { - return Err(Invalid); + + // Instantiating crate (paths always start with uppercase characters). + match parser.sym.as_bytes().get(parser.next) { + Some(&b'A'...b'Z') => { + try!(parser.skip_path()); + } + _ => {} } - Ok(Demangle { + Ok((Demangle { inner: inner, - }) + }, &parser.sym[parser.next..])) } impl<'s> Display for Demangle<'s> { @@ -1064,4 +1065,20 @@ mod tests { ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))" ); } + + #[test] + fn demangle_thinlto() { + t_nohash!("_RC3foo.llvm.9D1C9369", "foo"); + t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo"); + t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo"); + } + + #[test] + fn demangle_extra_suffix() { + // From alexcrichton/rustc-demangle#27: + t_nohash!( + "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0", + "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0" + ); + } } diff --git a/vendor/serde/.cargo-checksum.json b/vendor/serde/.cargo-checksum.json index 855da1633f..976a948e02 100644 --- a/vendor/serde/.cargo-checksum.json +++ b/vendor/serde/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"9f1e33b4b64aefd1513f71b767ce2c8d77b3ad0ec94490f4258a111e0380c587","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3760f279854d1ca296894756ebd4d8bc91fe164874aa4c17db522843a9725f8e","build.rs":"36983e7377af4e76eba9c8745e0d58c1668afaf651abf4ba53d203f985593f32","crates-io.md":"131dee2d4beaf83485aed22942b98815ef65af9bcfb65f02b5b90c59b8bc7b8b","src/de/from_primitive.rs":"058fa17313ed3a9c29ec04c6ec67f21a756f6f28cdeb4b0dfcd7012b3e702d0b","src/de/ignored_any.rs":"3c199f3e4c3f8775ab30439c6868b61aa0a32fa23232b218afb94d1aadb15f0a","src/de/impls.rs":"75a798b149c690ef197d3f190c95f42a2bc0a8f7b3bd9f689f7faae02c0e9403","src/de/mod.rs":"76161f9f86b1589495681da619a6785561b587c27c62724fe960b630be69c564","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"a878f6bdd57d25b0b93bfc6288ed1e46c50870dc8703748b6fbb8c0965a6b586","src/export.rs":"1519d8bf2d18368eb0a394e1aceff74e092922902a966f388b74fddecdbeb5f9","src/integer128.rs":"f8298a559f1fae7579819cb68f6cba8c01cdda11737cf1fb498bf52810c130b6","src/lib.rs":"cdb28f42ebc35a886f5b380190f8339d315cf8c75e356fd5d60264fa4497bcac","src/macros.rs":"f18fc25c5fb857238bf119cdee5c7987a8584dea69c51f27ca718b7dfd871d0f","src/private/de.rs":"2a4b0b7145135b1116f7b0af4adebe74b7d3aa4cc96896584066a654aa4b6c6c","src/private/macros.rs":"ebb6affd4c89e3b5f9a42e03f8b7d966bc588875e9b44e962d0b7aba7f80a10f","src/private/mod.rs":"f8f2cd5edbfc26c268b34cdb89db1b34e6348f81384f03d18532e7568575006d","src/private/ser.rs":"946bf9910bb646a4c1732fd17f8c98db2515fe23edeb6e622e3618ff4de46b33","src/ser/impls.rs":"1a6598433a22d2672f743619e4ec99c55378d9283f26783ade02dd2ce4acf892","src/ser/impossible.rs":"3dd0e165b88fc67e698e675f16569b91fab9e054caa4c3e1997f929ba364fe90","src/ser/mod.rs":"6fac442413315d14b60fb62d9298c857d2b93276dc8d03729db44bf8fb9a1ec5"},"package":"32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be"} \ No newline at end of file +{"files":{"Cargo.toml":"d5628833661f9f1ba17a3c46bd8b64778bf0f53c9eade43bce4b6fcf6bb74b5d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3760f279854d1ca296894756ebd4d8bc91fe164874aa4c17db522843a9725f8e","build.rs":"8248e200a4524f1cf3fd6ca1079d27cee8d2722ab0c5c6771970811f10898043","crates-io.md":"131dee2d4beaf83485aed22942b98815ef65af9bcfb65f02b5b90c59b8bc7b8b","src/de/from_primitive.rs":"058fa17313ed3a9c29ec04c6ec67f21a756f6f28cdeb4b0dfcd7012b3e702d0b","src/de/ignored_any.rs":"6a0527edd497a56a103ae65f5e73da675b3f99094d6dcad3c335c8d932daaf40","src/de/impls.rs":"c88c99a9414ed73d470ad672f2d67a692458875bcfc54725083e60c7b5b3748e","src/de/mod.rs":"76161f9f86b1589495681da619a6785561b587c27c62724fe960b630be69c564","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"a878f6bdd57d25b0b93bfc6288ed1e46c50870dc8703748b6fbb8c0965a6b586","src/export.rs":"2ebdf0eccaa64c5e98c6dfd13b4980474f627fc3fae90cfc2c741acf860afd5d","src/integer128.rs":"b213ec6c1ecf8c8228d9591e0b2c31b78d972cd4c6a0b231468090f15784f6f6","src/lib.rs":"317b3a5d53f58152f700431971a9e5de92fc4d8805f5c53113ef033b3bfa3722","src/macros.rs":"f18fc25c5fb857238bf119cdee5c7987a8584dea69c51f27ca718b7dfd871d0f","src/private/de.rs":"175fa8a219cf931d3d41e140bb1c9c0599a009e589a8443f9cb54f02fdf2c7ed","src/private/macros.rs":"ebb6affd4c89e3b5f9a42e03f8b7d966bc588875e9b44e962d0b7aba7f80a10f","src/private/mod.rs":"f8f2cd5edbfc26c268b34cdb89db1b34e6348f81384f03d18532e7568575006d","src/private/ser.rs":"946bf9910bb646a4c1732fd17f8c98db2515fe23edeb6e622e3618ff4de46b33","src/ser/impls.rs":"741d6e24635911e65e31bc67d2596284a8e90b5682c975bacf11388e9b3d05e4","src/ser/impossible.rs":"3dd0e165b88fc67e698e675f16569b91fab9e054caa4c3e1997f929ba364fe90","src/ser/mod.rs":"6fac442413315d14b60fb62d9298c857d2b93276dc8d03729db44bf8fb9a1ec5"},"package":"fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"} \ No newline at end of file diff --git a/vendor/serde/Cargo.toml b/vendor/serde/Cargo.toml index 572c27db55..fbaa2f05cc 100644 --- a/vendor/serde/Cargo.toml +++ b/vendor/serde/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "serde" -version = "1.0.92" +version = "1.0.99" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] @@ -33,7 +33,7 @@ optional = true version = "1.0" [features] -alloc = ["unstable"] +alloc = [] default = ["std"] derive = ["serde_derive"] rc = [] diff --git a/vendor/serde/build.rs b/vendor/serde/build.rs index e27e2f34f0..e36ed62f5e 100644 --- a/vendor/serde/build.rs +++ b/vendor/serde/build.rs @@ -68,6 +68,31 @@ fn main() { if minor >= 28 { println!("cargo:rustc-cfg=num_nonzero"); } + + // TryFrom, Atomic types, and non-zero signed integers stabilized in Rust 1.34: + // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto + // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations + if minor >= 34 { + println!("cargo:rustc-cfg=core_try_from"); + println!("cargo:rustc-cfg=num_nonzero_signed"); + + // Whitelist of archs that support std::sync::atomic module. Ideally we + // would use #[cfg(target_has_atomic = "...")] but it is not stable yet. + // Instead this is based on rustc's src/librustc_target/spec/*.rs. + let has_atomic64 = target.starts_with("x86_64") + || target.starts_with("i686") + || target.starts_with("aarch64") + || target.starts_with("powerpc64") + || target.starts_with("sparc64") + || target.starts_with("mips64el"); + let has_atomic32 = has_atomic64 || emscripten; + if has_atomic64 { + println!("cargo:rustc-cfg=std_atomic64"); + } + if has_atomic32 { + println!("cargo:rustc-cfg=std_atomic"); + } + } } fn rustc_minor_version() -> Option { diff --git a/vendor/serde/src/de/ignored_any.rs b/vendor/serde/src/de/ignored_any.rs index 855d68e1ae..68a644e0d1 100644 --- a/vendor/serde/src/de/ignored_any.rs +++ b/vendor/serde/src/de/ignored_any.rs @@ -1,6 +1,8 @@ use lib::*; -use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; +use de::{ + Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, +}; /// An efficient way of discarding data from a deserializer. /// @@ -205,6 +207,13 @@ impl<'de> Visitor<'de> for IgnoredAny { let _ = bytes; Ok(IgnoredAny) } + + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, + { + data.variant::()?.1.newtype_variant() + } } impl<'de> Deserialize<'de> for IgnoredAny { diff --git a/vendor/serde/src/de/impls.rs b/vendor/serde/src/de/impls.rs index 1d4c318784..e963148092 100644 --- a/vendor/serde/src/de/impls.rs +++ b/vendor/serde/src/de/impls.rs @@ -790,7 +790,8 @@ seq_impl!( BinaryHeap::clear, BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::reserve, - BinaryHeap::push); + BinaryHeap::push +); #[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( @@ -799,7 +800,8 @@ seq_impl!( BTreeSet::clear, BTreeSet::new(), nop_reserve, - BTreeSet::insert); + BTreeSet::insert +); #[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( @@ -2402,7 +2404,6 @@ macro_rules! nonzero_integers { } nonzero_integers! { - // Not including signed NonZeroI* since they might be removed NonZeroU8, NonZeroU16, NonZeroU32, @@ -2410,12 +2411,26 @@ nonzero_integers! { NonZeroUsize, } +#[cfg(num_nonzero_signed)] +nonzero_integers! { + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroIsize, +} + // Currently 128-bit integers do not work on Emscripten targets so we need an // additional `#[cfg]` serde_if_integer128! { nonzero_integers! { NonZeroU128, } + + #[cfg(num_nonzero_signed)] + nonzero_integers! { + NonZeroI128, + } } //////////////////////////////////////////////////////////////////////////////// @@ -2543,3 +2558,31 @@ where Deserialize::deserialize(deserializer).map(Wrapping) } } + +#[cfg(all(feature = "std", std_atomic))] +macro_rules! atomic_impl { + ($($ty:ident)*) => { + $( + impl<'de> Deserialize<'de> for $ty { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Self::new) + } + } + )* + }; +} + +#[cfg(all(feature = "std", std_atomic))] +atomic_impl! { + AtomicBool + AtomicI8 AtomicI16 AtomicI32 AtomicIsize + AtomicU8 AtomicU16 AtomicU32 AtomicUsize +} + +#[cfg(all(feature = "std", std_atomic64))] +atomic_impl! { + AtomicI64 AtomicU64 +} diff --git a/vendor/serde/src/export.rs b/vendor/serde/src/export.rs index 80dcb7f5a3..caa1f4dc22 100644 --- a/vendor/serde/src/export.rs +++ b/vendor/serde/src/export.rs @@ -11,6 +11,9 @@ pub use self::string::from_utf8_lossy; #[cfg(any(feature = "alloc", feature = "std"))] pub use lib::{ToString, Vec}; +#[cfg(core_try_from)] +pub use lib::convert::TryFrom; + mod string { use lib::*; diff --git a/vendor/serde/src/integer128.rs b/vendor/serde/src/integer128.rs index 7a24e50ad6..01d6f34a1e 100644 --- a/vendor/serde/src/integer128.rs +++ b/vendor/serde/src/integer128.rs @@ -1,13 +1,13 @@ /// Conditional compilation depending on whether Serde is built with support for /// 128-bit integers. /// -/// Data formats that wish to support Rust compiler versions older than 1.26 may -/// place the i128 / u128 methods of their Serializer and Deserializer behind -/// this macro. +/// Data formats that wish to support Rust compiler versions older than 1.26 +/// (or targets that lack 128-bit integers) may place the i128 / u128 methods +/// of their Serializer and Deserializer behind this macro. /// -/// Data formats that require a minimum Rust compiler version of at least 1.26 -/// do not need to bother with this macro and may assume support for 128-bit -/// integers. +/// Data formats that require a minimum Rust compiler version of at least 1.26, +/// or do not target platforms that lack 128-bit integers, do not need to +/// bother with this macro and may assume support for 128-bit integers. /// /// ```edition2018 /// # use serde::private::ser::Error; diff --git a/vendor/serde/src/lib.rs b/vendor/serde/src/lib.rs index 4133c1436f..84287f04ae 100644 --- a/vendor/serde/src/lib.rs +++ b/vendor/serde/src/lib.rs @@ -73,7 +73,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.92")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.99")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Unstable functionality only if the user asks for it. For tracking and @@ -81,8 +81,7 @@ // // https://github.com/serde-rs/serde/issues/812 #![cfg_attr(feature = "unstable", feature(specialization, never_type))] -#![cfg_attr(feature = "alloc", feature(alloc))] -#![allow(unknown_lints, bare_trait_objects)] +#![allow(unknown_lints, bare_trait_objects, deprecated)] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] // Ignored clippy and clippy_pedantic lints @@ -90,13 +89,13 @@ feature = "cargo-clippy", allow( // not available in our oldest supported compiler - const_static_lifetime, + checked_conversions, empty_enum, redundant_field_names, + redundant_static_lifetimes, // integer and float ser/de requires these sorts of casts cast_possible_truncation, cast_possible_wrap, - cast_precision_loss, cast_sign_loss, // things are often more readable this way cast_lossless, @@ -213,6 +212,14 @@ mod lib { #[cfg(range_inclusive)] pub use self::core::ops::RangeInclusive; + #[cfg(all(feature = "std", std_atomic))] + pub use std::sync::atomic::{ + AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, + AtomicUsize, Ordering, + }; + #[cfg(all(feature = "std", std_atomic64))] + pub use std::sync::atomic::{AtomicI64, AtomicU64}; + #[cfg(any(core_duration, feature = "std"))] pub use self::core::time::Duration; } diff --git a/vendor/serde/src/private/de.rs b/vendor/serde/src/private/de.rs index feb3d4c7bf..ffa5012dc7 100644 --- a/vendor/serde/src/private/de.rs +++ b/vendor/serde/src/private/de.rs @@ -1420,6 +1420,7 @@ mod content { Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::U8(v) => visitor.visit_u8(v), + Content::U64(v) => visitor.visit_u64(v), _ => Err(self.invalid_type(&visitor)), } } @@ -2123,6 +2124,7 @@ mod content { Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::U8(v) => visitor.visit_u8(v), + Content::U64(v) => visitor.visit_u64(v), _ => Err(self.invalid_type(&visitor)), } } diff --git a/vendor/serde/src/ser/impls.rs b/vendor/serde/src/ser/impls.rs index 49b7477a4f..0ac667dbfc 100644 --- a/vendor/serde/src/ser/impls.rs +++ b/vendor/serde/src/ser/impls.rs @@ -481,7 +481,6 @@ macro_rules! nonzero_integers { } nonzero_integers! { - // Not including signed NonZeroI* since they might be removed NonZeroU8, NonZeroU16, NonZeroU32, @@ -489,12 +488,26 @@ nonzero_integers! { NonZeroUsize, } +#[cfg(num_nonzero_signed)] +nonzero_integers! { + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroIsize, +} + // Currently 128-bit integers do not work on Emscripten targets so we need an // additional `#[cfg]` serde_if_integer128! { nonzero_integers! { NonZeroU128, } + + #[cfg(num_nonzero_signed)] + nonzero_integers! { + NonZeroI128, + } } impl Serialize for Cell @@ -620,6 +633,7 @@ impl Serialize for SystemTime { #[cfg(feature = "std")] macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ + #[allow(deprecated)] let mut buffer: [u8; $max] = unsafe { mem::uninitialized() }; let remaining_len = { let mut remaining = &mut buffer[..]; @@ -838,3 +852,33 @@ where self.0.serialize(serializer) } } + +//////////////////////////////////////////////////////////////////////////////// + +#[cfg(all(feature = "std", std_atomic))] +macro_rules! atomic_impl { + ($($ty:ident)*) => { + $( + impl Serialize for $ty { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.load(Ordering::SeqCst).serialize(serializer) + } + } + )* + } +} + +#[cfg(all(feature = "std", std_atomic))] +atomic_impl! { + AtomicBool + AtomicI8 AtomicI16 AtomicI32 AtomicIsize + AtomicU8 AtomicU16 AtomicU32 AtomicUsize +} + +#[cfg(all(feature = "std", std_atomic64))] +atomic_impl! { + AtomicI64 AtomicU64 +} diff --git a/vendor/strsim/.cargo-checksum.json b/vendor/strsim/.cargo-checksum.json index 68e81d3f5b..6b073e9bdf 100644 --- a/vendor/strsim/.cargo-checksum.json +++ b/vendor/strsim/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"1472e9bc914215d1c63d842e409e0b93d23a8b62b411ce09b7e3e5b2de212100","Cargo.toml":"41ef74c41992b1750d53de7878e1e200a36add38741303a98aa3e1321462097f","LICENSE":"1738b51502ae831fb59ffbeb22ebdd90bf17e5c72fe57c00b47552415f133fd8","README.md":"9cc6cae9758534e8cf3a0376f73983935fb7968463cd324bbef06328659f5030","appveyor.yml":"b41eae9798a9bb250f6046509d9bbd6e63bac9ad2655d342b3d9c8975584f0c0","dev":"5bd26dc2c86f777627abe96c5992b6c45e6b5dea52f42b7107fa5c106abe2ab4","src/lib.rs":"14b7916423df616e73974e984468584481bf84a8f7d24a0a3c392d48c5c711d2","tests/lib.rs":"eb2f829a86b54481ca97e17414fb1e4cec7c5e1cb27ead5913eea87d61f7f29f"},"package":"bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"} \ No newline at end of file +{"files":{"CHANGELOG.md":"18e89ab18be7d22dd835924a38b1198651e870dfd0a2904a344120d341c4bc0e","Cargo.toml":"dd189fa732c00b7d1b036b43220253ef6ff2a0b1ff5ca7cf13f0669113a2055e","LICENSE":"1738b51502ae831fb59ffbeb22ebdd90bf17e5c72fe57c00b47552415f133fd8","README.md":"cfb01477df60cd0780ba59cbbc388f3f71d83bf51bab77e004fc7b811aff0efd","appveyor.yml":"b41eae9798a9bb250f6046509d9bbd6e63bac9ad2655d342b3d9c8975584f0c0","benches/benches.rs":"e277857c44afdc08b2acf35fc05be6226529c588eb9da397382b0a74c58615ab","dev":"5bd26dc2c86f777627abe96c5992b6c45e6b5dea52f42b7107fa5c106abe2ab4","src/lib.rs":"26a960216567e5dea46033b3383a69e7da498095c092e195e92c05faef52f915","tests/lib.rs":"de2b1181c379a0f55de7b86021a9afb77dbe81053a6acf99623bec3663f9b7c4"},"package":"8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"} \ No newline at end of file diff --git a/vendor/strsim/CHANGELOG.md b/vendor/strsim/CHANGELOG.md index e73385d9f6..48d6359eaf 100644 --- a/vendor/strsim/CHANGELOG.md +++ b/vendor/strsim/CHANGELOG.md @@ -3,9 +3,13 @@ This project attempts to adhere to [Semantic Versioning](http://semver.org). ## [Unreleased] +## [0.8.0] - (2018-08-19) +### Added +- Normalized versions of Levenshtein and Damerau-Levenshtein (thanks [@gentoid](https://github.com/gentoid)) + ## [0.7.0] - (2018-01-17) ### Changed -- Faster Levenshtein implementation (thanks @wdv4758h) +- Faster Levenshtein implementation (thanks [@wdv4758h](https://github.com/wdv4758h)) ### Removed - Remove the "against_vec" functions. They are one-liners now, so they don't @@ -90,13 +94,14 @@ vector of results (thanks @ovarene) ### Fixed - Limit Jaro-Winkler return value to a maximum of 1.0 -- Fix float comparsions in tests +- Fix float comparisons in tests ## [0.1.0] - (2015-02-09) ### Added - Implement Hamming, Jaro, Jaro-Winkler, and Levenshtein -[Unreleased]: https://github.com/dguo/strsim-rs/compare/0.7.0...HEAD +[Unreleased]: https://github.com/dguo/strsim-rs/compare/0.8.0...HEAD +[0.8.0]: https://github.com/dguo/strsim-rs/compare/0.7.0...0.8.0 [0.7.0]: https://github.com/dguo/strsim-rs/compare/0.6.0...0.7.0 [0.6.0]: https://github.com/dguo/strsim-rs/compare/0.5.2...0.6.0 [0.5.2]: https://github.com/dguo/strsim-rs/compare/0.5.1...0.5.2 diff --git a/vendor/strsim/Cargo.toml b/vendor/strsim/Cargo.toml index aa92bde7e2..38d37aee5b 100644 --- a/vendor/strsim/Cargo.toml +++ b/vendor/strsim/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "strsim" -version = "0.7.0" +version = "0.8.0" authors = ["Danny Guo "] description = "Implementations of string similarity metrics.\nIncludes Hamming, Levenshtein, OSA, Damerau-Levenshtein, Jaro, and Jaro-Winkler.\n" homepage = "https://github.com/dguo/strsim-rs" @@ -21,8 +21,8 @@ readme = "README.md" keywords = ["string", "similarity", "Hamming", "Levenshtein", "Jaro"] license = "MIT" repository = "https://github.com/dguo/strsim-rs" -[badges.travis-ci] +[badges.appveyor] repository = "dguo/strsim-rs" -[badges.appveyor] +[badges.travis-ci] repository = "dguo/strsim-rs" diff --git a/vendor/strsim/README.md b/vendor/strsim/README.md index 747debbc3b..8765ea85f9 100644 --- a/vendor/strsim/README.md +++ b/vendor/strsim/README.md @@ -2,16 +2,16 @@ [Rust](https://www.rust-lang.org) implementations of [string similarity metrics]: - [Hamming] - - [Levenshtein] + - [Levenshtein] - distance & normalized - [Optimal string alignment] - - [Damerau-Levenshtein] + - [Damerau-Levenshtein] - distance & normalized - [Jaro and Jaro-Winkler] - this implementation of Jaro-Winkler does not limit the common prefix length ### Installation ```toml # Cargo.toml [dependencies] -strsim = "0.7.0" +strsim = "0.8.0" ``` ### [Documentation](https://docs.rs/strsim/) @@ -23,7 +23,8 @@ version in the ```rust extern crate strsim; -use strsim::{hamming, levenshtein, osa_distance, damerau_levenshtein, jaro, +use strsim::{hamming, levenshtein, normalized_levenshtein, osa_distance, + damerau_levenshtein, normalized_damerau_levenshtein, jaro, jaro_winkler}; fn main() { @@ -34,10 +35,14 @@ fn main() { assert_eq!(3, levenshtein("kitten", "sitting")); + assert!((normalized_levenshtein("kitten", "sitting") - 0.57142).abs() < 0.00001); + assert_eq!(3, osa_distance("ac", "cba")); assert_eq!(2, damerau_levenshtein("ac", "cba")); + assert!((normalized_damerau_levenshtein("levenshtein", "löwenbräu") - 0.27272).abs() < 0.00001) + assert!((0.392 - jaro("Friedrich Nietzsche", "Jean-Paul Sartre")).abs() < 0.001); @@ -50,6 +55,8 @@ fn main() { If you don't want to install Rust itself, you can run `$ ./dev` for a development CLI if you have [Docker] installed. +Benchmarks require a Nightly toolchain. They are run by `cargo +nightly bench`. + ### License [MIT](https://github.com/dguo/strsim-rs/blob/master/LICENSE) diff --git a/vendor/strsim/benches/benches.rs b/vendor/strsim/benches/benches.rs new file mode 100644 index 0000000000..a6d5372e84 --- /dev/null +++ b/vendor/strsim/benches/benches.rs @@ -0,0 +1,84 @@ +//! Benchmarks for strsim. + +#![feature(test)] + +extern crate strsim; + +mod benches { + use super::*; + + extern crate test; + use self::test::Bencher; + + #[bench] + fn bench_hamming(bencher: &mut Bencher) { + let a = "ACAAGATGCCATTGTCCCCCGGCCTCCTGCTGCTGCTGCTCTCCGGGG"; + let b = "CCTGGAGGGTGGCCCCACCGGCCGAGACAGCGAGCATATGCAGGAAGC"; + bencher.iter(|| { + strsim::hamming(&a, &b).unwrap(); + }) + } + + #[bench] + fn bench_jaro(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::jaro(&a, &b); + }) + } + + #[bench] + fn bench_jaro_winkler(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::jaro_winkler(&a, &b); + }) + } + + #[bench] + fn bench_levenshtein(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::levenshtein(&a, &b); + }) + } + + #[bench] + fn bench_normalized_levenshtein(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::normalized_levenshtein(&a, &b); + }) + } + + #[bench] + fn bench_osa_distance(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::osa_distance(&a, &b); + }) + } + + #[bench] + fn bench_damerau_levenshtein(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::damerau_levenshtein(&a, &b); + }) + } + + #[bench] + fn bench_normalized_damerau_levenshtein(bencher: &mut Bencher) { + let a = "Philosopher Friedrich Nietzsche"; + let b = "Philosopher Jean-Paul Sartre"; + bencher.iter(|| { + strsim::normalized_damerau_levenshtein(&a, &b); + }) + } +} diff --git a/vendor/strsim/src/lib.rs b/vendor/strsim/src/lib.rs index e6da05bad2..8c56843b3c 100644 --- a/vendor/strsim/src/lib.rs +++ b/vendor/strsim/src/lib.rs @@ -171,6 +171,25 @@ pub fn levenshtein(a: &str, b: &str) -> usize { result } +/// Calculates a normalized score of the Levenshtein algorithm between 0.0 and +/// 1.0 (inclusive), where 1.0 means the strings are the same. +/// +/// ``` +/// use strsim::normalized_levenshtein; +/// +/// assert!((normalized_levenshtein("kitten", "sitting") - 0.57142).abs() < 0.00001); +/// assert!((normalized_levenshtein("", "") - 1.0).abs() < 0.00001); +/// assert!(normalized_levenshtein("", "second").abs() < 0.00001); +/// assert!(normalized_levenshtein("first", "").abs() < 0.00001); +/// assert!((normalized_levenshtein("string", "string") - 1.0).abs() < 0.00001); +/// ``` +pub fn normalized_levenshtein(a: &str, b: &str) -> f64 { + if a.is_empty() && b.is_empty() { + return 1.0; + } + 1.0 - (levenshtein(a, b) as f64) / (a.chars().count().max(b.chars().count()) as f64) +} + /// Like Levenshtein but allows for adjacent transpositions. Each substring can /// only be edited once. /// @@ -295,6 +314,25 @@ pub fn damerau_levenshtein(a: &str, b: &str) -> usize { distances[a_len + 1][b_len + 1] } +/// Calculates a normalized score of the Damerau–Levenshtein algorithm between +/// 0.0 and 1.0 (inclusive), where 1.0 means the strings are the same. +/// +/// ``` +/// use strsim::normalized_damerau_levenshtein; +/// +/// assert!((normalized_damerau_levenshtein("levenshtein", "löwenbräu") - 0.27272).abs() < 0.00001); +/// assert!((normalized_damerau_levenshtein("", "") - 1.0).abs() < 0.00001); +/// assert!(normalized_damerau_levenshtein("", "flower").abs() < 0.00001); +/// assert!(normalized_damerau_levenshtein("tree", "").abs() < 0.00001); +/// assert!((normalized_damerau_levenshtein("sunglasses", "sunglasses") - 1.0).abs() < 0.00001); +/// ``` +pub fn normalized_damerau_levenshtein(a: &str, b: &str) -> f64 { + if a.is_empty() && b.is_empty() { + return 1.0; + } + 1.0 - (damerau_levenshtein(a, b) as f64) / (a.chars().count().max(b.chars().count()) as f64) +} + #[cfg(test)] mod tests { use super::*; @@ -530,6 +568,31 @@ mod tests { assert_eq!(6, levenshtein("kitten", "")); } + #[test] + fn normalized_levenshtein_diff_short() { + assert!((normalized_levenshtein("kitten", "sitting") - 0.57142).abs() < 0.00001); + } + + #[test] + fn normalized_levenshtein_for_empty_strings() { + assert!((normalized_levenshtein("", "") - 1.0).abs() < 0.00001); + } + + #[test] + fn normalized_levenshtein_first_empty() { + assert!(normalized_levenshtein("", "second").abs() < 0.00001); + } + + #[test] + fn normalized_levenshtein_second_empty() { + assert!(normalized_levenshtein("first", "").abs() < 0.00001); + } + + #[test] + fn normalized_levenshtein_identical_strings() { + assert!((normalized_levenshtein("identical", "identical") - 1.0).abs() < 0.00001); + } + #[test] fn osa_distance_empty() { assert_eq!(0, osa_distance("", "")); @@ -695,4 +758,29 @@ mod tests { fn damerau_levenshtein_unrestricted_edit() { assert_eq!(3, damerau_levenshtein("a cat", "an abct")); } + + #[test] + fn normalized_damerau_levenshtein_diff_short() { + assert!((normalized_damerau_levenshtein("levenshtein", "löwenbräu") - 0.27272).abs() < 0.00001); + } + + #[test] + fn normalized_damerau_levenshtein_for_empty_strings() { + assert!((normalized_damerau_levenshtein("", "") - 1.0).abs() < 0.00001); + } + + #[test] + fn normalized_damerau_levenshtein_first_empty() { + assert!(normalized_damerau_levenshtein("", "flower").abs() < 0.00001); + } + + #[test] + fn normalized_damerau_levenshtein_second_empty() { + assert!(normalized_damerau_levenshtein("tree", "").abs() < 0.00001); + } + + #[test] + fn normalized_damerau_levenshtein_identical_strings() { + assert!((normalized_damerau_levenshtein("sunglasses", "sunglasses") - 1.0).abs() < 0.00001); + } } diff --git a/vendor/strsim/tests/lib.rs b/vendor/strsim/tests/lib.rs index 46478828f4..ad7af513ae 100644 --- a/vendor/strsim/tests/lib.rs +++ b/vendor/strsim/tests/lib.rs @@ -1,7 +1,7 @@ extern crate strsim; -use strsim::{hamming, levenshtein, osa_distance, damerau_levenshtein, jaro, - jaro_winkler}; +use strsim::{hamming, levenshtein, normalized_levenshtein, osa_distance,damerau_levenshtein, + normalized_damerau_levenshtein, jaro, jaro_winkler}; #[test] fn hamming_works() { @@ -16,6 +16,11 @@ fn levenshtein_works() { assert_eq!(3, levenshtein("kitten", "sitting")); } +#[test] +fn normalized_levenshtein_works() { + assert!((normalized_levenshtein("kitten", "sitting") - 0.57142).abs() < 0.00001); +} + #[test] fn osa_distance_works() { assert_eq!(3, osa_distance("ac", "cba")); @@ -26,6 +31,11 @@ fn damerau_levenshtein_works() { assert_eq!(2, damerau_levenshtein("ac", "cba")); } +#[test] +fn normalized_damerau_levenshtein_works() { + assert!((normalized_damerau_levenshtein("levenshtein", "löwenbräu") - 0.27272).abs() < 0.00001); +} + #[test] fn jaro_works() { assert!((0.392 - jaro("Friedrich Nietzsche", "Jean-Paul Sartre")).abs() < diff --git a/vendor/syn/.cargo-checksum.json b/vendor/syn-0.15.35/.cargo-checksum.json similarity index 100% rename from vendor/syn/.cargo-checksum.json rename to vendor/syn-0.15.35/.cargo-checksum.json diff --git a/vendor/syn/Cargo.toml b/vendor/syn-0.15.35/Cargo.toml similarity index 100% rename from vendor/syn/Cargo.toml rename to vendor/syn-0.15.35/Cargo.toml diff --git a/vendor/syn/LICENSE-APACHE b/vendor/syn-0.15.35/LICENSE-APACHE similarity index 100% rename from vendor/syn/LICENSE-APACHE rename to vendor/syn-0.15.35/LICENSE-APACHE diff --git a/vendor/toml-0.4.10/LICENSE-MIT b/vendor/syn-0.15.35/LICENSE-MIT similarity index 96% rename from vendor/toml-0.4.10/LICENSE-MIT rename to vendor/syn-0.15.35/LICENSE-MIT index 39e0ed6602..31aa79387f 100644 --- a/vendor/toml-0.4.10/LICENSE-MIT +++ b/vendor/syn-0.15.35/LICENSE-MIT @@ -1,5 +1,3 @@ -Copyright (c) 2014 Alex Crichton - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the diff --git a/vendor/syn/README.md b/vendor/syn-0.15.35/README.md similarity index 100% rename from vendor/syn/README.md rename to vendor/syn-0.15.35/README.md diff --git a/vendor/syn/build.rs b/vendor/syn-0.15.35/build.rs similarity index 100% rename from vendor/syn/build.rs rename to vendor/syn-0.15.35/build.rs diff --git a/vendor/syn/src/attr.rs b/vendor/syn-0.15.35/src/attr.rs similarity index 100% rename from vendor/syn/src/attr.rs rename to vendor/syn-0.15.35/src/attr.rs diff --git a/vendor/syn/src/buffer.rs b/vendor/syn-0.15.35/src/buffer.rs similarity index 100% rename from vendor/syn/src/buffer.rs rename to vendor/syn-0.15.35/src/buffer.rs diff --git a/vendor/syn/src/custom_keyword.rs b/vendor/syn-0.15.35/src/custom_keyword.rs similarity index 100% rename from vendor/syn/src/custom_keyword.rs rename to vendor/syn-0.15.35/src/custom_keyword.rs diff --git a/vendor/syn/src/custom_punctuation.rs b/vendor/syn-0.15.35/src/custom_punctuation.rs similarity index 100% rename from vendor/syn/src/custom_punctuation.rs rename to vendor/syn-0.15.35/src/custom_punctuation.rs diff --git a/vendor/syn/src/data.rs b/vendor/syn-0.15.35/src/data.rs similarity index 100% rename from vendor/syn/src/data.rs rename to vendor/syn-0.15.35/src/data.rs diff --git a/vendor/syn/src/derive.rs b/vendor/syn-0.15.35/src/derive.rs similarity index 100% rename from vendor/syn/src/derive.rs rename to vendor/syn-0.15.35/src/derive.rs diff --git a/vendor/syn/src/error.rs b/vendor/syn-0.15.35/src/error.rs similarity index 100% rename from vendor/syn/src/error.rs rename to vendor/syn-0.15.35/src/error.rs diff --git a/vendor/syn/src/export.rs b/vendor/syn-0.15.35/src/export.rs similarity index 100% rename from vendor/syn/src/export.rs rename to vendor/syn-0.15.35/src/export.rs diff --git a/vendor/syn/src/expr.rs b/vendor/syn-0.15.35/src/expr.rs similarity index 100% rename from vendor/syn/src/expr.rs rename to vendor/syn-0.15.35/src/expr.rs diff --git a/vendor/syn/src/ext.rs b/vendor/syn-0.15.35/src/ext.rs similarity index 100% rename from vendor/syn/src/ext.rs rename to vendor/syn-0.15.35/src/ext.rs diff --git a/vendor/syn/src/file.rs b/vendor/syn-0.15.35/src/file.rs similarity index 100% rename from vendor/syn/src/file.rs rename to vendor/syn-0.15.35/src/file.rs diff --git a/vendor/syn/src/gen/fold.rs b/vendor/syn-0.15.35/src/gen/fold.rs similarity index 100% rename from vendor/syn/src/gen/fold.rs rename to vendor/syn-0.15.35/src/gen/fold.rs diff --git a/vendor/syn/src/gen/visit.rs b/vendor/syn-0.15.35/src/gen/visit.rs similarity index 100% rename from vendor/syn/src/gen/visit.rs rename to vendor/syn-0.15.35/src/gen/visit.rs diff --git a/vendor/syn/src/gen/visit_mut.rs b/vendor/syn-0.15.35/src/gen/visit_mut.rs similarity index 100% rename from vendor/syn/src/gen/visit_mut.rs rename to vendor/syn-0.15.35/src/gen/visit_mut.rs diff --git a/vendor/syn/src/gen_helper.rs b/vendor/syn-0.15.35/src/gen_helper.rs similarity index 100% rename from vendor/syn/src/gen_helper.rs rename to vendor/syn-0.15.35/src/gen_helper.rs diff --git a/vendor/syn/src/generics.rs b/vendor/syn-0.15.35/src/generics.rs similarity index 100% rename from vendor/syn/src/generics.rs rename to vendor/syn-0.15.35/src/generics.rs diff --git a/vendor/syn/src/group.rs b/vendor/syn-0.15.35/src/group.rs similarity index 100% rename from vendor/syn/src/group.rs rename to vendor/syn-0.15.35/src/group.rs diff --git a/vendor/syn/src/ident.rs b/vendor/syn-0.15.35/src/ident.rs similarity index 100% rename from vendor/syn/src/ident.rs rename to vendor/syn-0.15.35/src/ident.rs diff --git a/vendor/syn/src/item.rs b/vendor/syn-0.15.35/src/item.rs similarity index 100% rename from vendor/syn/src/item.rs rename to vendor/syn-0.15.35/src/item.rs diff --git a/vendor/syn/src/keyword.rs b/vendor/syn-0.15.35/src/keyword.rs similarity index 100% rename from vendor/syn/src/keyword.rs rename to vendor/syn-0.15.35/src/keyword.rs diff --git a/vendor/syn/src/lib.rs b/vendor/syn-0.15.35/src/lib.rs similarity index 100% rename from vendor/syn/src/lib.rs rename to vendor/syn-0.15.35/src/lib.rs diff --git a/vendor/syn/src/lifetime.rs b/vendor/syn-0.15.35/src/lifetime.rs similarity index 100% rename from vendor/syn/src/lifetime.rs rename to vendor/syn-0.15.35/src/lifetime.rs diff --git a/vendor/syn/src/lit.rs b/vendor/syn-0.15.35/src/lit.rs similarity index 100% rename from vendor/syn/src/lit.rs rename to vendor/syn-0.15.35/src/lit.rs diff --git a/vendor/syn/src/lookahead.rs b/vendor/syn-0.15.35/src/lookahead.rs similarity index 100% rename from vendor/syn/src/lookahead.rs rename to vendor/syn-0.15.35/src/lookahead.rs diff --git a/vendor/syn/src/mac.rs b/vendor/syn-0.15.35/src/mac.rs similarity index 100% rename from vendor/syn/src/mac.rs rename to vendor/syn-0.15.35/src/mac.rs diff --git a/vendor/syn/src/macros.rs b/vendor/syn-0.15.35/src/macros.rs similarity index 100% rename from vendor/syn/src/macros.rs rename to vendor/syn-0.15.35/src/macros.rs diff --git a/vendor/syn/src/op.rs b/vendor/syn-0.15.35/src/op.rs similarity index 100% rename from vendor/syn/src/op.rs rename to vendor/syn-0.15.35/src/op.rs diff --git a/vendor/syn/src/parse.rs b/vendor/syn-0.15.35/src/parse.rs similarity index 100% rename from vendor/syn/src/parse.rs rename to vendor/syn-0.15.35/src/parse.rs diff --git a/vendor/syn/src/parse_macro_input.rs b/vendor/syn-0.15.35/src/parse_macro_input.rs similarity index 100% rename from vendor/syn/src/parse_macro_input.rs rename to vendor/syn-0.15.35/src/parse_macro_input.rs diff --git a/vendor/syn/src/parse_quote.rs b/vendor/syn-0.15.35/src/parse_quote.rs similarity index 100% rename from vendor/syn/src/parse_quote.rs rename to vendor/syn-0.15.35/src/parse_quote.rs diff --git a/vendor/syn/src/path.rs b/vendor/syn-0.15.35/src/path.rs similarity index 100% rename from vendor/syn/src/path.rs rename to vendor/syn-0.15.35/src/path.rs diff --git a/vendor/syn/src/print.rs b/vendor/syn-0.15.35/src/print.rs similarity index 100% rename from vendor/syn/src/print.rs rename to vendor/syn-0.15.35/src/print.rs diff --git a/vendor/syn/src/punctuated.rs b/vendor/syn-0.15.35/src/punctuated.rs similarity index 100% rename from vendor/syn/src/punctuated.rs rename to vendor/syn-0.15.35/src/punctuated.rs diff --git a/vendor/syn/src/sealed.rs b/vendor/syn-0.15.35/src/sealed.rs similarity index 100% rename from vendor/syn/src/sealed.rs rename to vendor/syn-0.15.35/src/sealed.rs diff --git a/vendor/syn/src/span.rs b/vendor/syn-0.15.35/src/span.rs similarity index 100% rename from vendor/syn/src/span.rs rename to vendor/syn-0.15.35/src/span.rs diff --git a/vendor/syn/src/spanned.rs b/vendor/syn-0.15.35/src/spanned.rs similarity index 100% rename from vendor/syn/src/spanned.rs rename to vendor/syn-0.15.35/src/spanned.rs diff --git a/vendor/syn/src/thread.rs b/vendor/syn-0.15.35/src/thread.rs similarity index 100% rename from vendor/syn/src/thread.rs rename to vendor/syn-0.15.35/src/thread.rs diff --git a/vendor/syn/src/token.rs b/vendor/syn-0.15.35/src/token.rs similarity index 100% rename from vendor/syn/src/token.rs rename to vendor/syn-0.15.35/src/token.rs diff --git a/vendor/syn/src/tt.rs b/vendor/syn-0.15.35/src/tt.rs similarity index 100% rename from vendor/syn/src/tt.rs rename to vendor/syn-0.15.35/src/tt.rs diff --git a/vendor/syn/src/ty.rs b/vendor/syn-0.15.35/src/ty.rs similarity index 100% rename from vendor/syn/src/ty.rs rename to vendor/syn-0.15.35/src/ty.rs diff --git a/vendor/tempfile/.cargo-checksum.json b/vendor/tempfile/.cargo-checksum.json index 7b994ec04e..7488a04041 100644 --- a/vendor/tempfile/.cargo-checksum.json +++ b/vendor/tempfile/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"98111ca8df698919e755cff678b7d3cdc4f7d493dc1f31fee7918b4619c550fc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"dec3a2928a14aefbe5fe61846e4a87a8f3501258456d702c522e827ad91ee833","README.md":"c11eeed15c0d5661b25ea32115e23a31e3f529596c43f536d12b2e7a030feadc","src/dir.rs":"1a57b6f1b1ae5896ccd2de48143ced32425e9d800c4aa6890c45001370a1decf","src/error.rs":"e556cb6df652f25ab5b68e398197327664468dde29be0642d497572d536ccea9","src/file/imp/mod.rs":"bec50fb99c14cb4a49402bdbb7c5e6b5b8ff785b06b6fcb13267f35df8f3c8c2","src/file/imp/other.rs":"a6794a75a79b58849e951f0957b9f9df69d2971644ddf8ae602b1a639a873fcb","src/file/imp/unix.rs":"d5b40a692c358bdf509297c75191da89d4608b6f45473ad33ee0e1a3a567a548","src/file/imp/windows.rs":"d81e05a4573539b32f79e35e17d79420d18af28d639d3867ee7c300c69e5a1cd","src/file/mod.rs":"26688b26797b154df30081ecd96656cad17492f321565d8b303d53f44ecbb07e","src/lib.rs":"0e342f61f8de6ac6bf8a9d3fbeeb497dc14fdc865fcc502d477d2ee26c789528","src/spooled.rs":"b97702917bf4d7ffca6dc34fbc624ac8fa34c530154c0826efebd93ee1ca442a","src/util.rs":"52226bbc424ce358dcc2fb6cbe5ea47b7f836611af55aefdbda162db4552ace7","tests/namedtempfile.rs":"5185e2f3b104054d7fc6a8c3463f81f24457f38bbadadde30b0f169cece469c3","tests/spooled.rs":"e9e98431b1427760775ce68a790f524adb67e4bd36a134b4cdbb7f43f5d9d043","tests/tempdir.rs":"a8008a0adc7f0ed6f2f9e73ef0489eda7733b718be96a698a22c7fdc7a759e50","tests/tempfile.rs":"d699b2038906649b811aae6179baa687d427508c26530c39ba32178e1bd1a942"},"package":"7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"} \ No newline at end of file +{"files":{"Cargo.toml":"526cfadda74195985a5d860855ef4d8213661e9fcde075a2c128121aa7848003","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"e7da9558db65f61008aa9196066a18bcb16b4c7c4369766a67ea7ec9d52b632d","README.md":"2388f555712995933c80721d9de80fc9fe3428dd61609cc01cd26079bd543468","src/dir.rs":"50501bbbe44046d3f74c2fa1d590405cc898d5d52643f18f28964b7a82eafb80","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"bec50fb99c14cb4a49402bdbb7c5e6b5b8ff785b06b6fcb13267f35df8f3c8c2","src/file/imp/other.rs":"99c8f9f3251199fc31e7b88810134712e5725fb6fa14648696ed5cbea980fc5b","src/file/imp/unix.rs":"afc860978e362b1266b40722181fc3a509af72ce942a1b2dcd38ef1776897af3","src/file/imp/windows.rs":"03d81d71c404f0d448e1162825d6fbd57a78b4af8d4dc5287ec2e7c5a873d7cc","src/file/mod.rs":"ae7246a5c1445afa89765097742c11383ae996ea7046e8903f2dcbdb197bce53","src/lib.rs":"fb0c982c8dd2c6d0211c7d4542fa1c724d9ca45a8828ff5aeae866f4aa9d1507","src/spooled.rs":"34f5305923de710c58228d68c143133a11843e7ad5029ee31448ab4ab6172b74","src/util.rs":"25c62fb5d87411fd9508596db69ea489e9026b9ad0ffc9996db1ac8670b3da02","tests/namedtempfile.rs":"07ad89e54c9ce79d6b85d37d367d9687ec6f2cabc6cc44cdefd42731056afd6a","tests/spooled.rs":"29e797d486d867cb6ac46d4cf126eb5868a069a4070c3f50ffa02fbb0b887934","tests/tempdir.rs":"771d555d4eaa410207d212eb3744e016e0b5a22f1f1b7199636a4fac5daaf952","tests/tempfile.rs":"a1dacfd9b1ee3c40fdde5131b33995f3cfd62a212455c8664a98c735b9954ee6"},"package":"7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"} \ No newline at end of file diff --git a/vendor/tempfile/Cargo.toml b/vendor/tempfile/Cargo.toml index dfecf6bcda..dcc1ff94e7 100644 --- a/vendor/tempfile/Cargo.toml +++ b/vendor/tempfile/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,21 +11,22 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "tempfile" -version = "3.0.5" +version = "3.1.0" authors = ["Steven Allen ", "The Rust Project Developers", "Ashley Mannix ", "Jason White "] exclude = ["/.travis.yml", "/appveyor.yml"] -description = "A library for managing temporary files and directories.\n" +description = "A library for managing temporary files and directories." homepage = "http://stebalien.com/projects/tempfile-rs" documentation = "https://docs.rs/tempfile" keywords = ["tempfile", "tmpfile", "filesystem"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/Stebalien/tempfile" [dependencies.cfg-if] version = "0.1" [dependencies.rand] -version = "0.6" +version = "0.7" [dependencies.remove_dir_all] version = "0.5" @@ -35,4 +36,4 @@ version = "0.1" version = "0.2.27" [target."cfg(windows)".dependencies.winapi] version = "0.3" -features = ["fileapi", "winbase", "handleapi"] +features = ["fileapi", "handleapi", "winbase"] diff --git a/vendor/tempfile/NEWS b/vendor/tempfile/NEWS index 3af51ce977..f5e065cfe6 100644 --- a/vendor/tempfile/NEWS +++ b/vendor/tempfile/NEWS @@ -1,3 +1,112 @@ +3.1.0 +===== + +Features: + +* Bump rand dependency to `0.7`. + +Breaking: The minimum rust version is now `1.32.0`. + +3.0.9 +===== + +Documentation: + +* Add an example for reopening a named temporary file. +* Flesh out the security documentation. + +Features: + +* Introduce an `append` option to the builder. +* Errors: + * No longer implement the soft-deprecated `description`. + * Implement `source` instead of `cause`. + +Breaking: The minimum rust version is now 1.30. + +3.0.8 +===== + +This is a bugfix release. + +Fixes: + +* Export `PathPersistError`. +* Fix a bug where flushing a `SpooledTempFile` to disk could fail to write part + of the file in some rare, yet-to-reproduced cases. + +3.0.7 +===== + +Breaking: + +* `Builder::prefix` and `Builder::suffix` now accept a generic `&AsRef`. + This could affect type inference. +* Temporary files (except unnamed temporary files on Windows and Linux >= 3.11) + now use absolute path names. This will break programs that create temporary + files relative to their current working directory when they don't have the + search permission (x) on some ancestor directory. This is only likely to + affect programs with strange chroot-less filesystem sandboxes. If you believe + you're affected by this issue, please comment on #40. + +Features: + +* Accept anything implementing `&AsRef` in the builder: &OsStr, &OsString, &Path, etc. + +Fixes: + +* Fix LFS support. +* Use absolute paths for named temporary files to guard against changes in the + current directory. +* Use absolute paths when creating unnamed temporary files on platforms that + can't create unlinked or auto-deleted temporary files. This fixes a very + unlikely race where the current directory could change while the temporary + file is being created. + +Misc: + +* Use modern stdlib features to avoid custom unsafe code. This reduces the + number of unsafe blocks from 12 to 4. + +3.0.6 +===== + +* Don't hide temporary files on windows, fixing #66 and #69. + +3.0.5 +===== + +Features: + +* Added a spooled temporary file implementation. This temporary file variant + starts out as an in-memory temporary file but "rolls-over" onto disk when it + grows over a specified size (#68). +* Errors are now annotated with paths to make debugging easier (#73). + +Misc: + +* The rand version has been bumped to 0.6 (#74). + +Bugs: + +* Tempfile compiles again on Redox (#75). + +3.0.4 +===== + +* Now compiles on unsupported platforms. + +3.0.3 +===== + +* update rand to 0.5 + +3.0.2 +===== + +* Actually *delete* temporary files on non-Linux unix systems (thanks to +@oliverhenshaw for the fix and a test case). + 3.0.1 ===== @@ -52,7 +161,7 @@ Add LFS Support. * Implement `AsRef` for `NamedTempFile` allowing named temporary files to be borrowed as `File`s. -* Add a method to convert a `NamedTempFile` to an unnamed temporary `File`. +* Add a method to convert a `NamedTempFile` to an unnamed temporary `File`. 2.0.1 ===== diff --git a/vendor/tempfile/README.md b/vendor/tempfile/README.md index 8f12f44c30..6a9c06b485 100644 --- a/vendor/tempfile/README.md +++ b/vendor/tempfile/README.md @@ -15,7 +15,7 @@ patterns and surprisingly difficult to implement securely). Usage ----- -Minimum required Rust version: 1.18.0 +Minimum required Rust version: 1.32.0 Add this to your `Cargo.toml`: ```toml @@ -23,16 +23,10 @@ Add this to your `Cargo.toml`: tempfile = "3" ``` -...and this to your crate root: -```rust -extern crate tempfile; -``` - Example ------- ```rust -extern crate tempfile; use std::fs::File; use std::io::{Write, Read, Seek, SeekFrom}; diff --git a/vendor/tempfile/src/dir.rs b/vendor/tempfile/src/dir.rs index eb48159ec2..ae8a6377e4 100644 --- a/vendor/tempfile/src/dir.rs +++ b/vendor/tempfile/src/dir.rs @@ -12,8 +12,8 @@ use remove_dir_all::remove_dir_all; use std::path::{self, Path, PathBuf}; use std::{fmt, fs, io}; -use error::IoResultExt; -use Builder; +use crate::error::IoResultExt; +use crate::Builder; /// Create a new temporary directory. /// @@ -33,7 +33,6 @@ use Builder; /// # Examples /// /// ``` -/// # extern crate tempfile; /// use tempfile::tempdir; /// use std::fs::File; /// use std::io::{self, Write}; @@ -83,7 +82,6 @@ pub fn tempdir() -> io::Result { /// # Examples /// /// ``` -/// # extern crate tempfile; /// use tempfile::tempdir; /// use std::fs::File; /// use std::io::{self, Write}; @@ -237,7 +235,7 @@ impl TempDir { } /// Attempts to make a temporary directory inside of `dir`. - /// The directory and everything inside it will be automatically + /// The directory and everything inside it will be automatically /// deleted once the returned `TempDir` is destroyed. /// /// # Errors @@ -385,7 +383,7 @@ impl AsRef for TempDir { } impl fmt::Debug for TempDir { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TempDir") .field("path", &self.path()) .finish() diff --git a/vendor/tempfile/src/error.rs b/vendor/tempfile/src/error.rs index 5d70faec2c..ed6b6cc8d1 100644 --- a/vendor/tempfile/src/error.rs +++ b/vendor/tempfile/src/error.rs @@ -1,5 +1,5 @@ -use std::{error, io, fmt}; use std::path::PathBuf; +use std::{error, fmt, io}; #[derive(Debug)] struct PathError { @@ -8,18 +8,14 @@ struct PathError { } impl fmt::Display for PathError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} at path {:?}", self.err, self.path) } } impl error::Error for PathError { - fn description(&self) -> &str { - self.err.description() - } - - fn cause(&self) -> Option<&error::Error> { - self.err.cause() + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + self.err.source() } } @@ -37,10 +33,13 @@ impl IoResultExt for Result { P: Into, { self.map_err(|e| { - io::Error::new(e.kind(), PathError { - path: path().into(), - err: e, - }) + io::Error::new( + e.kind(), + PathError { + path: path().into(), + err: e, + }, + ) }) } } diff --git a/vendor/tempfile/src/file/imp/other.rs b/vendor/tempfile/src/file/imp/other.rs index da0bac3163..d8a55a7458 100644 --- a/vendor/tempfile/src/file/imp/other.rs +++ b/vendor/tempfile/src/file/imp/other.rs @@ -1,12 +1,15 @@ -use std::path::Path; +use std::fs::{File, OpenOptions}; use std::io; -use std::fs::File; +use std::path::Path; fn not_supported() -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "operation not supported on this platform")) + Err(io::Error::new( + io::ErrorKind::Other, + "operation not supported on this platform", + )) } -pub fn create_named(_path: &Path) -> io::Result { +pub fn create_named(_path: &Path, open_options: &mut OpenOptions) -> io::Result { not_supported() } @@ -21,3 +24,7 @@ pub fn reopen(_file: &File, _path: &Path) -> io::Result { pub fn persist(_old_path: &Path, _new_path: &Path, _overwrite: bool) -> io::Result<()> { not_supported() } + +pub fn keep(path: &Path) -> io::Result<()> { + not_supported() +} diff --git a/vendor/tempfile/src/file/imp/unix.rs b/vendor/tempfile/src/file/imp/unix.rs index b5df7c4507..35b1ddb1ea 100644 --- a/vendor/tempfile/src/file/imp/unix.rs +++ b/vendor/tempfile/src/file/imp/unix.rs @@ -1,21 +1,14 @@ -#[cfg(not(target_os = "redox"))] -use libc::{c_char, c_int, link, rename, unlink, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR}; -use std::ffi::CString; +use std::env; +use std::ffi::{CString, OsStr}; use std::fs::{self, File, OpenOptions}; use std::io; use std::os::unix::ffi::OsStrExt; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::fs::{MetadataExt, OpenOptionsExt}; use std::path::Path; -use util; - -#[cfg(all(lfs_support, target_os = "linux"))] -use libc::{fstat64 as fstat, open64 as open, stat64 as stat_t}; - -#[cfg(not(any(all(lfs_support, target_os = "linux"), target_os = "redox")))] -use libc::{fstat, open, stat as stat_t}; +use crate::util; -#[cfg(target_os = "redox")] -use syscall::{self, fstat, open, Stat as stat_t, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR}; +#[cfg(not(target_os = "redox"))] +use libc::{c_char, c_int, link, rename, unlink}; #[cfg(not(target_os = "redox"))] #[inline(always)] @@ -39,32 +32,26 @@ pub fn cstr(path: &Path) -> io::Result { .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contained a null")) } -#[cfg(not(target_os = "redox"))] -pub fn create_named(path: &Path) -> io::Result { - unsafe { - let path = cstr(path)?; - let fd = cvt_err(open( - path.as_ptr() as *const c_char, - O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT, - 0o600, - ))?; - Ok(FromRawFd::from_raw_fd(fd)) - } +pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result { + open_options + .read(true) + .write(true) + .create_new(true) + .mode(0o600) + .open(path) } -#[cfg(target_os = "redox")] -pub fn create_named(path: &Path) -> io::Result { - unsafe { - let fd = cvt_err(open( - path.as_os_str().as_bytes(), - O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT | 0o600, - ))?; - Ok(FromRawFd::from_raw_fd(fd)) +fn create_unlinked(path: &Path) -> io::Result { + let tmp; + // shadow this to decrease the lifetime. It can't live longer than `tmp`. + let mut path = path; + if !path.is_absolute() { + let cur_dir = env::current_dir()?; + tmp = cur_dir.join(path); + path = &tmp; } -} -fn create_unlinked(path: &Path) -> io::Result { - let f = create_named(path)?; + let f = create_named(path, &mut OpenOptions::new())?; // don't care whether the path has already been unlinked, // but perhaps there are some IO error conditions we should send up? let _ = fs::remove_file(path); @@ -73,18 +60,19 @@ fn create_unlinked(path: &Path) -> io::Result { #[cfg(target_os = "linux")] pub fn create(dir: &Path) -> io::Result { - use libc::O_TMPFILE; - match unsafe { - let path = cstr(dir)?; - open( - path.as_ptr() as *const c_char, - O_CLOEXEC | O_EXCL | O_TMPFILE | O_RDWR, - 0o600, - ) - } { - -1 => create_unix(dir), - fd => Ok(unsafe { FromRawFd::from_raw_fd(fd) }), - } + use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_EXCL, O_TMPFILE}; + OpenOptions::new() + .read(true) + .write(true) + .custom_flags(O_TMPFILE | O_EXCL) // do not mix with `create_new(true)` + .open(dir) + .or_else(|e| { + match e.raw_os_error() { + // These are the three "not supported" error codes for O_TMPFILE. + Some(EOPNOTSUPP) | Some(EISDIR) | Some(ENOENT) => create_unix(dir), + _ => Err(e), + } + }) } #[cfg(not(target_os = "linux"))] @@ -93,30 +81,26 @@ pub fn create(dir: &Path) -> io::Result { } fn create_unix(dir: &Path) -> io::Result { - util::create_helper(dir, ".tmp", "", ::NUM_RAND_CHARS, |path| { - create_unlinked(&path) - }) -} - -unsafe fn stat(fd: RawFd) -> io::Result { - let mut meta: stat_t = ::std::mem::zeroed(); - cvt_err(fstat(fd, &mut meta))?; - Ok(meta) + util::create_helper( + dir, + OsStr::new(".tmp"), + OsStr::new(""), + crate::NUM_RAND_CHARS, + |path| create_unlinked(&path), + ) } pub fn reopen(file: &File, path: &Path) -> io::Result { let new_file = OpenOptions::new().read(true).write(true).open(path)?; - unsafe { - let old_meta = stat(file.as_raw_fd())?; - let new_meta = stat(new_file.as_raw_fd())?; - if old_meta.st_dev != new_meta.st_dev || old_meta.st_ino != new_meta.st_ino { - return Err(io::Error::new( - io::ErrorKind::NotFound, - "original tempfile has been replaced", - )); - } - Ok(new_file) + let old_meta = file.metadata()?; + let new_meta = new_file.metadata()?; + if old_meta.dev() != new_meta.dev() || old_meta.ino() != new_meta.ino() { + return Err(io::Error::new( + io::ErrorKind::NotFound, + "original tempfile has been replaced", + )); } + Ok(new_file) } #[cfg(not(target_os = "redox"))] @@ -147,3 +131,7 @@ pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result< // XXX implement when possible Err(io::Error::from_raw_os_error(syscall::ENOSYS)) } + +pub fn keep(_: &Path) -> io::Result<()> { + Ok(()) +} diff --git a/vendor/tempfile/src/file/imp/windows.rs b/vendor/tempfile/src/file/imp/windows.rs index 27c28ce62e..71b4748802 100644 --- a/vendor/tempfile/src/file/imp/windows.rs +++ b/vendor/tempfile/src/file/imp/windows.rs @@ -1,85 +1,61 @@ -use std::fs::File; -use std::io; +use std::ffi::OsStr; +use std::fs::{File, OpenOptions}; use std::os::windows::ffi::OsStrExt; +use std::os::windows::fs::OpenOptionsExt; use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle}; use std::path::Path; -use std::ptr; +use std::{io, iter}; -use winapi::shared::minwindef::DWORD; -use winapi::um::fileapi::{CreateFileW, SetFileAttributesW, CREATE_NEW}; +use winapi::um::fileapi::SetFileAttributesW; use winapi::um::handleapi::INVALID_HANDLE_VALUE; -use winapi::um::winbase::{FILE_FLAG_DELETE_ON_CLOSE, MOVEFILE_REPLACE_EXISTING}; use winapi::um::winbase::{MoveFileExW, ReOpenFile}; -use winapi::um::winnt::{FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY}; +use winapi::um::winbase::{FILE_FLAG_DELETE_ON_CLOSE, MOVEFILE_REPLACE_EXISTING}; +use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY}; use winapi::um::winnt::{FILE_GENERIC_READ, FILE_GENERIC_WRITE, HANDLE}; use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE}; -use util; - -#[cfg_attr(irustfmt, rustfmt_skip)] -const ACCESS: DWORD = FILE_GENERIC_READ - | FILE_GENERIC_WRITE; -#[cfg_attr(irustfmt, rustfmt_skip)] -const SHARE_MODE: DWORD = FILE_SHARE_DELETE - | FILE_SHARE_READ - | FILE_SHARE_WRITE; -#[cfg_attr(irustfmt, rustfmt_skip)] -const FLAGS: DWORD = FILE_ATTRIBUTE_HIDDEN - | FILE_ATTRIBUTE_TEMPORARY; +use crate::util; fn to_utf16(s: &Path) -> Vec { - s.as_os_str() - .encode_wide() - .chain(Some(0).into_iter()) - .collect() + s.as_os_str().encode_wide().chain(iter::once(0)).collect() } -fn win_create( - path: &Path, - access: DWORD, - share_mode: DWORD, - disp: DWORD, - flags: DWORD, -) -> io::Result { - let path = to_utf16(path); - let handle = unsafe { - CreateFileW( - path.as_ptr(), - access, - share_mode, - 0 as *mut _, - disp, - flags, - ptr::null_mut(), - ) - }; - if handle == INVALID_HANDLE_VALUE { - Err(io::Error::last_os_error()) - } else { - Ok(unsafe { File::from_raw_handle(handle as RawHandle) }) - } -} - -pub fn create_named(path: &Path) -> io::Result { - win_create(path, ACCESS, SHARE_MODE, CREATE_NEW, FLAGS) +pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result { + open_options + .create_new(true) + .read(true) + .write(true) + .custom_flags(FILE_ATTRIBUTE_TEMPORARY) + .open(path) } pub fn create(dir: &Path) -> io::Result { - util::create_helper(dir, ".tmp", "", ::NUM_RAND_CHARS, |path| { - win_create( - &path, - ACCESS, - 0, // Exclusive - CREATE_NEW, - FLAGS | FILE_FLAG_DELETE_ON_CLOSE, - ) - }) + util::create_helper( + dir, + OsStr::new(".tmp"), + OsStr::new(""), + crate::NUM_RAND_CHARS, + |path| { + OpenOptions::new() + .create_new(true) + .read(true) + .write(true) + .share_mode(0) + .custom_flags(FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE) + .open(path) + }, + ) } pub fn reopen(file: &File, _path: &Path) -> io::Result { let handle = file.as_raw_handle(); unsafe { - let handle = ReOpenFile(handle as HANDLE, ACCESS, SHARE_MODE, 0); + let handle = ReOpenFile( + handle as HANDLE, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + ); if handle == INVALID_HANDLE_VALUE { Err(io::Error::last_os_error()) } else { @@ -88,6 +64,17 @@ pub fn reopen(file: &File, _path: &Path) -> io::Result { } } +pub fn keep(path: &Path) -> io::Result<()> { + unsafe { + let path_w = to_utf16(path); + if SetFileAttributesW(path_w.as_ptr(), FILE_ATTRIBUTE_NORMAL) == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } + } +} + pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> { // TODO: We should probably do this in one-shot using SetFileInformationByHandle but the API is // really painful. @@ -112,7 +99,7 @@ pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result< let e = io::Error::last_os_error(); // If this fails, the temporary file is now un-hidden and no longer marked temporary // (slightly less efficient) but it will still work. - let _ = SetFileAttributesW(old_path_w.as_ptr(), FLAGS); + let _ = SetFileAttributesW(old_path_w.as_ptr(), FILE_ATTRIBUTE_TEMPORARY); Err(e) } else { Ok(()) diff --git a/vendor/tempfile/src/file/mod.rs b/vendor/tempfile/src/file/mod.rs index b43f8de613..ce70cac731 100644 --- a/vendor/tempfile/src/file/mod.rs +++ b/vendor/tempfile/src/file/mod.rs @@ -3,14 +3,14 @@ use std::env; use std::error; use std::ffi::OsStr; use std::fmt; -use std::fs::{self, File}; +use std::fs::{self, File, OpenOptions}; use std::io::{self, Read, Seek, SeekFrom, Write}; use std::mem; use std::ops::Deref; use std::path::{Path, PathBuf}; -use error::IoResultExt; -use Builder; +use crate::error::IoResultExt; +use crate::Builder; mod imp; @@ -34,7 +34,6 @@ mod imp; /// # Examples /// /// ``` -/// # extern crate tempfile; /// use tempfile::tempfile; /// use std::io::{self, Write}; /// @@ -76,7 +75,6 @@ pub fn tempfile() -> io::Result { /// # Examples /// /// ``` -/// # extern crate tempfile; /// use tempfile::tempfile_in; /// use std::io::{self, Write}; /// @@ -123,17 +121,13 @@ impl From for TempPath { } impl fmt::Display for PathPersistError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "failed to persist temporary file path: {}", self.error) } } impl error::Error for PathPersistError { - fn description(&self) -> &str { - "failed to persist temporary file path" - } - - fn cause(&self) -> Option<&error::Error> { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&self.error) } } @@ -160,7 +154,6 @@ impl TempPath { /// # Examples /// /// ```no_run - /// # extern crate tempfile; /// # use std::io; /// use tempfile::NamedTempFile; /// @@ -212,7 +205,6 @@ impl TempPath { /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -272,7 +264,6 @@ impl TempPath { /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -310,10 +301,59 @@ impl TempPath { }), } } + + /// Keep the temporary file from being deleted. This function will turn the + /// temporary file into a non-temporary file without moving it. + /// + /// + /// # Errors + /// + /// On some platforms (e.g., Windows), we need to mark the file as + /// non-temporary. This operation could fail. + /// + /// # Examples + /// + /// ```no_run + /// # use std::io::{self, Write}; + /// use tempfile::NamedTempFile; + /// + /// # fn main() { + /// # if let Err(_) = run() { + /// # ::std::process::exit(1); + /// # } + /// # } + /// # fn run() -> Result<(), io::Error> { + /// let mut file = NamedTempFile::new()?; + /// writeln!(file, "Brian was here. Briefly.")?; + /// + /// let path = file.into_temp_path(); + /// let path = path.keep()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`PathPersistError`]: struct.PathPersistError.html + pub fn keep(mut self) -> Result { + match imp::keep(&self.path) { + Ok(_) => { + // Don't drop `self`. We don't want to try deleting the old + // temporary file path. (It'll fail, but the failure is never + // seen.) + let mut path = PathBuf::new(); + mem::swap(&mut self.path, &mut path); + mem::forget(self); + Ok(path) + } + Err(e) => Err(PathPersistError { + error: e, + path: self, + }), + } + } } impl fmt::Debug for TempPath { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.path.fmt(f) } } @@ -353,7 +393,63 @@ impl AsRef for TempPath { /// /// # Security /// -/// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner. +/// Most operating systems employ temporary file cleaners to delete old +/// temporary files. Unfortunately these temporary file cleaners don't always +/// reliably _detect_ whether the temporary file is still being used. +/// +/// Specifically, the following sequence of events can happen: +/// +/// 1. A user creates a temporary file with `NamedTempFile::new()`. +/// 2. Time passes. +/// 3. The temporary file cleaner deletes (unlinks) the temporary file from the +/// filesystem. +/// 4. Some other program creates a new file to replace this deleted temporary +/// file. +/// 5. The user tries to re-open the temporary file (in the same program or in a +/// different program) by path. Unfortunately, they'll end up opening the +/// file created by the other program, not the original file. +/// +/// ## Operating System Specific Concerns +/// +/// The behavior of temporary files and temporary file cleaners differ by +/// operating system. +/// +/// ### Windows +/// +/// On Windows, open files _can't_ be deleted. This removes most of the concerns +/// around temporary file cleaners. +/// +/// Furthermore, temporary files are, by default, created in per-user temporary +/// file directories so only an application running as the same user would be +/// able to interfere (which they could do anyways). However, an application +/// running as the same user can still _accidentally_ re-create deleted +/// temporary files if the number of random bytes in the temporary file name is +/// too small. +/// +/// So, the only real concern on Windows is: +/// +/// 1. Opening a named temporary file in a world-writable directory. +/// 2. Using the `into_temp_path()` and/or `into_parts()` APIs to close the file +/// handle without deleting the underlying file. +/// 3. Continuing to use the file by path. +/// +/// ### UNIX +/// +/// Unlike on Windows, UNIX (and UNIX like) systems allow open files to be +/// "unlinked" (deleted). +/// +/// #### MacOS +/// +/// Like on Windows, temporary files are created in per-user temporary file +/// directories by default so calling `NamedTempFile::new()` should be +/// relatively safe. +/// +/// #### Linux +/// +/// Unfortunately, most _Linux_ distributions don't create per-user temporary +/// file directories. Worse, systemd's tmpfiles daemon (a common temporary file +/// cleaner) will happily remove open temporary files if they haven't been +/// modified within the last 10 days. /// /// # Resource Leaking /// @@ -375,7 +471,7 @@ pub struct NamedTempFile { } impl fmt::Debug for NamedTempFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NamedTempFile({:?})", self.path) } } @@ -411,16 +507,13 @@ impl From for NamedTempFile { } impl fmt::Display for PersistError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "failed to persist temporary file: {}", self.error) } } impl error::Error for PersistError { - fn description(&self) -> &str { - "failed to persist temporary file" - } - fn cause(&self) -> Option<&error::Error> { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&self.error) } } @@ -433,9 +526,9 @@ impl NamedTempFile { /// # Security /// /// This will create a temporary file in the default temporary file - /// directory (platform dependent). These directories are often patrolled by temporary file - /// cleaners so only use this method if you're *positive* that the temporary file cleaner won't - /// delete your file. + /// directory (platform dependent). This has security implications on many + /// platforms so please read the security section of this type's + /// documentation. /// /// Reasons to use this method: /// @@ -467,7 +560,6 @@ impl NamedTempFile { /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -501,15 +593,14 @@ impl NamedTempFile { /// /// # Security /// - /// Only use this method if you're positive that a - /// temporary file cleaner won't have deleted your file. Otherwise, the path - /// returned by this method may refer to an attacker controlled file. + /// Referring to a temporary file's path may not be secure in all cases. + /// Please read the security section on the top level documentation of this + /// type for details. /// /// # Examples /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -540,7 +631,6 @@ impl NamedTempFile { /// # Examples /// /// ```no_run - /// # extern crate tempfile; /// # use std::io; /// use tempfile::NamedTempFile; /// @@ -576,9 +666,9 @@ impl NamedTempFile { /// /// # Security /// - /// Only use this method if you're positive that a - /// temporary file cleaner won't have deleted your file. Otherwise, you - /// might end up persisting an attacker controlled file. + /// This method persists the temporary file using it's path and may not be + /// secure in the in all cases. Please read the security section on the top + /// level documentation of this type for details. /// /// # Errors /// @@ -588,7 +678,6 @@ impl NamedTempFile { /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -631,9 +720,9 @@ impl NamedTempFile { /// /// # Security /// - /// Only use this method if you're positive that a - /// temporary file cleaner won't have deleted your file. Otherwise, you - /// might end up persisting an attacker controlled file. + /// This method persists the temporary file using it's path and may not be + /// secure in the in all cases. Please read the security section on the top + /// level documentation of this type for details. /// /// # Errors /// @@ -644,7 +733,6 @@ impl NamedTempFile { /// /// ```no_run /// # use std::io::{self, Write}; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -674,7 +762,48 @@ impl NamedTempFile { } } - /// Reopen the temporary file. + /// Keep the temporary file from being deleted. This function will turn the + /// temporary file into a non-temporary file without moving it. + /// + /// + /// # Errors + /// + /// On some platforms (e.g., Windows), we need to mark the file as + /// non-temporary. This operation could fail. + /// + /// # Examples + /// + /// ```no_run + /// # use std::io::{self, Write}; + /// use tempfile::NamedTempFile; + /// + /// # fn main() { + /// # if let Err(_) = run() { + /// # ::std::process::exit(1); + /// # } + /// # } + /// # fn run() -> Result<(), io::Error> { + /// let mut file = NamedTempFile::new()?; + /// writeln!(file, "Brian was here. Briefly.")?; + /// + /// let (file, path) = file.keep()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`PathPersistError`]: struct.PathPersistError.html + pub fn keep(self) -> Result<(File, PathBuf), PersistError> { + let (file, path) = (self.file, self.path); + match path.keep() { + Ok(path) => Ok((file, path)), + Err(PathPersistError { error, path }) => Err(PersistError { + file: NamedTempFile { path, file }, + error, + }), + } + } + + /// Securely reopen the temporary file. /// /// This function is useful when you need multiple independent handles to /// the same file. It's perfectly fine to drop the original `NamedTempFile` @@ -685,11 +814,16 @@ impl NamedTempFile { /// /// If the file cannot be reopened, `Err` is returned. /// + /// # Security + /// + /// Unlike `File::open(my_temp_file.path())`, `NamedTempFile::reopen()` + /// guarantees that the re-opened file is the _same_ file, even in the + /// presence of pathological temporary file cleaners. + /// /// # Examples /// /// ```no_run /// # use std::io; - /// # extern crate tempfile; /// use tempfile::NamedTempFile; /// /// # fn main() { @@ -705,7 +839,8 @@ impl NamedTempFile { /// # } /// ``` pub fn reopen(&self) -> io::Result { - imp::reopen(self.as_file(), NamedTempFile::path(self)).with_err_path(|| NamedTempFile::path(self)) + imp::reopen(self.as_file(), NamedTempFile::path(self)) + .with_err_path(|| NamedTempFile::path(self)) } /// Get a reference to the underlying file. @@ -732,6 +867,14 @@ impl NamedTempFile { pub fn into_temp_path(self) -> TempPath { self.path } + + /// Converts the named temporary file into its constituent parts. + /// + /// Note: When the path is dropped, the file is deleted but the file handle + /// is still usable. + pub fn into_parts(self) -> (File, TempPath) { + (self.file, self.path) + } } impl Read for NamedTempFile { @@ -794,8 +937,16 @@ impl std::os::windows::io::AsRawHandle for NamedTempFile { } } -pub(crate) fn create_named(path: PathBuf) -> io::Result { - imp::create_named(&path) +pub(crate) fn create_named( + mut path: PathBuf, + open_options: &mut OpenOptions, +) -> io::Result { + // Make the path absolute. Otherwise, changing directories could cause us to + // delete the wrong file. + if !path.is_absolute() { + path = env::current_dir()?.join(path) + } + imp::create_named(&path, open_options) .with_err_path(|| path.clone()) .map(|file| NamedTempFile { path: TempPath { path }, diff --git a/vendor/tempfile/src/lib.rs b/vendor/tempfile/src/lib.rs index e5b6bd33b0..a4cb574bbc 100644 --- a/vendor/tempfile/src/lib.rs +++ b/vendor/tempfile/src/lib.rs @@ -24,14 +24,14 @@ //! a temporary file cleaner could delete the temporary file which an attacker could then replace. //! //! `tempfile` doesn't rely on file paths so this isn't an issue. However, `NamedTempFile` does -//! rely on file paths. +//! rely on file paths for _some_ operations. See the security documentation on +//! the `NamedTempFile` type for more information. //! //! ## Examples //! //! Create a temporary file and write some data into it: //! //! ``` -//! # extern crate tempfile; //! use tempfile::tempfile; //! use std::io::{self, Write}; //! @@ -49,10 +49,40 @@ //! # } //! ``` //! +//! Create a named temporary file and open an independent file handle: +//! +//! ``` +//! use tempfile::NamedTempFile; +//! use std::io::{self, Write, Read}; +//! +//! # fn main() { +//! # if let Err(_) = run() { +//! # ::std::process::exit(1); +//! # } +//! # } +//! # fn run() -> Result<(), io::Error> { +//! let text = "Brian was here. Briefly."; +//! +//! // Create a file inside of `std::env::temp_dir()`. +//! let mut file1 = NamedTempFile::new()?; +//! +//! // Re-open it. +//! let mut file2 = file1.reopen()?; +//! +//! // Write some test data to the first handle. +//! file1.write_all(text.as_bytes())?; +//! +//! // Read the test data using the second handle. +//! let mut buf = String::new(); +//! file2.read_to_string(&mut buf)?; +//! assert_eq!(buf, text); +//! # Ok(()) +//! # } +//! ``` +//! //! Create a temporary directory and add a file to it: //! //! ``` -//! # extern crate tempfile; //! use tempfile::tempdir; //! use std::fs::File; //! use std::io::{self, Write}; @@ -87,55 +117,51 @@ //! [`NamedTempFile`]: struct.NamedTempFile.html //! [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/tempfile/2.2.0")] +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://docs.rs/tempfile/3.1.0" +)] #![cfg_attr(test, deny(warnings))] +#![deny(rust_2018_idioms)] #[macro_use] extern crate cfg_if; -extern crate rand; -extern crate remove_dir_all; - -#[cfg(unix)] -extern crate libc; - -#[cfg(windows)] -extern crate winapi; - -#[cfg(target_os = "redox")] -extern crate syscall; const NUM_RETRIES: u32 = 1 << 31; const NUM_RAND_CHARS: usize = 6; +use std::ffi::OsStr; +use std::fs::OpenOptions; use std::path::Path; use std::{env, io}; -mod error; mod dir; +mod error; mod file; -mod util; mod spooled; +mod util; -pub use dir::{tempdir, tempdir_in, TempDir}; -pub use file::{tempfile, tempfile_in, NamedTempFile, PersistError, TempPath}; -pub use spooled::{spooled_tempfile, SpooledTempFile}; +pub use crate::dir::{tempdir, tempdir_in, TempDir}; +pub use crate::file::{tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath}; +pub use crate::spooled::{spooled_tempfile, SpooledTempFile}; /// Create a new temporary file or directory with custom parameters. #[derive(Debug, Clone, Eq, PartialEq)] pub struct Builder<'a, 'b> { random_len: usize, - prefix: &'a str, - suffix: &'b str, + prefix: &'a OsStr, + suffix: &'b OsStr, + append: bool, } impl<'a, 'b> Default for Builder<'a, 'b> { fn default() -> Self { Builder { - random_len: ::NUM_RAND_CHARS, - prefix: ".tmp", - suffix: "", + random_len: crate::NUM_RAND_CHARS, + prefix: OsStr::new(".tmp"), + suffix: OsStr::new(""), + append: false, } } } @@ -148,7 +174,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// Create a named temporary file and write some data into it: /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # use std::ffi::OsStr; /// # fn main() { @@ -181,7 +206,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// Create a temporary directory and add a file to it: /// /// ``` - /// # extern crate tempfile; /// # use std::io::{self, Write}; /// # use std::fs::File; /// # use std::ffi::OsStr; @@ -224,7 +248,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Examples /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # fn main() { /// # if let Err(_) = run() { @@ -239,8 +262,8 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Ok(()) /// # } /// ``` - pub fn prefix(&mut self, prefix: &'a str) -> &mut Self { - self.prefix = prefix; + pub fn prefix + ?Sized>(&mut self, prefix: &'a S) -> &mut Self { + self.prefix = prefix.as_ref(); self } @@ -252,7 +275,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Examples /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # fn main() { /// # if let Err(_) = run() { @@ -267,8 +289,8 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Ok(()) /// # } /// ``` - pub fn suffix(&mut self, suffix: &'b str) -> &mut Self { - self.suffix = suffix; + pub fn suffix + ?Sized>(&mut self, suffix: &'b S) -> &mut Self { + self.suffix = suffix.as_ref(); self } @@ -279,7 +301,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Examples /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # fn main() { /// # if let Err(_) = run() { @@ -299,6 +320,32 @@ impl<'a, 'b> Builder<'a, 'b> { self } + /// Set the file to be opened in append mode. + /// + /// Default: `false`. + /// + /// # Examples + /// + /// ``` + /// # use std::io; + /// # fn main() { + /// # if let Err(_) = run() { + /// # ::std::process::exit(1); + /// # } + /// # } + /// # fn run() -> Result<(), io::Error> { + /// # use tempfile::Builder; + /// let named_tempfile = Builder::new() + /// .append(true) + /// .tempfile()?; + /// # Ok(()) + /// # } + /// ``` + pub fn append(&mut self, append: bool) -> &mut Self { + self.append = append; + self + } + /// Create the named temporary file. /// /// # Security @@ -316,7 +363,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Examples /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # fn main() { /// # if let Err(_) = run() { @@ -353,7 +399,6 @@ impl<'a, 'b> Builder<'a, 'b> { /// # Examples /// /// ``` - /// # extern crate tempfile; /// # use std::io; /// # fn main() { /// # if let Err(_) = run() { @@ -375,7 +420,7 @@ impl<'a, 'b> Builder<'a, 'b> { self.prefix, self.suffix, self.random_len, - file::create_named, + |path| file::create_named(path, OpenOptions::new().append(self.append)), ) } diff --git a/vendor/tempfile/src/spooled.rs b/vendor/tempfile/src/spooled.rs index b046c13ab3..e6f750e58c 100644 --- a/vendor/tempfile/src/spooled.rs +++ b/vendor/tempfile/src/spooled.rs @@ -1,7 +1,6 @@ +use crate::file::tempfile; use std::fs::File; -use std::io::{self, Read, Write, Seek, SeekFrom, Cursor}; -use file::tempfile; -use std::mem::drop; +use std::io::{self, Cursor, Read, Seek, SeekFrom, Write}; #[derive(Debug)] enum SpooledInner { @@ -35,7 +34,6 @@ pub struct SpooledTempFile { /// # Examples /// /// ``` -/// # extern crate tempfile; /// use tempfile::spooled_tempfile; /// use std::io::{self, Write}; /// @@ -86,9 +84,8 @@ impl SpooledTempFile { if !self.is_rolled() { let mut file = tempfile()?; if let SpooledInner::InMemory(ref mut cursor) = self.inner { - file.write(cursor.get_ref())?; + file.write_all(cursor.get_ref())?; file.seek(SeekFrom::Start(cursor.position()))?; - drop(cursor); } self.inner = SpooledInner::OnDisk(file); } @@ -103,7 +100,7 @@ impl SpooledTempFile { SpooledInner::InMemory(ref mut cursor) => { cursor.get_mut().resize(size as usize, 0); Ok(()) - }, + } SpooledInner::OnDisk(ref mut file) => file.set_len(size), } } diff --git a/vendor/tempfile/src/util.rs b/vendor/tempfile/src/util.rs index 887070f00a..36c9a7879a 100644 --- a/vendor/tempfile/src/util.rs +++ b/vendor/tempfile/src/util.rs @@ -1,45 +1,39 @@ -use rand; -use rand::RngCore; -use std::ffi::OsString; +use rand::distributions::Alphanumeric; +use rand::{self, Rng}; +use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; -use std::{io, iter}; +use std::{io, str}; -use error::IoResultExt; +use crate::error::IoResultExt; -fn tmpname(prefix: &str, suffix: &str, rand_len: usize) -> OsString { - let mut buf = String::with_capacity(prefix.len() + suffix.len() + rand_len); - buf.push_str(prefix); - buf.extend(iter::repeat('X').take(rand_len)); - buf.push_str(suffix); +fn tmpname(prefix: &OsStr, suffix: &OsStr, rand_len: usize) -> OsString { + let mut buf = OsString::with_capacity(prefix.len() + suffix.len() + rand_len); + buf.push(prefix); - // Randomize. + // Push each character in one-by-one. Unfortunately, this is the only + // safe(ish) simple way to do this without allocating a temporary + // String/Vec. unsafe { - // We guarantee utf8. - let bytes = &mut buf.as_mut_vec()[prefix.len()..prefix.len() + rand_len]; - rand::thread_rng().fill_bytes(bytes); - for byte in bytes.iter_mut() { - *byte = match *byte % 62 { - v @ 0...9 => (v + b'0'), - v @ 10...35 => (v - 10 + b'a'), - v @ 36...61 => (v - 36 + b'A'), - _ => unreachable!(), - } - } + rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(rand_len) + .for_each(|b| buf.push(str::from_utf8_unchecked(&[b as u8]))) } - OsString::from(buf) + buf.push(suffix); + buf } pub fn create_helper( base: &Path, - prefix: &str, - suffix: &str, + prefix: &OsStr, + suffix: &OsStr, random_len: usize, f: F, ) -> io::Result where F: Fn(PathBuf) -> io::Result, { - let num_retries = if random_len != 0 { ::NUM_RETRIES } else { 1 }; + let num_retries = if random_len != 0 { crate::NUM_RETRIES } else { 1 }; for _ in 0..num_retries { let path = base.join(tmpname(prefix, suffix, random_len)); @@ -50,7 +44,8 @@ where } Err(io::Error::new( - io::ErrorKind::AlreadyExists, - "too many temporary files exist")) - .with_err_path(|| base) + io::ErrorKind::AlreadyExists, + "too many temporary files exist", + )) + .with_err_path(|| base) } diff --git a/vendor/tempfile/tests/namedtempfile.rs b/vendor/tempfile/tests/namedtempfile.rs index 3f7f7cbf01..a489d56dba 100644 --- a/vendor/tempfile/tests/namedtempfile.rs +++ b/vendor/tempfile/tests/namedtempfile.rs @@ -1,4 +1,5 @@ -extern crate tempfile; +#![deny(rust_2018_idioms)] + use std::env; use std::fs::File; use std::io::{Read, Seek, SeekFrom, Write}; @@ -95,6 +96,19 @@ fn test_customnamed() { assert_eq!(name.len(), 18); } +#[test] +fn test_append() { + let mut tmpfile = Builder::new().append(true).tempfile().unwrap(); + tmpfile.write(b"a").unwrap(); + tmpfile.seek(SeekFrom::Start(0)).unwrap(); + tmpfile.write(b"b").unwrap(); + + tmpfile.seek(SeekFrom::Start(0)).unwrap(); + let mut buf = vec![0u8; 1]; + tmpfile.read_exact(&mut buf).unwrap(); + assert_eq!(buf, b"a"); +} + #[test] fn test_reopen() { let source = NamedTempFile::new().unwrap(); @@ -201,3 +215,69 @@ fn test_temppath_persist_noclobber() { assert_eq!("abcde", buf); std::fs::remove_file(&persist_path).unwrap(); } + +#[test] +fn test_write_after_close() { + let path = NamedTempFile::new().unwrap().into_temp_path(); + File::create(path).unwrap().write_all(b"test").unwrap(); +} + +#[test] +fn test_change_dir() { + env::set_current_dir(env::temp_dir()).unwrap(); + let tmpfile = NamedTempFile::new_in(".").unwrap(); + let path = env::current_dir().unwrap().join(tmpfile.path()); + env::set_current_dir("/").unwrap(); + drop(tmpfile); + assert!(!exists(path)) +} + +#[test] +fn test_into_parts() { + let mut file = NamedTempFile::new().unwrap(); + write!(file, "abcd").expect("write failed"); + + let (mut file, temp_path) = file.into_parts(); + + let path = temp_path.to_path_buf(); + + assert!(path.exists()); + drop(temp_path); + assert!(!path.exists()); + + write!(file, "efgh").expect("write failed"); + + file.seek(SeekFrom::Start(0)).unwrap(); + let mut buf = String::new(); + file.read_to_string(&mut buf).unwrap(); + assert_eq!("abcdefgh", buf); +} + +#[test] +fn test_keep() { + let mut tmpfile = NamedTempFile::new().unwrap(); + write!(tmpfile, "abcde").unwrap(); + let (mut f, temp_path) = tmpfile.into_parts(); + let path; + { + assert!(exists(&temp_path)); + path = temp_path.keep().unwrap(); + assert!(exists(&path)); + + // Check original file + f.seek(SeekFrom::Start(0)).unwrap(); + let mut buf = String::new(); + f.read_to_string(&mut buf).unwrap(); + assert_eq!("abcde", buf); + } + + { + // Try opening it again. + let mut f = File::open(&path).unwrap(); + f.seek(SeekFrom::Start(0)).unwrap(); + let mut buf = String::new(); + f.read_to_string(&mut buf).unwrap(); + assert_eq!("abcde", buf); + } + std::fs::remove_file(&path).unwrap(); +} diff --git a/vendor/tempfile/tests/spooled.rs b/vendor/tempfile/tests/spooled.rs index fa388aafbf..288d1e6eeb 100644 --- a/vendor/tempfile/tests/spooled.rs +++ b/vendor/tempfile/tests/spooled.rs @@ -1,6 +1,6 @@ -extern crate tempfile; +#![deny(rust_2018_idioms)] -use std::io::{Write, Seek, Read, SeekFrom}; +use std::io::{Read, Seek, SeekFrom, Write}; use tempfile::{spooled_tempfile, SpooledTempFile}; @@ -265,7 +265,10 @@ fn test_set_len(t: &mut SpooledTempFile) { assert_eq!(t.seek(SeekFrom::Current(0)).unwrap(), 10); // tell() assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); assert_eq!(t.read_to_end(&mut buf).unwrap(), 40); - assert_eq!(buf.as_slice(), &b"abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"[..]); + assert_eq!( + buf.as_slice(), + &b"abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"[..] + ); } #[test] diff --git a/vendor/tempfile/tests/tempdir.rs b/vendor/tempfile/tests/tempdir.rs index 6be06779a9..746fe4738c 100644 --- a/vendor/tempfile/tests/tempdir.rs +++ b/vendor/tempfile/tests/tempdir.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate tempfile; +#![deny(rust_2018_idioms)] use std::env; use std::fs; @@ -222,7 +222,8 @@ pub fn dont_double_panic() { // Panic. If TempDir panics *again* due to the rmdir // error then the process will abort. panic!(); - }).join(); + }) + .join(); assert!(r.is_err()); } diff --git a/vendor/tempfile/tests/tempfile.rs b/vendor/tempfile/tests/tempfile.rs index b77da4a670..065dccbe1d 100644 --- a/vendor/tempfile/tests/tempfile.rs +++ b/vendor/tempfile/tests/tempfile.rs @@ -1,8 +1,9 @@ -extern crate tempfile; -use std::io::{Read, Seek, SeekFrom, Write}; +#![deny(rust_2018_idioms)] + use std::fs; -use std::thread; +use std::io::{Read, Seek, SeekFrom, Write}; use std::sync::mpsc::{sync_channel, TryRecvError}; +use std::thread; #[test] fn test_basic() { diff --git a/vendor/term_size/.cargo-checksum.json b/vendor/term_size/.cargo-checksum.json new file mode 100644 index 0000000000..e73b8d94ba --- /dev/null +++ b/vendor/term_size/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"c3ba8be220413f2ed5fce3f49a3888d22e20802f19a237cdaa1171fb13000427","CONTRIBUTORS.md":"fec990280aad6c99316b11a69f7f560fbdf722b5e83d9743449127e8f3d5499b","Cargo.toml":"3202b196bb0c19167c07b8c980550f1d21640e0c4a6b6ce72012fb7b5fbf7a75","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"9cf3574889a4e7f4fe68f532bacd596786057d41eb20fe8e8ed2215d430d8bd3","appveyor.yml":"bd88ad4a942e10ef602540ae592f3e010327dc93aa3d60f07f9f7ff6d3562719","index.html":"d2203968a6fb051d52c55d6e517614c942ea0edbc283e6c3cc8aeb4556eeaad4","justfile":"d89a49bee30578a4af4a4bba4d98578331214370e665561052c0dca7bf956ce1","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/lib.rs":"eab371fe8be05d03bb1cd2a5f1ec3e665423501412383d211552174e21da05c7"},"package":"9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"} \ No newline at end of file diff --git a/vendor/term_size/CHANGELOG.md b/vendor/term_size/CHANGELOG.md new file mode 100644 index 0000000000..3a0d3dfad7 --- /dev/null +++ b/vendor/term_size/CHANGELOG.md @@ -0,0 +1,48 @@ + +## v0.3.0 (2017-04-09) + + +#### Features + +* allows getting the terminal size of all standard streams, or just particular ones ([c7095c95](https://github.com/kbknapp/term_size-rs/commit/c7095c95d633e0a36ea78434bc83349a9711a187)) + + + + +### v0.2.3 (2017-02-21) + +#### Bug Fixes + +* Moves the code into distinct modules and adds dummy functions for unsupported platforms + + + +### v0.2.2 (2017-01-29) + +* Updates deps `libc` and `clippy` + + +### v0.2.1 (2016-09-05) + + +#### Bug Fixes + +* uses libc::winsize instead of homegrown ([216986ec](https://github.com/kbknapp/term_size-rs/commit/216986ecdbe528523953a1cde4cf6c329a0f4fbc), closes [#6](https://github.com/kbknapp/term_size-rs/issues/6)) + + + + +v0.2.0 +## v0.2.0 (2016-09-05) + +#### Features + +* adds support for Windows ([f181c99](https://github.com/kbknapp/term_size-rs/commit/f181c99c0c306b711952a2a4053df904e851413f)) + +#### Documentation + +* **README.md:** + * fixes documentation link ([ca06bf13](https://github.com/kbknapp/term_size-rs/commit/ca06bf132948559032853addd9aa0af022a126e9)) + * minor fixups ([1c269046](https://github.com/kbknapp/term_size-rs/commit/1c2690462b1b1db58d46395c6f1cf098dd769e18)) + + diff --git a/vendor/term_size/CONTRIBUTORS.md b/vendor/term_size/CONTRIBUTORS.md new file mode 100644 index 0000000000..43d92f4248 --- /dev/null +++ b/vendor/term_size/CONTRIBUTORS.md @@ -0,0 +1,11 @@ +the following is a list of contributors: + + +[kbknapp](https://github.com/kbknapp) |[nabijaczleweli](https://github.com/nabijaczleweli) |[vorner](https://github.com/vorner) |[nbaksalyar](https://github.com/nbaksalyar) |[kaegi](https://github.com/kaegi) | +:---: |:---: |:---: |:---: |:---: | +[kbknapp](https://github.com/kbknapp) |[nabijaczleweli](https://github.com/nabijaczleweli) |[vorner](https://github.com/vorner) |[nbaksalyar](https://github.com/nbaksalyar) |[kaegi](https://github.com/kaegi) | + + + + +This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list) diff --git a/vendor/term_size/Cargo.toml b/vendor/term_size/Cargo.toml new file mode 100644 index 0000000000..4b5c0fe744 --- /dev/null +++ b/vendor/term_size/Cargo.toml @@ -0,0 +1,84 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "term_size" +version = "0.3.1" +authors = ["Kevin K. ", "Benjamin Sago "] +exclude = [] +description = "functions for determining terminal sizes and dimensions" +documentation = "https://kbknapp.github.io/term_size-rs" +readme = "README.md" +keywords = ["term", "terminal", "size", "width", "dimension"] +categories = ["command-line-interface"] +license = "MIT/Apache-2.0" +repository = "https://github.com/kbknapp/term_size-rs.git" +[profile.test] +opt-level = 1 +lto = false +codegen-units = 2 +debug = true +debug-assertions = true +rpath = false + +[profile.doc] +opt-level = 0 +lto = false +codegen-units = 4 +debug = true +debug-assertions = true +rpath = false + +[profile.bench] +opt-level = 3 +lto = true +debug = false +debug-assertions = false +rpath = false + +[profile.dev] +opt-level = 0 +lto = false +codegen-units = 4 +debug = true +debug-assertions = true +rpath = false + +[profile.release] +opt-level = 3 +lto = true +debug = false +debug-assertions = false +rpath = false +[dependencies.clippy] +version = "~0.0.112" +optional = true + +[features] +debug = [] +default = [] +lints = ["clippy", "nightly"] +nightly = [] +travis = ["lints", "nightly"] +unstable = [] +[target."cfg(not(target_os = \"windows\"))".dependencies.libc] +version = "~0.2.20" +[target."cfg(target_os = \"windows\")".dependencies.kernel32-sys] +version = "~0.2.2" + +[target."cfg(target_os = \"windows\")".dependencies.winapi] +version = "~0.2.8" +[badges.appveyor] +repository = "kbknapp/term_size-rs" + +[badges.travis-ci] +repository = "kbknapp/term_size-rs" diff --git a/vendor/toml-0.4.10/LICENSE-APACHE b/vendor/term_size/LICENSE-APACHE similarity index 100% rename from vendor/toml-0.4.10/LICENSE-APACHE rename to vendor/term_size/LICENSE-APACHE diff --git a/vendor/owning_ref/LICENSE b/vendor/term_size/LICENSE-MIT similarity index 96% rename from vendor/owning_ref/LICENSE rename to vendor/term_size/LICENSE-MIT index dff72d1e43..5acedf0412 100644 --- a/vendor/owning_ref/LICENSE +++ b/vendor/term_size/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Marvin Löbel +Copyright (c) 2015-2016 Kevin B. Knapp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/term_size/README.md b/vendor/term_size/README.md new file mode 100644 index 0000000000..9f9c6f26aa --- /dev/null +++ b/vendor/term_size/README.md @@ -0,0 +1,63 @@ +term_size +==== + +[![Crates.io](https://img.shields.io/crates/v/term_size.svg)](https://crates.io/crates/term_size) [![Crates.io](https://img.shields.io/crates/d/term_size.svg)](https://crates.io/crates/term_size) [![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/kbknapp/term_size-rs/blob/master/LICENSE-MIT) [![license](http://img.shields.io/badge/license-Apache2.0-blue.svg)](https://github.com/kbknapp/term_size-rs/blob/master/LICENSE-APACHE) [![Coverage Status](https://coveralls.io/repos/kbknapp/term_size-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/kbknapp/term_size-rs?branch=master) [![Join the chat at https://gitter.im/kbknapp/term_size-rs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kbknapp/term_size-rs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Linux: [![Build Status](https://travis-ci.org/kbknapp/term_size-rs.svg?branch=master)](https://travis-ci.org/kbknapp/term_size-rs) +Windows: [![Build status](https://ci.appveyor.com/api/projects/status/6q0x4h6i0e3ypbm5?svg=true +)](https://ci.appveyor.com/project/kbknapp/term_size-rs/branch/master) + +A Rust library to enable getting terminal sizes and dimensions + +[Documentation](https://kbknapp.github.io/term_size-rs) + +## Usage + +First, add the following to your `Cargo.toml`: + +```toml +[dependencies] +term_size = "0.3" +``` + +Next, add this to your crate root: + +```rust +extern crate term_size; +``` + +To get the dimensions of your terminal window, simply use the following: + +```rust +fn main() { + if let Some((w, h)) = term_size::dimensions() { + println!("Width: {}\nHeight: {}", w, h); + } else { + println!("Unable to get term size :(") + } +} +``` + +## License + +Copyright Benjamin Sago, Kevin Knapp, and `term_size` contributors. + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contributing + +1. Fork it! +2. Create your feature branch: `git checkout -b my-new-feature` +3. Commit your changes: `git commit -am 'Add some feature'` +4. Push to the branch: `git push origin my-new-feature` +5. Submit a pull request :D + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the +Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/vendor/term_size/appveyor.yml b/vendor/term_size/appveyor.yml new file mode 100644 index 0000000000..efef69ec25 --- /dev/null +++ b/vendor/term_size/appveyor.yml @@ -0,0 +1,12 @@ +install: + - ps: Start-FileDownload 'https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe' + - rust-nightly-i686-pc-windows-gnu.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - rustc -V + - cargo -V + +build: false + +test_script: + - cargo build --verbose + - cargo test --verbose diff --git a/vendor/term_size/index.html b/vendor/term_size/index.html new file mode 100644 index 0000000000..0b03ded533 --- /dev/null +++ b/vendor/term_size/index.html @@ -0,0 +1 @@ + diff --git a/vendor/term_size/justfile b/vendor/term_size/justfile new file mode 100644 index 0000000000..64ec724e38 --- /dev/null +++ b/vendor/term_size/justfile @@ -0,0 +1,39 @@ +@update-contributors: + echo 'Removing old CONTRIBUTORS.md' + mv CONTRIBUTORS.md CONTRIBUTORS.md.bak + echo 'Downloading a list of new contributors' + echo "the following is a list of contributors:" > CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + githubcontrib --owner kbknapp --repo term_size-rs --sha master --cols 6 --format md --showlogin true --sortBy contributions --sortOrder desc >> CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + echo "" >> CONTRIBUTORS.md + echo "This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list)" >> CONTRIBUTORS.md + rm CONTRIBUTORS.md.bak + +run-test TEST: + cargo test --test {{TEST}} + +debug TEST: + cargo test --test {{TEST}} --features debug + +run-tests: + cargo test --features "yaml unstable" + +@bench: nightly + cargo bench && just remove-nightly + +nightly: + rustup override add nightly + +remove-nightly: + rustup override remove + +@lint: nightly + cargo build --features lints && just remove-nightly + +clean: + cargo clean + find . -type f -name "*.orig" -exec rm {} \; + find . -type f -name "*.bk" -exec rm {} \; + find . -type f -name ".*~" -exec rm {} \; diff --git a/vendor/term_size/rustfmt.toml b/vendor/term_size/rustfmt.toml new file mode 100644 index 0000000000..0136d86e31 --- /dev/null +++ b/vendor/term_size/rustfmt.toml @@ -0,0 +1,4 @@ +format_strings = false +chain_overflow_last = false +same_line_if_else = true +fn_single_line = true diff --git a/vendor/term_size/src/lib.rs b/vendor/term_size/src/lib.rs new file mode 100644 index 0000000000..da2b96cbe3 --- /dev/null +++ b/vendor/term_size/src/lib.rs @@ -0,0 +1,237 @@ +// The following was originally taken and adapated from exa source +// repo: https://github.com/ogham/exa +// commit: b9eb364823d0d4f9085eb220233c704a13d0f611 +// license: MIT - Copyright (c) 2014 Benjamin Sago + +//! System calls for getting the terminal size. +//! +//! Getting the terminal size is performed using an ioctl command that takes +//! the file handle to the terminal -- which in this case, is stdout -- and +//! populates a structure containing the values. +//! +//! The size is needed when the user wants the output formatted into columns: +//! the default grid view, or the hybrid grid-details view. + +#[cfg(not(target_os = "windows"))] +extern crate libc; +#[cfg(target_os = "windows")] +extern crate kernel32; +#[cfg(target_os = "windows")] +extern crate winapi; + +pub use platform::{dimensions, dimensions_stdout, dimensions_stdin, dimensions_stderr}; + +#[cfg(any(target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "ios", + target_os = "bitrig", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris"))] +mod platform { + use libc::{STDOUT_FILENO, STDIN_FILENO, STDERR_FILENO, c_int, c_ulong, winsize}; + use std::mem::zeroed; + + // Unfortunately the actual command is not standardised... + #[cfg(any(target_os = "linux", target_os = "android"))] + static TIOCGWINSZ: c_ulong = 0x5413; + + #[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "bitrig", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd"))] + static TIOCGWINSZ: c_ulong = 0x40087468; + + #[cfg(target_os = "solaris")] + static TIOCGWINSZ: c_ulong = 0x5468; + + extern "C" { + fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; + } + + /// Runs the ioctl command. Returns (0, 0) if all of the streams are not to a terminal, or + /// there is an error. (0, 0) is an invalid size to have anyway, which is why + /// it can be used as a nil value. + unsafe fn get_dimensions_any() -> winsize { + let mut window: winsize = zeroed(); + let mut result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window); + + if result == -1 { + window = zeroed(); + result = ioctl(STDIN_FILENO, TIOCGWINSZ, &mut window); + if result == -1 { + window = zeroed(); + result = ioctl(STDERR_FILENO, TIOCGWINSZ, &mut window); + if result == -1 { + return zeroed(); + } + } + } + window + } + + /// Runs the ioctl command. Returns (0, 0) if the output is not to a terminal, or + /// there is an error. (0, 0) is an invalid size to have anyway, which is why + /// it can be used as a nil value. + unsafe fn get_dimensions_out() -> winsize { + let mut window: winsize = zeroed(); + let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window); + + if result != -1 { + return window; + } + zeroed() + } + + /// Runs the ioctl command. Returns (0, 0) if the input is not to a terminal, or + /// there is an error. (0, 0) is an invalid size to have anyway, which is why + /// it can be used as a nil value. + unsafe fn get_dimensions_in() -> winsize { + let mut window: winsize = zeroed(); + let result = ioctl(STDIN_FILENO, TIOCGWINSZ, &mut window); + + if result != -1 { + return window; + } + zeroed() + } + + /// Runs the ioctl command. Returns (0, 0) if the error is not to a terminal, or + /// there is an error. (0, 0) is an invalid size to have anyway, which is why + /// it can be used as a nil value. + unsafe fn get_dimensions_err() -> winsize { + let mut window: winsize = zeroed(); + let result = ioctl(STDERR_FILENO, TIOCGWINSZ, &mut window); + + if result != -1 { + return window; + } + zeroed() + } + + /// Query the current processes's output (`stdout`), input (`stdin`), and error (`stderr`) in + /// that order, in the attempt to dtermine terminal width. If one of those streams is actually + /// a tty, this function returns its width and height as a number of characters. + /// + /// If *all* of the streams are not ttys or return any errors this function will return `None`. + pub fn dimensions() -> Option<(usize, usize)> { + let w = unsafe { get_dimensions_any() }; + + if w.ws_col == 0 || w.ws_row == 0 { + None + } else { + Some((w.ws_col as usize, w.ws_row as usize)) + } + } + + /// Query the current processes's output (`stdout`) *only*, in the attempt to dtermine + /// terminal width. If that streams is actually a tty, this function returns its width + /// and height as a number of characters. + /// + /// If *all* of the streams are not ttys or return any errors this function will return `None`. + pub fn dimensions_stdout() -> Option<(usize, usize)> { + let w = unsafe { get_dimensions_out() }; + + if w.ws_col == 0 || w.ws_row == 0 { + None + } else { + Some((w.ws_col as usize, w.ws_row as usize)) + } + } + + /// Query the current processes's input (`stdin`) *only*, in the attempt to dtermine + /// terminal width. If that streams is actually a tty, this function returns its width + /// and height as a number of characters. + /// + /// If *all* of the streams are not ttys or return any errors this function will return `None`. + pub fn dimensions_stdin() -> Option<(usize, usize)> { + let w = unsafe { get_dimensions_in() }; + + if w.ws_col == 0 || w.ws_row == 0 { + None + } else { + Some((w.ws_col as usize, w.ws_row as usize)) + } + } + + /// Query the current processes's error output (`stderr`) *only*, in the attempt to dtermine + /// terminal width. If that streams is actually a tty, this function returns its width + /// and height as a number of characters. + /// + /// If *all* of the streams are not ttys or return any errors this function will return `None`. + pub fn dimensions_stderr() -> Option<(usize, usize)> { + let w = unsafe { get_dimensions_err() }; + + if w.ws_col == 0 || w.ws_row == 0 { + None + } else { + Some((w.ws_col as usize, w.ws_row as usize)) + } + } +} + +#[cfg(target_os = "windows")] +mod platform { + use kernel32::{GetConsoleScreenBufferInfo, GetStdHandle}; + use winapi::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT, STD_OUTPUT_HANDLE}; + + /// Query the current processes's output, returning its width and height as a + /// number of characters. Returns `None` if the output isn't to a terminal. + pub fn dimensions() -> Option<(usize, usize)> { + let null_coord = COORD { X: 0, Y: 0 }; + let null_smallrect = SMALL_RECT { + Left: 0, + Top: 0, + Right: 0, + Bottom: 0, + }; + + let stdout_h = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) }; + let mut console_data = CONSOLE_SCREEN_BUFFER_INFO { + dwSize: null_coord, + dwCursorPosition: null_coord, + wAttributes: 0, + srWindow: null_smallrect, + dwMaximumWindowSize: null_coord, + }; + + if unsafe { GetConsoleScreenBufferInfo(stdout_h, &mut console_data) } != 0 { + Some(((console_data.srWindow.Right - console_data.srWindow.Left) as usize, + (console_data.srWindow.Bottom - console_data.srWindow.Top) as usize)) + } else { + None + } + } + /// Query the current processes's output, returning its width and height as a + /// number of characters. Returns `None` if the output isn't to a terminal. + pub fn dimensions_stdout() -> Option<(usize, usize)> { dimensions() } + /// This isn't implemented for Windows + pub fn dimensions_stdin() -> Option<(usize, usize)> { unimplemented!() } + /// This isn't implemented for Windows + pub fn dimensions_stderr() -> Option<(usize, usize)> { unimplemented!() } +} + +// makes project compilable on unsupported platforms +#[cfg(not(any(target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "ios", + target_os = "bitrig", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "windows")))] +mod platform { + pub fn dimensions() -> Option<(usize, usize)> { None } + pub fn dimensions_stdout() -> Option<(usize, usize)> { None } + pub fn dimensions_stdin() -> Option<(usize, usize)> { None } + pub fn dimensions_stderr() -> Option<(usize, usize)> { None } +} diff --git a/vendor/textwrap/.cargo-checksum.json b/vendor/textwrap/.cargo-checksum.json index 37c2d446c1..02794aab85 100644 --- a/vendor/textwrap/.cargo-checksum.json +++ b/vendor/textwrap/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5d03f24b7d5cd88dd89e8b72a35c9c92d80366841d80c99d7d160557bdf6b7b9","LICENSE":"ce93600c49fbb3e14df32efe752264644f6a2f8e08a735ba981725799e5309ef","README.md":"ba2c306833964b8d7b251068303b9b610ea952e12df1b1c765d53e0654277229","benches/linear.rs":"068432718816fed5b4a46132826d119d7102f9b61896e391136e885ce5ac29ee","examples/layout.rs":"576157b6d6c7e5b8c12b3f477d23dc6801d2f22d3b0292cf0a19434d3d967c2c","examples/termwidth.rs":"f969e869802d21daf59d1ae23c668539bfb493d5b9ef9c7cbc9de30ce315a529","src/lib.rs":"5331d506de207a2218c1627245f09c5f894d3cdac1776ebdb96abc600d19bc0d","tests/version-numbers.rs":"0d75532e72e9054cb8c8c12b8851e55fad7319ed14482b562f6806872f18dd0f"},"package":"307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"} \ No newline at end of file +{"files":{"Cargo.toml":"a0e3c783725beb480b666d52d49da0ec69865c82e8bd5c8a76ba330158e954c1","LICENSE":"ce93600c49fbb3e14df32efe752264644f6a2f8e08a735ba981725799e5309ef","README.md":"9af1f6627e8c2e19c7383c99462ca028b235b2f8dadbb33f13e2d1663c8c20e3","benches/linear.rs":"ec084063923bafc6e80c2cd78deb0f7ad18ae19a7e66005e991e00dac1ff3ce4","examples/layout.rs":"38cf4d316d28e0b99925bef604b68aad05489c06ec77e6105575cd26ce994631","examples/termwidth.rs":"67d95b60feb52cfd59fe5b17c37c53e51fb7f2a8e5e483d75aec8d0044dbcbd7","src/indentation.rs":"04f8479286fd87f2d75b0f02ce8309a815a5ffd1e79a7323132e34dc0e107aef","src/lib.rs":"115bf6ec566b8241d52cff83977146f03df3460d6f94ad897f2221cb56100118","src/splitting.rs":"071ef8ce0ea6c3f33230889a3426fd645276a6de626f45223ae7b873394df662","tests/version-numbers.rs":"e0e9316073d6d410440a6ee33c2f3bdfd0faa48895f6f9d05a220a91b7afcc99"},"package":"d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"} \ No newline at end of file diff --git a/vendor/textwrap/Cargo.toml b/vendor/textwrap/Cargo.toml index 3738621665..4ec570f10c 100644 --- a/vendor/textwrap/Cargo.toml +++ b/vendor/textwrap/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "textwrap" -version = "0.10.0" +version = "0.11.0" authors = ["Martin Geisler "] exclude = [".dir-locals.el"] description = "Textwrap is a small library for word wrapping, indenting, and\ndedenting strings.\n\nYou can use it to format strings (such as help and error messages) for\ndisplay in commandline applications. It is designed to be efficient\nand handle Unicode characters correctly.\n" @@ -25,7 +25,8 @@ repository = "https://github.com/mgeisler/textwrap" [package.metadata.docs.rs] all-features = true [dependencies.hyphenation] -version = "0.6.1" +version = "0.7.1" +features = ["embed_all"] optional = true [dependencies.term_size] @@ -35,15 +36,21 @@ optional = true [dependencies.unicode-width] version = "0.1.3" [dev-dependencies.lipsum] -version = "0.5" +version = "0.6" [dev-dependencies.rand] -version = "0.4" +version = "0.6" + +[dev-dependencies.rand_xorshift] +version = "0.1" [dev-dependencies.version-sync] -version = "0.5" +version = "0.6" [badges.appveyor] repository = "mgeisler/textwrap" +[badges.codecov] +repository = "mgeisler/textwrap" + [badges.travis-ci] repository = "mgeisler/textwrap" diff --git a/vendor/textwrap/README.md b/vendor/textwrap/README.md index 71489eb1a9..23a5439043 100644 --- a/vendor/textwrap/README.md +++ b/vendor/textwrap/README.md @@ -4,6 +4,7 @@ [![](https://docs.rs/textwrap/badge.svg)][api-docs] [![](https://travis-ci.org/mgeisler/textwrap.svg?branch=master)][travis-ci] [![](https://ci.appveyor.com/api/projects/status/github/mgeisler/textwrap?branch=master&svg=true)][appveyor] +[![](https://codecov.io/gh/mgeisler/textwrap/branch/master/graph/badge.svg)][codecov] Textwrap is a small Rust crate for word wrapping text. You can use it to format strings for display in commandline applications. The crate @@ -15,7 +16,7 @@ the [Python textwrap module][py-textwrap]. Add this to your `Cargo.toml`: ```toml [dependencies] -textwrap = "0.10" +textwrap = "0.11" ``` and this to your crate root: @@ -27,7 +28,7 @@ If you would like to have automatic hyphenation, specify the dependency as: ```toml [dependencies] -textwrap = { version = "0.10", features = ["hyphenation"] } +textwrap = { version = "0.11", features = ["hyphenation"] } ``` To conveniently wrap text at the current terminal width, enable the @@ -35,7 +36,7 @@ To conveniently wrap text at the current terminal width, enable the ```toml [dependencies] -textwrap = { version = "0.10", features = ["term_size"] } +textwrap = { version = "0.11", features = ["term_size"] } ``` ## Documentation @@ -68,12 +69,12 @@ configure the hyphenation patterns to use: extern crate hyphenation; extern crate textwrap; -use hyphenation::Language; +use hyphenation::{Language, Load, Standard}; use textwrap::Wrapper; fn main() { - let corpus = hyphenation::load(Language::English_US).unwrap(); - let wrapper = Wrapper::with_splitter(18, corpus); + let hyphenator = Standard::from_embedded(Language::EnglishUS).unwrap(); + let wrapper = Wrapper::with_splitter(18, hyphenator); let text = "textwrap: a small library for wrapping text."; println!("{}", wrapper.fill(text)) } @@ -181,13 +182,20 @@ cost abstractions. This section lists the largest changes per release. +### Version 0.11.0 — December 9th, 2018 + +Due to our dependencies bumping their minimum supported version of +Rust, the minimum version of Rust we test against is now 1.22.0. + +* Merged [#141][issue-141]: Fix `dedent` handling of empty lines and + trailing newlines. Thanks @bbqsrc! +* Fixed [#151][issue-151]: Release of version with hyphenation 0.7. + ### Version 0.10.0 — April 28th, 2018 Due to our dependencies bumping their minimum supported version of Rust, the minimum version of Rust we test against is now 1.17.0. -Issues closed: - * Fixed [#99][issue-99]: Word broken even though it would fit on line. * Fixed [#107][issue-107]: Automatic hyphenation is off by one. * Fixed [#122][issue-122]: Take newlines into account when wrapping. @@ -204,8 +212,6 @@ Added a regression test for the case where `width` is set to `usize::MAX`, thanks @Fraser999! All public structs now implement `Debug`, thanks @hcpl! -Issues closed: - * Fixed [#101][issue-101]: Make `term_size` an optional dependency. ### Version 0.8.0 — September 4th, 2017 @@ -219,12 +225,9 @@ The `Wrapper` struct has two new methods that will wrap the input text lazily: `Wrapper::wrap_iter` and `Wrapper::into_wrap_iter`. Use those if you will be iterating over the wrapped lines one by one. -Issues closed: - * Fixed [#59][issue-59]: `wrap` could return an iterator. Thanks @hcpl! - -* Fixed [#81][issue-81]: Set `html_root_url` +* Fixed [#81][issue-81]: Set `html_root_url`. ### Version 0.7.0 — July 20th, 2017 @@ -241,12 +244,8 @@ The `squeeze_whitespace` option has been removed since it was complicating the above optimization. Let us know if this option is important for you so we can provide a work around. -Issues closed: - -* Fixed [#58][issue-58]: Add a "fast_wrap" function that reuses the - input string - -* Fixed [#61][issue-61]: Documentation errors +* Fixed [#58][issue-58]: Add a "fast_wrap" function. +* Fixed [#61][issue-61]: Documentation errors. ### Version 0.6.0 — May 22nd, 2017 @@ -260,9 +259,7 @@ let wrapper = Wrapper::new(60).break_words(false); It also add a new `NoHyphenation` word splitter that will never split words, not even at existing hyphens. -Issues closed: - -* Fixed [#28][issue-28]: Support not squeezing whitespace +* Fixed [#28][issue-28]: Support not squeezing whitespace. ### Version 0.5.0 — May 15th, 2017 @@ -281,20 +278,18 @@ wrapper.splitter = Box::new(corpus); Other changes include optimizations, so version 0.5.0 is roughly 10-15% faster than version 0.4.0. -Issues closed: - -* Fixed [#19][issue-19]: Add support for finding terminal size -* Fixed [#25][issue-25]: Handle words longer than `self.width` -* Fixed [#26][issue-26]: Support custom indentation -* Fixed [#36][issue-36]: Support building without `hyphenation` -* Fixed [#39][issue-39]: Respect non-breaking spaces +* Fixed [#19][issue-19]: Add support for finding terminal size. +* Fixed [#25][issue-25]: Handle words longer than `self.width`. +* Fixed [#26][issue-26]: Support custom indentation. +* Fixed [#36][issue-36]: Support building without `hyphenation`. +* Fixed [#39][issue-39]: Respect non-breaking spaces. ### Version 0.4.0 — January 24th, 2017 Documented complexities and tested these via `cargo bench`. -* Fixed [#13][issue-13]: Immediatedly add word if it fits -* Fixed [#14][issue-14]: Avoid splitting on initial hyphens in `--foo-bar` +* Fixed [#13][issue-13]: Immediatedly add word if it fits. +* Fixed [#14][issue-14]: Avoid splitting on initial hyphens. ### Version 0.3.0 — January 7th, 2017 @@ -316,6 +311,7 @@ Contributions will be accepted under the same license. [crates-io]: https://crates.io/crates/textwrap [travis-ci]: https://travis-ci.org/mgeisler/textwrap [appveyor]: https://ci.appveyor.com/project/mgeisler/textwrap +[codecov]: https://codecov.io/gh/mgeisler/textwrap [py-textwrap]: https://docs.python.org/library/textwrap [patterns]: https://github.com/tapeinosyne/hyphenation/tree/master/patterns-tex [api-docs]: https://docs.rs/textwrap/ @@ -336,4 +332,6 @@ Contributions will be accepted under the same license. [issue-107]: https://github.com/mgeisler/textwrap/issues/107 [issue-122]: https://github.com/mgeisler/textwrap/issues/122 [issue-129]: https://github.com/mgeisler/textwrap/issues/129 +[issue-141]: https://github.com/mgeisler/textwrap/issues/141 +[issue-151]: https://github.com/mgeisler/textwrap/issues/151 [mit]: LICENSE diff --git a/vendor/textwrap/benches/linear.rs b/vendor/textwrap/benches/linear.rs index 94e350b97d..104398a1b6 100644 --- a/vendor/textwrap/benches/linear.rs +++ b/vendor/textwrap/benches/linear.rs @@ -7,13 +7,15 @@ extern crate hyphenation; extern crate lipsum; extern crate rand; +extern crate rand_xorshift; extern crate test; extern crate textwrap; #[cfg(feature = "hyphenation")] -use hyphenation::Language; +use hyphenation::{Language, Load, Standard}; use lipsum::MarkovChain; -use rand::XorShiftRng; +use rand::SeedableRng; +use rand_xorshift::XorShiftRng; use test::Bencher; #[cfg(feature = "hyphenation")] use textwrap::Wrapper; @@ -25,7 +27,7 @@ fn lorem_ipsum(length: usize) -> String { // The average word length in the lorem ipsum text is somewhere // between 6 and 7. So we conservatively divide by 5 to have a // long enough text that we can truncate below. - let rng = XorShiftRng::new_unseeded(); + let rng = XorShiftRng::seed_from_u64(0); let mut chain = MarkovChain::new_with_rng(rng); chain.learn(lipsum::LOREM_IPSUM); chain.learn(lipsum::LIBER_PRIMUS); @@ -87,8 +89,8 @@ fn wrap_800(b: &mut Bencher) { #[cfg(feature = "hyphenation")] fn hyphenation_fill_100(b: &mut Bencher) { let text = &lorem_ipsum(100); - let corpus = hyphenation::load(Language::Latin).unwrap(); - let wrapper = Wrapper::with_splitter(LINE_LENGTH, corpus); + let dictionary = Standard::from_embedded(Language::Latin).unwrap(); + let wrapper = Wrapper::with_splitter(LINE_LENGTH, dictionary); b.iter(|| wrapper.fill(text)) } @@ -96,8 +98,8 @@ fn hyphenation_fill_100(b: &mut Bencher) { #[cfg(feature = "hyphenation")] fn hyphenation_fill_200(b: &mut Bencher) { let text = &lorem_ipsum(200); - let corpus = hyphenation::load(Language::Latin).unwrap(); - let wrapper = Wrapper::with_splitter(LINE_LENGTH, corpus); + let dictionary = Standard::from_embedded(Language::Latin).unwrap(); + let wrapper = Wrapper::with_splitter(LINE_LENGTH, dictionary); b.iter(|| wrapper.fill(text)) } @@ -105,8 +107,8 @@ fn hyphenation_fill_200(b: &mut Bencher) { #[cfg(feature = "hyphenation")] fn hyphenation_fill_400(b: &mut Bencher) { let text = &lorem_ipsum(400); - let corpus = hyphenation::load(Language::Latin).unwrap(); - let wrapper = Wrapper::with_splitter(LINE_LENGTH, corpus); + let dictionary = Standard::from_embedded(Language::Latin).unwrap(); + let wrapper = Wrapper::with_splitter(LINE_LENGTH, dictionary); b.iter(|| wrapper.fill(text)) } @@ -114,7 +116,7 @@ fn hyphenation_fill_400(b: &mut Bencher) { #[cfg(feature = "hyphenation")] fn hyphenation_fill_800(b: &mut Bencher) { let text = &lorem_ipsum(800); - let corpus = hyphenation::load(Language::Latin).unwrap(); - let wrapper = Wrapper::with_splitter(LINE_LENGTH, corpus); + let dictionary = Standard::from_embedded(Language::Latin).unwrap(); + let wrapper = Wrapper::with_splitter(LINE_LENGTH, dictionary); b.iter(|| wrapper.fill(text)) } diff --git a/vendor/textwrap/examples/layout.rs b/vendor/textwrap/examples/layout.rs index caa9340646..d36cb3ab93 100644 --- a/vendor/textwrap/examples/layout.rs +++ b/vendor/textwrap/examples/layout.rs @@ -3,7 +3,7 @@ extern crate hyphenation; extern crate textwrap; #[cfg(feature = "hyphenation")] -use hyphenation::Language; +use hyphenation::{Language, Load}; use textwrap::Wrapper; #[cfg(not(feature = "hyphenation"))] @@ -12,9 +12,9 @@ fn new_wrapper<'a>() -> Wrapper<'a, textwrap::HyphenSplitter> { } #[cfg(feature = "hyphenation")] -fn new_wrapper<'a>() -> Wrapper<'a, hyphenation::Corpus> { - let corpus = hyphenation::load(Language::English_US).unwrap(); - Wrapper::with_splitter(0, corpus) +fn new_wrapper<'a>() -> Wrapper<'a, hyphenation::Standard> { + let dictionary = hyphenation::Standard::from_embedded(Language::EnglishUS).unwrap(); + Wrapper::with_splitter(0, dictionary) } fn main() { diff --git a/vendor/textwrap/examples/termwidth.rs b/vendor/textwrap/examples/termwidth.rs index 7d81a5c654..75db3aa7e4 100644 --- a/vendor/textwrap/examples/termwidth.rs +++ b/vendor/textwrap/examples/termwidth.rs @@ -1,6 +1,12 @@ -#[cfg(feature = "term_size")] +#[cfg(feature = "hyphenation")] +extern crate hyphenation; extern crate textwrap; +#[cfg(feature = "hyphenation")] +use hyphenation::{Language, Load, Standard}; +#[cfg(feature = "term_size")] +use textwrap::Wrapper; + #[cfg(not(feature = "term_size"))] fn main() { println!("Please enable the term_size feature to run this example."); @@ -8,13 +14,27 @@ fn main() { #[cfg(feature = "term_size")] fn main() { + #[cfg(not(feature = "hyphenation"))] + fn new_wrapper<'a>() -> (&'static str, Wrapper<'a, textwrap::HyphenSplitter>) { + ("without hyphenation", Wrapper::with_termwidth()) + } + + #[cfg(feature = "hyphenation")] + fn new_wrapper<'a>() -> (&'static str, Wrapper<'a, Standard>) { + let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); + ( + "with hyphenation", + Wrapper::with_splitter(textwrap::termwidth(), dictionary), + ) + } + let example = "Memory safety without garbage collection. \ Concurrency without data races. \ Zero-cost abstractions."; // Create a new Wrapper -- automatically set the width to the // current terminal width. - let wrapper = textwrap::Wrapper::with_termwidth(); - println!("Formatted in within {} columns:", wrapper.width); + let (msg, wrapper) = new_wrapper(); + println!("Formatted {} in {} columns:", msg, wrapper.width); println!("----"); println!("{}", wrapper.fill(example)); println!("----"); diff --git a/vendor/textwrap/src/indentation.rs b/vendor/textwrap/src/indentation.rs new file mode 100644 index 0000000000..276ba10553 --- /dev/null +++ b/vendor/textwrap/src/indentation.rs @@ -0,0 +1,294 @@ +//! Functions related to adding and removing indentation from lines of +//! text. +//! +//! The functions here can be used to uniformly indent or dedent +//! (unindent) word wrapped lines of text. + +/// Add prefix to each non-empty line. +/// +/// ``` +/// use textwrap::indent; +/// +/// assert_eq!(indent(" +/// Foo +/// Bar +/// ", " "), " +/// Foo +/// Bar +/// "); +/// ``` +/// +/// Empty lines (lines consisting only of whitespace) are not indented +/// and the whitespace is replaced by a single newline (`\n`): +/// +/// ``` +/// use textwrap::indent; +/// +/// assert_eq!(indent(" +/// Foo +/// +/// Bar +/// \t +/// Baz +/// ", "->"), " +/// ->Foo +/// +/// ->Bar +/// +/// ->Baz +/// "); +/// ``` +/// +/// Leading and trailing whitespace on non-empty lines is kept +/// unchanged: +/// +/// ``` +/// use textwrap::indent; +/// +/// assert_eq!(indent(" \t Foo ", "->"), "-> \t Foo \n"); +/// ``` +pub fn indent(s: &str, prefix: &str) -> String { + let mut result = String::new(); + for line in s.lines() { + if line.chars().any(|c| !c.is_whitespace()) { + result.push_str(prefix); + result.push_str(line); + } + result.push('\n'); + } + result +} + +/// Removes common leading whitespace from each line. +/// +/// This function will look at each non-empty line and determine the +/// maximum amount of whitespace that can be removed from all lines: +/// +/// ``` +/// use textwrap::dedent; +/// +/// assert_eq!(dedent(" +/// 1st line +/// 2nd line +/// 3rd line +/// "), " +/// 1st line +/// 2nd line +/// 3rd line +/// "); +/// ``` +pub fn dedent(s: &str) -> String { + let mut prefix = ""; + let mut lines = s.lines(); + + // We first search for a non-empty line to find a prefix. + for line in &mut lines { + let mut whitespace_idx = line.len(); + for (idx, ch) in line.char_indices() { + if !ch.is_whitespace() { + whitespace_idx = idx; + break; + } + } + + // Check if the line had anything but whitespace + if whitespace_idx < line.len() { + prefix = &line[..whitespace_idx]; + break; + } + } + + // We then continue looking through the remaining lines to + // possibly shorten the prefix. + for line in &mut lines { + let mut whitespace_idx = line.len(); + for ((idx, a), b) in line.char_indices().zip(prefix.chars()) { + if a != b { + whitespace_idx = idx; + break; + } + } + + // Check if the line had anything but whitespace and if we + // have found a shorter prefix + if whitespace_idx < line.len() && whitespace_idx < prefix.len() { + prefix = &line[..whitespace_idx]; + } + } + + // We now go over the lines a second time to build the result. + let mut result = String::new(); + for line in s.lines() { + if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) { + let (_, tail) = line.split_at(prefix.len()); + result.push_str(tail); + } + result.push('\n'); + } + + if result.ends_with('\n') && !s.ends_with('\n') { + let new_len = result.len() - 1; + result.truncate(new_len); + } + + result +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Add newlines. Ensures that the final line in the vector also + /// has a newline. + fn add_nl(lines: &[&str]) -> String { + lines.join("\n") + "\n" + } + + #[test] + fn indent_empty() { + assert_eq!(indent("\n", " "), "\n"); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn indent_nonempty() { + let x = vec![" foo", + "bar", + " baz"]; + let y = vec!["// foo", + "//bar", + "// baz"]; + assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn indent_empty_line() { + let x = vec![" foo", + "bar", + "", + " baz"]; + let y = vec!["// foo", + "//bar", + "", + "// baz"]; + assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y)); + } + + #[test] + fn dedent_empty() { + assert_eq!(dedent(""), ""); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_multi_line() { + let x = vec![" foo", + " bar", + " baz"]; + let y = vec![" foo", + "bar", + " baz"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_empty_line() { + let x = vec![" foo", + " bar", + " ", + " baz"]; + let y = vec![" foo", + "bar", + "", + " baz"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_blank_line() { + let x = vec![" foo", + "", + " bar", + " foo", + " bar", + " baz"]; + let y = vec!["foo", + "", + " bar", + " foo", + " bar", + " baz"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_whitespace_line() { + let x = vec![" foo", + " ", + " bar", + " foo", + " bar", + " baz"]; + let y = vec!["foo", + "", + " bar", + " foo", + " bar", + " baz"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_mixed_whitespace() { + let x = vec!["\tfoo", + " bar"]; + let y = vec!["\tfoo", + " bar"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_tabbed_whitespace() { + let x = vec!["\t\tfoo", + "\t\t\tbar"]; + let y = vec!["foo", + "\tbar"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_mixed_tabbed_whitespace() { + let x = vec!["\t \tfoo", + "\t \t\tbar"]; + let y = vec!["foo", + "\tbar"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_mixed_tabbed_whitespace2() { + let x = vec!["\t \tfoo", + "\t \tbar"]; + let y = vec!["\tfoo", + " \tbar"]; + assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn dedent_preserve_no_terminating_newline() { + let x = vec![" foo", + " bar"].join("\n"); + let y = vec!["foo", + " bar"].join("\n"); + assert_eq!(dedent(&x), y); + } +} diff --git a/vendor/textwrap/src/lib.rs b/vendor/textwrap/src/lib.rs index 1cee8209b9..2f82325fbc 100644 --- a/vendor/textwrap/src/lib.rs +++ b/vendor/textwrap/src/lib.rs @@ -41,7 +41,7 @@ //! //! [unicode-width]: https://docs.rs/unicode-width/ -#![doc(html_root_url = "https://docs.rs/textwrap/0.10.0")] +#![doc(html_root_url = "https://docs.rs/textwrap/0.11.0")] #![deny(missing_docs)] #![deny(missing_debug_implementations)] @@ -54,143 +54,18 @@ extern crate unicode_width; use std::borrow::Cow; use std::str::CharIndices; -#[cfg(feature = "hyphenation")] -use hyphenation::{Corpus, Hyphenation}; use unicode_width::UnicodeWidthChar; use unicode_width::UnicodeWidthStr; /// A non-breaking space. const NBSP: char = '\u{a0}'; -/// An interface for splitting words. -/// -/// When the [`wrap_iter`] method will try to fit text into a line, it -/// will eventually find a word that it too large the current text -/// width. It will then call the currently configured `WordSplitter` to -/// have it attempt to split the word into smaller parts. This trait -/// describes that functionality via the [`split`] method. -/// -/// If the `textwrap` crate has been compiled with the `hyphenation` -/// feature enabled, you will find an implementation of `WordSplitter` -/// by the `hyphenation::language::Corpus` struct. Use this struct for -/// language-aware hyphenation. See the [`hyphenation` documentation] -/// for details. -/// -/// [`wrap_iter`]: struct.Wrapper.html#method.wrap_iter -/// [`split`]: #tymethod.split -/// [`hyphenation` documentation]: https://docs.rs/hyphenation/ -pub trait WordSplitter { - /// Return all possible splits of word. Each split is a triple - /// with a head, a hyphen, and a tail where `head + &hyphen + - /// &tail == word`. The hyphen can be empty if there is already a - /// hyphen in the head. - /// - /// The splits should go from smallest to longest and should - /// include no split at all. So the word "technology" could be - /// split into - /// - /// ```no_run - /// vec![("tech", "-", "nology"), - /// ("technol", "-", "ogy"), - /// ("technolo", "-", "gy"), - /// ("technology", "", "")]; - /// ``` - fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)>; -} - -/// Use this as a [`Wrapper.splitter`] to avoid any kind of -/// hyphenation: -/// -/// ``` -/// use textwrap::{Wrapper, NoHyphenation}; -/// -/// let wrapper = Wrapper::with_splitter(8, NoHyphenation); -/// assert_eq!(wrapper.wrap("foo bar-baz"), vec!["foo", "bar-baz"]); -/// ``` -/// -/// [`Wrapper.splitter`]: struct.Wrapper.html#structfield.splitter -#[derive(Clone, Debug)] -pub struct NoHyphenation; - -/// `NoHyphenation` implements `WordSplitter` by not splitting the -/// word at all. -impl WordSplitter for NoHyphenation { - fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { - vec![(word, "", "")] - } -} - -/// Simple and default way to split words: splitting on existing -/// hyphens only. -/// -/// You probably don't need to use this type since it's already used -/// by default by `Wrapper::new`. -#[derive(Clone, Debug)] -pub struct HyphenSplitter; - -/// `HyphenSplitter` is the default `WordSplitter` used by -/// `Wrapper::new`. It will split words on any existing hyphens in the -/// word. -/// -/// It will only use hyphens that are surrounded by alphanumeric -/// characters, which prevents a word like "--foo-bar" from being -/// split on the first or second hyphen. -impl WordSplitter for HyphenSplitter { - fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { - let mut triples = Vec::new(); - // Split on hyphens, smallest split first. We only use hyphens - // that are surrounded by alphanumeric characters. This is to - // avoid splitting on repeated hyphens, such as those found in - // --foo-bar. - let mut char_indices = word.char_indices(); - // Early return if the word is empty. - let mut prev = match char_indices.next() { - None => return vec![(word, "", "")], - Some((_, ch)) => ch, - }; - - // Find current word, or return early if the word only has a - // single character. - let (mut idx, mut cur) = match char_indices.next() { - None => return vec![(word, "", "")], - Some((idx, cur)) => (idx, cur), - }; - - for (i, next) in char_indices { - if prev.is_alphanumeric() && cur == '-' && next.is_alphanumeric() { - let (head, tail) = word.split_at(idx + 1); - triples.push((head, "", tail)); - } - prev = cur; - idx = i; - cur = next; - } - - // Finally option is no split at all. - triples.push((word, "", "")); - - triples - } -} - -/// A hyphenation Corpus can be used to do language-specific -/// hyphenation using patterns from the hyphenation crate. -#[cfg(feature = "hyphenation")] -impl WordSplitter for Corpus { - fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { - // Find splits based on language corpus. - let mut triples = Vec::new(); - for n in word.opportunities(self) { - let (head, tail) = word.split_at(n); - let hyphen = if head.ends_with('-') { "" } else { "-" }; - triples.push((head, hyphen, tail)); - } - // Finally option is no split at all. - triples.push((word, "", "")); +mod indentation; +pub use indentation::dedent; +pub use indentation::indent; - triples - } -} +mod splitting; +pub use splitting::{HyphenSplitter, NoHyphenation, WordSplitter}; /// A Wrapper holds settings for wrapping and filling text. Use it /// when the convenience [`wrap_iter`], [`wrap`] and [`fill`] functions @@ -218,8 +93,8 @@ pub struct Wrapper<'a, S: WordSplitter> { /// `self.width`. pub break_words: bool, /// The method for splitting words. If the `hyphenation` feature - /// is enabled, you can use a `hyphenation::language::Corpus` here - /// to get language-aware hyphenation. + /// is enabled, you can use a `hyphenation::Standard` dictionary + /// here to get language-aware hyphenation. pub splitter: S, } @@ -255,7 +130,7 @@ impl<'a> Wrapper<'a, HyphenSplitter> { } } -impl<'w, 'a: 'w, S: WordSplitter> Wrapper<'a, S> { +impl<'a, S: WordSplitter> Wrapper<'a, S> { /// Use the given [`WordSplitter`] to create a new Wrapper for /// wrapping at the specified width. By default, we allow words /// longer than `width` to be broken. @@ -453,7 +328,7 @@ impl<'w, 'a: 'w, S: WordSplitter> Wrapper<'a, S> { /// [`self.splitter`]: #structfield.splitter /// [`WordSplitter`]: trait.WordSplitter.html /// [`WrapIter`]: struct.WrapIter.html - pub fn wrap_iter(&'w self, s: &'a str) -> WrapIter<'w, 'a, S> { + pub fn wrap_iter<'w>(&'w self, s: &'a str) -> WrapIter<'w, 'a, S> { WrapIter { wrapper: self, inner: WrapIterImpl::new(self, s), @@ -824,121 +699,6 @@ pub fn wrap_iter(s: &str, width: usize) -> IntoWrapIter { Wrapper::new(width).into_wrap_iter(s) } -/// Add prefix to each non-empty line. -/// -/// ``` -/// use textwrap::indent; -/// -/// assert_eq!(indent(" -/// Foo -/// Bar -/// ", " "), " -/// Foo -/// Bar -/// "); -/// ``` -/// -/// Empty lines (lines consisting only of whitespace) are not indented -/// and the whitespace is replaced by a single newline (`\n`): -/// -/// ``` -/// use textwrap::indent; -/// -/// assert_eq!(indent(" -/// Foo -/// -/// Bar -/// \t -/// Baz -/// ", "->"), " -/// ->Foo -/// -/// ->Bar -/// -/// ->Baz -/// "); -/// ``` -/// -/// Leading and trailing whitespace on non-empty lines is kept -/// unchanged: -/// -/// ``` -/// use textwrap::indent; -/// -/// assert_eq!(indent(" \t Foo ", "->"), "-> \t Foo \n"); -/// ``` -pub fn indent(s: &str, prefix: &str) -> String { - let mut result = String::new(); - for line in s.lines() { - if line.chars().any(|c| !c.is_whitespace()) { - result.push_str(prefix); - result.push_str(line); - } - result.push('\n'); - } - result -} - -/// Removes common leading whitespace from each line. -/// -/// This function will look at each non-empty line and determine the -/// maximum amount of whitespace that can be removed from all lines: -/// -/// ``` -/// use textwrap::dedent; -/// -/// assert_eq!(dedent(" -/// 1st line -/// 2nd line -/// 3rd line -/// "), " -/// 1st line -/// 2nd line -/// 3rd line -/// "); -/// ``` -pub fn dedent(s: &str) -> String { - let mut prefix = String::new(); - let mut lines = s.lines(); - - // We first search for a non-empty line to find a prefix. - for line in &mut lines { - let whitespace = line.chars() - .take_while(|c| c.is_whitespace()) - .collect::(); - // Check if the line had anything but whitespace - if whitespace.len() < line.len() { - prefix = whitespace; - break; - } - } - - // We then continue looking through the remaining lines to - // possibly shorten the prefix. - for line in &mut lines { - let whitespace = line.chars() - .zip(prefix.chars()) - .take_while(|&(a, b)| a == b) - .map(|(_, b)| b) - .collect::(); - // Check if we have found a shorter prefix - if whitespace.len() < prefix.len() { - prefix = whitespace; - } - } - - // We now go over the lines a second time to build the result. - let mut result = String::new(); - for line in s.lines() { - if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) { - let (_, tail) = line.split_at(prefix.len()); - result.push_str(tail); - } - result.push('\n'); - } - result -} - #[cfg(test)] mod tests { #[cfg(feature = "hyphenation")] @@ -946,13 +706,7 @@ mod tests { use super::*; #[cfg(feature = "hyphenation")] - use hyphenation::Language; - - /// Add newlines. Ensures that the final line in the vector also - /// has a newline. - fn add_nl(lines: &[&str]) -> String { - lines.join("\n") + "\n" - } + use hyphenation::{Language, Load, Standard}; #[test] fn no_wrap() { @@ -1120,14 +874,14 @@ mod tests { #[test] #[cfg(feature = "hyphenation")] fn auto_hyphenation() { - let corpus = hyphenation::load(Language::English_US).unwrap(); + let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); let wrapper = Wrapper::new(10); assert_eq!( wrapper.wrap("Internationalization"), vec!["Internatio", "nalization"] ); - let wrapper = Wrapper::with_splitter(10, corpus); + let wrapper = Wrapper::with_splitter(10, dictionary); assert_eq!( wrapper.wrap("Internationalization"), vec!["Interna-", "tionaliza-", "tion"] @@ -1139,8 +893,8 @@ mod tests { fn split_len_hyphenation() { // Test that hyphenation takes the width of the wihtespace // into account. - let corpus = hyphenation::load(Language::English_US).unwrap(); - let wrapper = Wrapper::with_splitter(15, corpus); + let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); + let wrapper = Wrapper::with_splitter(15, dictionary); assert_eq!( wrapper.wrap("garbage collection"), vec!["garbage col-", "lection"] @@ -1153,8 +907,8 @@ mod tests { // Lines that end with an extra hyphen are owned, the final // line is borrowed. use std::borrow::Cow::{Borrowed, Owned}; - let corpus = hyphenation::load(Language::English_US).unwrap(); - let wrapper = Wrapper::with_splitter(10, corpus); + let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); + let wrapper = Wrapper::with_splitter(10, dictionary); let lines = wrapper.wrap("Internationalization"); if let Borrowed(s) = lines[0] { assert!(false, "should not have been borrowed: {:?}", s); @@ -1170,11 +924,11 @@ mod tests { #[test] #[cfg(feature = "hyphenation")] fn auto_hyphenation_with_hyphen() { - let corpus = hyphenation::load(Language::English_US).unwrap(); + let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); let wrapper = Wrapper::new(8).break_words(false); assert_eq!(wrapper.wrap("over-caffinated"), vec!["over-", "caffinated"]); - let wrapper = Wrapper::with_splitter(8, corpus).break_words(false); + let wrapper = Wrapper::with_splitter(8, dictionary).break_words(false); assert_eq!( wrapper.wrap("over-caffinated"), vec!["over-", "caffi-", "nated"] @@ -1230,76 +984,4 @@ mod tests { fn fill_simple() { assert_eq!(fill("foo bar baz", 10), "foo bar\nbaz"); } - - #[test] - fn indent_empty() { - assert_eq!(indent("\n", " "), "\n"); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn indent_nonempty() { - let x = vec![" foo", - "bar", - " baz"]; - let y = vec!["// foo", - "//bar", - "// baz"]; - assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y)); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn indent_empty_line() { - let x = vec![" foo", - "bar", - "", - " baz"]; - let y = vec!["// foo", - "//bar", - "", - "// baz"]; - assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y)); - } - - #[test] - fn dedent_empty() { - assert_eq!(dedent(""), ""); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn dedent_multi_line() { - let x = vec![" foo", - " bar", - " baz"]; - let y = vec![" foo", - "bar", - " baz"]; - assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn dedent_empty_line() { - let x = vec![" foo", - " bar", - " ", - " baz"]; - let y = vec![" foo", - "bar", - "", - " baz"]; - assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn dedent_mixed_whitespace() { - let x = vec!["\tfoo", - " bar"]; - let y = vec!["\tfoo", - " bar"]; - assert_eq!(dedent(&add_nl(&x)), add_nl(&y)); - } } diff --git a/vendor/textwrap/src/splitting.rs b/vendor/textwrap/src/splitting.rs new file mode 100644 index 0000000000..f6b65afda1 --- /dev/null +++ b/vendor/textwrap/src/splitting.rs @@ -0,0 +1,139 @@ +//! Word splitting functionality. +//! +//! To wrap text into lines, long words sometimes need to be split +//! across lines. The [`WordSplitter`] trait defines this +//! functionality. [`HyphenSplitter`] is the default implementation of +//! this treat: it will simply split words on existing hyphens. + +#[cfg(feature = "hyphenation")] +use hyphenation::{Hyphenator, Standard}; + +/// An interface for splitting words. +/// +/// When the [`wrap_iter`] method will try to fit text into a line, it +/// will eventually find a word that it too large the current text +/// width. It will then call the currently configured `WordSplitter` to +/// have it attempt to split the word into smaller parts. This trait +/// describes that functionality via the [`split`] method. +/// +/// If the `textwrap` crate has been compiled with the `hyphenation` +/// feature enabled, you will find an implementation of `WordSplitter` +/// by the `hyphenation::language::Corpus` struct. Use this struct for +/// language-aware hyphenation. See the [`hyphenation` documentation] +/// for details. +/// +/// [`wrap_iter`]: ../struct.Wrapper.html#method.wrap_iter +/// [`split`]: #tymethod.split +/// [`hyphenation` documentation]: https://docs.rs/hyphenation/ +pub trait WordSplitter { + /// Return all possible splits of word. Each split is a triple + /// with a head, a hyphen, and a tail where `head + &hyphen + + /// &tail == word`. The hyphen can be empty if there is already a + /// hyphen in the head. + /// + /// The splits should go from smallest to longest and should + /// include no split at all. So the word "technology" could be + /// split into + /// + /// ```no_run + /// vec![("tech", "-", "nology"), + /// ("technol", "-", "ogy"), + /// ("technolo", "-", "gy"), + /// ("technology", "", "")]; + /// ``` + fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)>; +} + +/// Use this as a [`Wrapper.splitter`] to avoid any kind of +/// hyphenation: +/// +/// ``` +/// use textwrap::{Wrapper, NoHyphenation}; +/// +/// let wrapper = Wrapper::with_splitter(8, NoHyphenation); +/// assert_eq!(wrapper.wrap("foo bar-baz"), vec!["foo", "bar-baz"]); +/// ``` +/// +/// [`Wrapper.splitter`]: ../struct.Wrapper.html#structfield.splitter +#[derive(Clone, Debug)] +pub struct NoHyphenation; + +/// `NoHyphenation` implements `WordSplitter` by not splitting the +/// word at all. +impl WordSplitter for NoHyphenation { + fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { + vec![(word, "", "")] + } +} + +/// Simple and default way to split words: splitting on existing +/// hyphens only. +/// +/// You probably don't need to use this type since it's already used +/// by default by `Wrapper::new`. +#[derive(Clone, Debug)] +pub struct HyphenSplitter; + +/// `HyphenSplitter` is the default `WordSplitter` used by +/// `Wrapper::new`. It will split words on any existing hyphens in the +/// word. +/// +/// It will only use hyphens that are surrounded by alphanumeric +/// characters, which prevents a word like "--foo-bar" from being +/// split on the first or second hyphen. +impl WordSplitter for HyphenSplitter { + fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { + let mut triples = Vec::new(); + // Split on hyphens, smallest split first. We only use hyphens + // that are surrounded by alphanumeric characters. This is to + // avoid splitting on repeated hyphens, such as those found in + // --foo-bar. + let mut char_indices = word.char_indices(); + // Early return if the word is empty. + let mut prev = match char_indices.next() { + None => return vec![(word, "", "")], + Some((_, ch)) => ch, + }; + + // Find current word, or return early if the word only has a + // single character. + let (mut idx, mut cur) = match char_indices.next() { + None => return vec![(word, "", "")], + Some((idx, cur)) => (idx, cur), + }; + + for (i, next) in char_indices { + if prev.is_alphanumeric() && cur == '-' && next.is_alphanumeric() { + let (head, tail) = word.split_at(idx + 1); + triples.push((head, "", tail)); + } + prev = cur; + idx = i; + cur = next; + } + + // Finally option is no split at all. + triples.push((word, "", "")); + + triples + } +} + +/// A hyphenation dictionary can be used to do language-specific +/// hyphenation using patterns from the hyphenation crate. +#[cfg(feature = "hyphenation")] +impl WordSplitter for Standard { + fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> { + // Find splits based on language dictionary. + let mut triples = Vec::new(); + for n in self.hyphenate(word).breaks { + let (head, tail) = word.split_at(n); + let hyphen = if head.ends_with('-') { "" } else { "-" }; + triples.push((head, hyphen, tail)); + } + // Finally option is no split at all. + triples.push((word, "", "")); + + triples + } +} diff --git a/vendor/textwrap/tests/version-numbers.rs b/vendor/textwrap/tests/version-numbers.rs index 411eea548e..85c52e372f 100644 --- a/vendor/textwrap/tests/version-numbers.rs +++ b/vendor/textwrap/tests/version-numbers.rs @@ -6,6 +6,11 @@ fn test_readme_deps() { assert_markdown_deps_updated!("README.md"); } +#[test] +fn test_readme_changelog() { + assert_contains_regex!("README.md", r"^### Version {version} — .* \d\d?.., 20\d\d$"); +} + #[test] fn test_html_root_url() { assert_html_root_url_updated!("src/lib.rs"); diff --git a/vendor/toml-0.4.10/.cargo-checksum.json b/vendor/toml-0.4.10/.cargo-checksum.json deleted file mode 100644 index b3aef7c271..0000000000 --- a/vendor/toml-0.4.10/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"9c2e60c7837a07dd06e24f1f33b5d95367b976d88dad80aa5527b82cdcd30897","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ec3fb1fd502c4137d7d2e88dd66f5843e78c5f57a3061e78093484e366c9d715","examples/decode.rs":"15eb011e0579f35e6960638151d215123b21d8236a6284169240f09a28efe5d1","examples/enum_external.rs":"e34b78d3c844aa87ad8f13deb9000993802d13d4e07b4b3a0c59000969d8e96d","examples/toml2json.rs":"eaa9ad85ec19714f6437048ae28b844966225a17055d1a37878f41bcbc2c5e47","src/datetime.rs":"167d2629cc5a1d640d72ac71eeace7370be99f4899054976b8e60ffa9b074815","src/de.rs":"f0255f32c4166e9583bb8492aa984ee0fe050d5bdf3c3d106966ad8e8f7c30ce","src/lib.rs":"af586efcc5380efa3c24c32dc14c5462277885bf6369294812f4be1262d2f3b5","src/macros.rs":"f30755f9dbb2b754a77d2777689e1cf90d7ae38c99826b2250940b2a5fea81dd","src/ser.rs":"d51e0eff1f434b2914a7d06845f5f309b35b0ad5a76b1e2c1932025b1edf42e2","src/spanned.rs":"4b6d501c5fad1621ff4163ed5f0a986211a7c20389158b4b67a2e1697bc8f58e","src/tokens.rs":"e8bb370427c9a13f54420308efbbfe5af5f70c66390f4c5895fc9a992bf9ce5c","src/value.rs":"321adb3697c534c6f48bf84a230e84737fb00931f7ee37ca9fd0f67bae31011b","tests/enum_external_deserialize.rs":"acacf03802a68508559c772882577711397bad4a1354248e9c84860752eb19e9"},"package":"758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"} \ No newline at end of file diff --git a/vendor/toml-0.4.10/Cargo.toml b/vendor/toml-0.4.10/Cargo.toml deleted file mode 100644 index 6e5462128d..0000000000 --- a/vendor/toml-0.4.10/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "toml" -version = "0.4.10" -authors = ["Alex Crichton "] -description = "A native Rust encoder and decoder of TOML-formatted files and streams. Provides\nimplementations of the standard Serialize/Deserialize traits for TOML data to\nfacilitate deserializing and serializing Rust structures.\n" -homepage = "https://github.com/alexcrichton/toml-rs" -documentation = "https://docs.rs/toml" -readme = "README.md" -keywords = ["encoding"] -categories = ["config", "encoding", "parser-implementations"] -license = "MIT/Apache-2.0" -repository = "https://github.com/alexcrichton/toml-rs" -[dependencies.serde] -version = "1.0" -[dev-dependencies.serde_derive] -version = "1.0" - -[dev-dependencies.serde_json] -version = "1.0" -[badges.travis-ci] -repository = "alexcrichton/toml-rs" diff --git a/vendor/toml-0.4.10/README.md b/vendor/toml-0.4.10/README.md deleted file mode 100644 index 6424c1fe6f..0000000000 --- a/vendor/toml-0.4.10/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# toml-rs - -[![Build Status](https://travis-ci.org/alexcrichton/toml-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/toml-rs) -[![Coverage Status](https://coveralls.io/repos/alexcrichton/toml-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/alexcrichton/toml-rs?branch=master) -[![Latest Version](https://img.shields.io/crates/v/toml.svg)](https://crates.io/crates/toml) -[![Documentation](https://docs.rs/toml/badge.svg)](https://docs.rs/toml) - -A [TOML][toml] decoder and encoder for Rust. This library is currently compliant -with the v0.5.0 version of TOML. This library will also likely continue to stay -up to date with the TOML specification as changes happen. - -[toml]: https://github.com/toml-lang/toml - -```toml -# Cargo.toml -[dependencies] -toml = "0.4" -``` - -This crate also supports serialization/deserialization through the -[serde](https://serde.rs) crate on crates.io. Currently the older `rustc-serialize` -crate is not supported in the 0.3+ series of the `toml` crate, but 0.2 can be -used for that support. - -# License - -This project is licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in toml-rs by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. diff --git a/vendor/toml-0.4.10/examples/decode.rs b/vendor/toml-0.4.10/examples/decode.rs deleted file mode 100644 index e8ce586113..0000000000 --- a/vendor/toml-0.4.10/examples/decode.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! An example showing off the usage of `Deserialize` to automatically decode -//! TOML into a Rust `struct` - -#![deny(warnings)] - -extern crate toml; -#[macro_use] -extern crate serde_derive; - -/// This is what we're going to decode into. Each field is optional, meaning -/// that it doesn't have to be present in TOML. -#[derive(Debug, Deserialize)] -struct Config { - global_string: Option, - global_integer: Option, - server: Option, - peers: Option>, -} - -/// Sub-structs are decoded from tables, so this will decode from the `[server]` -/// table. -/// -/// Again, each field is optional, meaning they don't have to be present. -#[derive(Debug, Deserialize)] -struct ServerConfig { - ip: Option, - port: Option, -} - -#[derive(Debug, Deserialize)] -struct PeerConfig { - ip: Option, - port: Option, -} - -fn main() { - let toml_str = r#" - global_string = "test" - global_integer = 5 - - [server] - ip = "127.0.0.1" - port = 80 - - [[peers]] - ip = "127.0.0.1" - port = 8080 - - [[peers]] - ip = "127.0.0.1" - "#; - - let decoded: Config = toml::from_str(toml_str).unwrap(); - println!("{:#?}", decoded); -} diff --git a/vendor/toml-0.4.10/examples/enum_external.rs b/vendor/toml-0.4.10/examples/enum_external.rs deleted file mode 100644 index e2ac4f8e72..0000000000 --- a/vendor/toml-0.4.10/examples/enum_external.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! An example showing off the usage of `Deserialize` to automatically decode -//! TOML into a Rust `struct`, with enums. - -#![deny(warnings)] - -extern crate toml; -#[macro_use] -extern crate serde_derive; - -/// This is what we're going to decode into. -#[derive(Debug, Deserialize)] -struct Config { - plain: MyEnum, - plain_table: MyEnum, - tuple: MyEnum, - #[serde(rename = "struct")] - structv: MyEnum, - newtype: MyEnum, - my_enum: Vec, -} - -#[derive(Debug, Deserialize)] -enum MyEnum { - Plain, - Tuple(i64, bool), - NewType(String), - Struct { value: i64 }, -} - -fn main() { - let toml_str = r#" - plain = "Plain" - plain_table = { Plain = {} } - tuple = { Tuple = { 0 = 123, 1 = true } } - struct = { Struct = { value = 123 } } - newtype = { NewType = "value" } - my_enum = [ - { Plain = {} }, - { Tuple = { 0 = 123, 1 = true } }, - { NewType = "value" }, - { Struct = { value = 123 } } - ]"#; - - let decoded: Config = toml::from_str(toml_str).unwrap(); - println!("{:#?}", decoded); -} diff --git a/vendor/toml-0.4.10/examples/toml2json.rs b/vendor/toml-0.4.10/examples/toml2json.rs deleted file mode 100644 index 1ed441a93a..0000000000 --- a/vendor/toml-0.4.10/examples/toml2json.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![deny(warnings)] - -extern crate toml; -extern crate serde_json; - -use std::fs::File; -use std::env; -use std::io; -use std::io::prelude::*; - -use toml::Value as Toml; -use serde_json::Value as Json; - -fn main() { - let mut args = env::args(); - let mut input = String::new(); - if args.len() > 1 { - let name = args.nth(1).unwrap(); - File::open(&name).and_then(|mut f| { - f.read_to_string(&mut input) - }).unwrap(); - } else { - io::stdin().read_to_string(&mut input).unwrap(); - } - - match input.parse() { - Ok(toml) => { - let json = convert(toml); - println!("{}", serde_json::to_string_pretty(&json).unwrap()); - } - Err(error) => println!("failed to parse TOML: {}", error), - } -} - -fn convert(toml: Toml) -> Json { - match toml { - Toml::String(s) => Json::String(s), - Toml::Integer(i) => Json::Number(i.into()), - Toml::Float(f) => { - let n = serde_json::Number::from_f64(f) - .expect("float infinite and nan not allowed"); - Json::Number(n) - } - Toml::Boolean(b) => Json::Bool(b), - Toml::Array(arr) => Json::Array(arr.into_iter().map(convert).collect()), - Toml::Table(table) => Json::Object(table.into_iter().map(|(k, v)| { - (k, convert(v)) - }).collect()), - Toml::Datetime(dt) => Json::String(dt.to_string()), - } -} diff --git a/vendor/toml-0.4.10/src/datetime.rs b/vendor/toml-0.4.10/src/datetime.rs deleted file mode 100644 index 3678f582a2..0000000000 --- a/vendor/toml-0.4.10/src/datetime.rs +++ /dev/null @@ -1,424 +0,0 @@ -use std::fmt; -use std::str::{self, FromStr}; -use std::error; - -use serde::{de, ser}; - -/// A parsed TOML datetime value -/// -/// This structure is intended to represent the datetime primitive type that can -/// be encoded into TOML documents. This type is a parsed version that contains -/// all metadata internally. -/// -/// Currently this type is intentionally conservative and only supports -/// `to_string` as an accessor. Over time though it's intended that it'll grow -/// more support! -/// -/// Note that if you're using `Deserialize` to deserialize a TOML document, you -/// can use this as a placeholder for where you're expecting a datetime to be -/// specified. -/// -/// Also note though that while this type implements `Serialize` and -/// `Deserialize` it's only recommended to use this type with the TOML format, -/// otherwise encoded in other formats it may look a little odd. -#[derive(PartialEq, Clone)] -pub struct Datetime { - date: Option, - time: Option